@@ -113,6 +113,260 @@ fn adt_destructor(tcx: TyCtxt<'_>, def_id: DefId) -> Option<ty::Destructor> {
113
113
tcx. calculate_dtor ( def_id, dropck:: check_drop_impl)
114
114
}
115
115
116
+ /// If this `DefId` is a "primary tables entry", returns
117
+ /// `Some((body_id, body_ty, fn_sig))`. Otherwise, returns `None`.
118
+ ///
119
+ /// If this function returns `Some`, then `typeck_results(def_id)` will
120
+ /// succeed; if it returns `None`, then `typeck_results(def_id)` may or
121
+ /// may not succeed. In some cases where this function returns `None`
122
+ /// (notably closures), `typeck_results(def_id)` would wind up
123
+ /// redirecting to the owning function.
124
+ fn primary_body_of (
125
+ tcx : TyCtxt < ' _ > ,
126
+ id : hir:: HirId ,
127
+ ) -> Option < ( hir:: BodyId , Option < & hir:: Ty < ' _ > > , Option < & hir:: FnSig < ' _ > > ) > {
128
+ match tcx. hir ( ) . get ( id) {
129
+ Node :: Item ( item) => match item. kind {
130
+ hir:: ItemKind :: Const ( ty, body) | hir:: ItemKind :: Static ( ty, _, body) => {
131
+ Some ( ( body, Some ( ty) , None ) )
132
+ }
133
+ hir:: ItemKind :: Fn ( ref sig, .., body) => Some ( ( body, None , Some ( sig) ) ) ,
134
+ _ => None ,
135
+ } ,
136
+ Node :: TraitItem ( item) => match item. kind {
137
+ hir:: TraitItemKind :: Const ( ty, Some ( body) ) => Some ( ( body, Some ( ty) , None ) ) ,
138
+ hir:: TraitItemKind :: Fn ( ref sig, hir:: TraitFn :: Provided ( body) ) => {
139
+ Some ( ( body, None , Some ( sig) ) )
140
+ }
141
+ _ => None ,
142
+ } ,
143
+ Node :: ImplItem ( item) => match item. kind {
144
+ hir:: ImplItemKind :: Const ( ty, body) => Some ( ( body, Some ( ty) , None ) ) ,
145
+ hir:: ImplItemKind :: Fn ( ref sig, body) => Some ( ( body, None , Some ( sig) ) ) ,
146
+ _ => None ,
147
+ } ,
148
+ Node :: AnonConst ( constant) => Some ( ( constant. body , None , None ) ) ,
149
+ _ => None ,
150
+ }
151
+ }
152
+
153
+ fn has_typeck_results ( tcx : TyCtxt < ' _ > , def_id : DefId ) -> bool {
154
+ // Closures' typeck results come from their outermost function,
155
+ // as they are part of the same "inference environment".
156
+ let typeck_root_def_id = tcx. typeck_root_def_id ( def_id) ;
157
+ if typeck_root_def_id != def_id {
158
+ return tcx. has_typeck_results ( typeck_root_def_id) ;
159
+ }
160
+
161
+ if let Some ( def_id) = def_id. as_local ( ) {
162
+ let id = tcx. hir ( ) . local_def_id_to_hir_id ( def_id) ;
163
+ primary_body_of ( tcx, id) . is_some ( )
164
+ } else {
165
+ false
166
+ }
167
+ }
168
+
169
+ fn used_trait_imports ( tcx : TyCtxt < ' _ > , def_id : LocalDefId ) -> & FxHashSet < LocalDefId > {
170
+ & * tcx. typeck ( def_id) . used_trait_imports
171
+ }
172
+
173
+ fn typeck_const_arg < ' tcx > (
174
+ tcx : TyCtxt < ' tcx > ,
175
+ ( did, param_did) : ( LocalDefId , DefId ) ,
176
+ ) -> & ty:: TypeckResults < ' tcx > {
177
+ let fallback = move || tcx. type_of ( param_did) ;
178
+ typeck_with_fallback ( tcx, did, fallback)
179
+ }
180
+
181
+ fn typeck < ' tcx > ( tcx : TyCtxt < ' tcx > , def_id : LocalDefId ) -> & ty:: TypeckResults < ' tcx > {
182
+ if let Some ( param_did) = tcx. opt_const_param_of ( def_id) {
183
+ tcx. typeck_const_arg ( ( def_id, param_did) )
184
+ } else {
185
+ let fallback = move || tcx. type_of ( def_id. to_def_id ( ) ) ;
186
+ typeck_with_fallback ( tcx, def_id, fallback)
187
+ }
188
+ }
189
+
190
+ /// Used only to get `TypeckResults` for type inference during error recovery.
191
+ /// Currently only used for type inference of `static`s and `const`s to avoid type cycle errors.
192
+ fn diagnostic_only_typeck < ' tcx > ( tcx : TyCtxt < ' tcx > , def_id : LocalDefId ) -> & ty:: TypeckResults < ' tcx > {
193
+ let fallback = move || {
194
+ let span = tcx. hir ( ) . span ( tcx. hir ( ) . local_def_id_to_hir_id ( def_id) ) ;
195
+ tcx. ty_error_with_message ( span, "diagnostic only typeck table used" )
196
+ } ;
197
+ typeck_with_fallback ( tcx, def_id, fallback)
198
+ }
199
+
200
+ fn typeck_with_fallback < ' tcx > (
201
+ tcx : TyCtxt < ' tcx > ,
202
+ def_id : LocalDefId ,
203
+ fallback : impl Fn ( ) -> Ty < ' tcx > + ' tcx ,
204
+ ) -> & ' tcx ty:: TypeckResults < ' tcx > {
205
+ // Closures' typeck results come from their outermost function,
206
+ // as they are part of the same "inference environment".
207
+ let typeck_root_def_id = tcx. typeck_root_def_id ( def_id. to_def_id ( ) ) . expect_local ( ) ;
208
+ if typeck_root_def_id != def_id {
209
+ return tcx. typeck ( typeck_root_def_id) ;
210
+ }
211
+
212
+ let id = tcx. hir ( ) . local_def_id_to_hir_id ( def_id) ;
213
+ let span = tcx. hir ( ) . span ( id) ;
214
+
215
+ // Figure out what primary body this item has.
216
+ let ( body_id, body_ty, fn_sig) = primary_body_of ( tcx, id) . unwrap_or_else ( || {
217
+ span_bug ! ( span, "can't type-check body of {:?}" , def_id) ;
218
+ } ) ;
219
+ let body = tcx. hir ( ) . body ( body_id) ;
220
+
221
+ let typeck_results = Inherited :: build ( tcx, def_id) . enter ( |inh| {
222
+ let param_env = tcx. param_env ( def_id) ;
223
+ let mut fcx = if let Some ( hir:: FnSig { header, decl, .. } ) = fn_sig {
224
+ let fn_sig = if crate :: collect:: get_infer_ret_ty ( & decl. output ) . is_some ( ) {
225
+ let fcx = FnCtxt :: new ( & inh, param_env, body. value . hir_id ) ;
226
+ <dyn AstConv < ' _ > >:: ty_of_fn ( & fcx, id, header. unsafety , header. abi , decl, None , None )
227
+ } else {
228
+ tcx. fn_sig ( def_id)
229
+ } ;
230
+
231
+ check_abi ( tcx, id, span, fn_sig. abi ( ) ) ;
232
+
233
+ // Compute the function signature from point of view of inside the fn.
234
+ let fn_sig = tcx. liberate_late_bound_regions ( def_id. to_def_id ( ) , fn_sig) ;
235
+ let fn_sig = inh. normalize_associated_types_in (
236
+ body. value . span ,
237
+ body_id. hir_id ,
238
+ param_env,
239
+ fn_sig,
240
+ ) ;
241
+ check_fn ( & inh, param_env, fn_sig, decl, id, body, None , true ) . 0
242
+ } else {
243
+ let fcx = FnCtxt :: new ( & inh, param_env, body. value . hir_id ) ;
244
+ let expected_type = body_ty
245
+ . and_then ( |ty| match ty. kind {
246
+ hir:: TyKind :: Infer => Some ( <dyn AstConv < ' _ > >:: ast_ty_to_ty ( & fcx, ty) ) ,
247
+ _ => None ,
248
+ } )
249
+ . unwrap_or_else ( || match tcx. hir ( ) . get ( id) {
250
+ Node :: AnonConst ( _) => match tcx. hir ( ) . get ( tcx. hir ( ) . get_parent_node ( id) ) {
251
+ Node :: Expr ( & hir:: Expr {
252
+ kind : hir:: ExprKind :: ConstBlock ( ref anon_const) ,
253
+ ..
254
+ } ) if anon_const. hir_id == id => fcx. next_ty_var ( TypeVariableOrigin {
255
+ kind : TypeVariableOriginKind :: TypeInference ,
256
+ span,
257
+ } ) ,
258
+ Node :: Ty ( & hir:: Ty {
259
+ kind : hir:: TyKind :: Typeof ( ref anon_const) , ..
260
+ } ) if anon_const. hir_id == id => fcx. next_ty_var ( TypeVariableOrigin {
261
+ kind : TypeVariableOriginKind :: TypeInference ,
262
+ span,
263
+ } ) ,
264
+ Node :: Expr ( & hir:: Expr { kind : hir:: ExprKind :: InlineAsm ( asm) , .. } )
265
+ | Node :: Item ( & hir:: Item { kind : hir:: ItemKind :: GlobalAsm ( asm) , .. } ) => {
266
+ let operand_ty = asm
267
+ . operands
268
+ . iter ( )
269
+ . filter_map ( |( op, _op_sp) | match op {
270
+ hir:: InlineAsmOperand :: Const { anon_const }
271
+ if anon_const. hir_id == id =>
272
+ {
273
+ // Inline assembly constants must be integers.
274
+ Some ( fcx. next_int_var ( ) )
275
+ }
276
+ hir:: InlineAsmOperand :: SymFn { anon_const }
277
+ if anon_const. hir_id == id =>
278
+ {
279
+ Some ( fcx. next_ty_var ( TypeVariableOrigin {
280
+ kind : TypeVariableOriginKind :: MiscVariable ,
281
+ span,
282
+ } ) )
283
+ }
284
+ _ => None ,
285
+ } )
286
+ . next ( ) ;
287
+ operand_ty. unwrap_or_else ( fallback)
288
+ }
289
+ _ => fallback ( ) ,
290
+ } ,
291
+ _ => fallback ( ) ,
292
+ } ) ;
293
+
294
+ let expected_type = fcx. normalize_associated_types_in ( body. value . span , expected_type) ;
295
+ fcx. require_type_is_sized ( expected_type, body. value . span , traits:: ConstSized ) ;
296
+
297
+ // Gather locals in statics (because of block expressions).
298
+ GatherLocalsVisitor :: new ( & fcx) . visit_body ( body) ;
299
+
300
+ fcx. check_expr_coercable_to_type ( & body. value , expected_type, None ) ;
301
+
302
+ fcx. write_ty ( id, expected_type) ;
303
+
304
+ fcx
305
+ } ;
306
+
307
+ let fallback_has_occurred = fcx. type_inference_fallback ( ) ;
308
+
309
+ // Even though coercion casts provide type hints, we check casts after fallback for
310
+ // backwards compatibility. This makes fallback a stronger type hint than a cast coercion.
311
+ fcx. check_casts ( ) ;
312
+ fcx. select_obligations_where_possible ( fallback_has_occurred, |_| { } ) ;
313
+
314
+ // Closure and generator analysis may run after fallback
315
+ // because they don't constrain other type variables.
316
+ // Closure analysis only runs on closures. Therefore they only need to fulfill non-const predicates (as of now)
317
+ let prev_constness = fcx. param_env . constness ( ) ;
318
+ fcx. param_env = fcx. param_env . without_const ( ) ;
319
+ fcx. closure_analyze ( body) ;
320
+ fcx. param_env = fcx. param_env . with_constness ( prev_constness) ;
321
+ assert ! ( fcx. deferred_call_resolutions. borrow( ) . is_empty( ) ) ;
322
+ // Before the generator analysis, temporary scopes shall be marked to provide more
323
+ // precise information on types to be captured.
324
+ fcx. resolve_rvalue_scopes ( def_id. to_def_id ( ) ) ;
325
+ fcx. resolve_generator_interiors ( def_id. to_def_id ( ) ) ;
326
+
327
+ for ( ty, span, code) in fcx. deferred_sized_obligations . borrow_mut ( ) . drain ( ..) {
328
+ let ty = fcx. normalize_ty ( span, ty) ;
329
+ fcx. require_type_is_sized ( ty, span, code) ;
330
+ }
331
+
332
+ fcx. resolve_base_expr ( ) ;
333
+
334
+ fcx. select_all_obligations_or_error ( ) ;
335
+
336
+ if !fcx. infcx . is_tainted_by_errors ( ) {
337
+ fcx. check_transmutes ( ) ;
338
+ }
339
+
340
+ fcx. check_asms ( ) ;
341
+
342
+ fcx. infcx . skip_region_resolution ( ) ;
343
+
344
+ fcx. resolve_type_vars_in_body ( body)
345
+ } ) ;
346
+
347
+ // Consistency check our TypeckResults instance can hold all ItemLocalIds
348
+ // it will need to hold.
349
+ assert_eq ! ( typeck_results. hir_owner, id. owner) ;
350
+
351
+ typeck_results
352
+ }
353
+
354
+ /// When `check_fn` is invoked on a generator (i.e., a body that
355
+ /// includes yield), it returns back some information about the yield
356
+ /// points.
357
+ struct GeneratorTypes < ' tcx > {
358
+ /// Type of generator argument / values returned by `yield`.
359
+ resume_ty : Ty < ' tcx > ,
360
+
361
+ /// Type of value that is yielded.
362
+ yield_ty : Ty < ' tcx > ,
363
+
364
+ /// Types that are captured (see `GeneratorInterior` for more).
365
+ interior : Ty < ' tcx > ,
366
+
367
+ /// Indicates if the generator is movable or static (immovable).
368
+ movability : hir:: Movability ,
369
+ }
116
370
/// Given a `DefId` for an opaque type in return position, find its parent item's return
117
371
/// expressions.
118
372
fn get_owner_return_paths < ' tcx > (
0 commit comments