@@ -83,20 +83,6 @@ macro_rules! type_error_struct {
8383 } )
8484}
8585
86- /// If this `DefId` is a "primary tables entry", returns
87- /// `Some((body_id, body_ty, fn_sig))`. Otherwise, returns `None`.
88- ///
89- /// If this function returns `Some`, then `typeck_results(def_id)` will
90- /// succeed; if it returns `None`, then `typeck_results(def_id)` may or
91- /// may not succeed. In some cases where this function returns `None`
92- /// (notably closures), `typeck_results(def_id)` would wind up
93- /// redirecting to the owning function.
94- fn primary_body_of (
95- node : Node < ' _ > ,
96- ) -> Option < ( hir:: BodyId , Option < & hir:: Ty < ' _ > > , Option < & hir:: FnSig < ' _ > > ) > {
97- Some ( ( node. body_id ( ) ?, node. ty ( ) , node. fn_sig ( ) ) )
98- }
99-
10086fn has_typeck_results ( tcx : TyCtxt < ' _ > , def_id : DefId ) -> bool {
10187 // Closures' typeck results come from their outermost function,
10288 // as they are part of the same "inference environment".
@@ -106,7 +92,7 @@ fn has_typeck_results(tcx: TyCtxt<'_>, def_id: DefId) -> bool {
10692 }
10793
10894 if let Some ( def_id) = def_id. as_local ( ) {
109- primary_body_of ( tcx. hir_node_by_def_id ( def_id) ) . is_some ( )
95+ tcx. hir_node_by_def_id ( def_id) . body_id ( ) . is_some ( )
11096 } else {
11197 false
11298 }
@@ -163,7 +149,7 @@ fn typeck_with_fallback<'tcx>(
163149 let span = tcx. hir ( ) . span ( id) ;
164150
165151 // Figure out what primary body this item has.
166- let ( body_id, body_ty , fn_sig ) = primary_body_of ( node) . unwrap_or_else ( || {
152+ let body_id = node. body_id ( ) . unwrap_or_else ( || {
167153 span_bug ! ( span, "can't type-check body of {:?}" , def_id) ;
168154 } ) ;
169155 let body = tcx. hir ( ) . body ( body_id) ;
@@ -176,7 +162,7 @@ fn typeck_with_fallback<'tcx>(
176162 }
177163 let mut fcx = FnCtxt :: new ( & root_ctxt, param_env, def_id) ;
178164
179- if let Some ( hir:: FnSig { header, decl, .. } ) = fn_sig {
165+ if let Some ( hir:: FnSig { header, decl, .. } ) = node . fn_sig ( ) {
180166 let fn_sig = if decl. output . get_infer_ret_ty ( ) . is_some ( ) {
181167 fcx. lowerer ( ) . lower_fn_ty ( id, header. unsafety , header. abi , decl, None , None )
182168 } else {
@@ -191,42 +177,7 @@ fn typeck_with_fallback<'tcx>(
191177
192178 check_fn ( & mut fcx, fn_sig, None , decl, def_id, body, tcx. features ( ) . unsized_fn_params ) ;
193179 } else {
194- let expected_type = if let Some ( & hir:: Ty { kind : hir:: TyKind :: Infer , span, .. } ) = body_ty {
195- Some ( fcx. next_ty_var ( TypeVariableOrigin {
196- kind : TypeVariableOriginKind :: TypeInference ,
197- span,
198- } ) )
199- } else if let Node :: AnonConst ( _) = node {
200- match tcx. parent_hir_node ( id) {
201- Node :: Ty ( & hir:: Ty { kind : hir:: TyKind :: Typeof ( ref anon_const) , .. } )
202- if anon_const. hir_id == id =>
203- {
204- Some ( fcx. next_ty_var ( TypeVariableOrigin {
205- kind : TypeVariableOriginKind :: TypeInference ,
206- span,
207- } ) )
208- }
209- Node :: Expr ( & hir:: Expr { kind : hir:: ExprKind :: InlineAsm ( asm) , .. } )
210- | Node :: Item ( & hir:: Item { kind : hir:: ItemKind :: GlobalAsm ( asm) , .. } ) => {
211- asm. operands . iter ( ) . find_map ( |( op, _op_sp) | match op {
212- hir:: InlineAsmOperand :: Const { anon_const } if anon_const. hir_id == id => {
213- // Inline assembly constants must be integers.
214- Some ( fcx. next_int_var ( ) )
215- }
216- hir:: InlineAsmOperand :: SymFn { anon_const } if anon_const. hir_id == id => {
217- Some ( fcx. next_ty_var ( TypeVariableOrigin {
218- kind : TypeVariableOriginKind :: MiscVariable ,
219- span,
220- } ) )
221- }
222- _ => None ,
223- } )
224- }
225- _ => None ,
226- }
227- } else {
228- None
229- } ;
180+ let expected_type = infer_type_if_missing ( & fcx, node) ;
230181 let expected_type = expected_type. unwrap_or_else ( fallback) ;
231182
232183 let expected_type = fcx. normalize ( body. value . span , expected_type) ;
@@ -296,6 +247,59 @@ fn typeck_with_fallback<'tcx>(
296247 typeck_results
297248}
298249
250+ fn infer_type_if_missing < ' tcx > ( fcx : & FnCtxt < ' _ , ' tcx > , node : Node < ' tcx > ) -> Option < Ty < ' tcx > > {
251+ let tcx = fcx. tcx ;
252+ let def_id = fcx. body_id ;
253+ let expected_type = if let Some ( & hir:: Ty { kind : hir:: TyKind :: Infer , span, .. } ) = node. ty ( ) {
254+ if let Some ( item) = tcx. opt_associated_item ( def_id. into ( ) )
255+ && let ty:: AssocKind :: Const = item. kind
256+ && let ty:: ImplContainer = item. container
257+ && let Some ( trait_item) = item. trait_item_def_id
258+ {
259+ let args =
260+ tcx. impl_trait_ref ( item. container_id ( tcx) ) . unwrap ( ) . instantiate_identity ( ) . args ;
261+ Some ( tcx. type_of ( trait_item) . instantiate ( tcx, args) )
262+ } else {
263+ Some ( fcx. next_ty_var ( TypeVariableOrigin {
264+ kind : TypeVariableOriginKind :: TypeInference ,
265+ span,
266+ } ) )
267+ }
268+ } else if let Node :: AnonConst ( _) = node {
269+ let id = tcx. local_def_id_to_hir_id ( def_id) ;
270+ match tcx. parent_hir_node ( id) {
271+ Node :: Ty ( & hir:: Ty { kind : hir:: TyKind :: Typeof ( ref anon_const) , span, .. } )
272+ if anon_const. hir_id == id =>
273+ {
274+ Some ( fcx. next_ty_var ( TypeVariableOrigin {
275+ kind : TypeVariableOriginKind :: TypeInference ,
276+ span,
277+ } ) )
278+ }
279+ Node :: Expr ( & hir:: Expr { kind : hir:: ExprKind :: InlineAsm ( asm) , span, .. } )
280+ | Node :: Item ( & hir:: Item { kind : hir:: ItemKind :: GlobalAsm ( asm) , span, .. } ) => {
281+ asm. operands . iter ( ) . find_map ( |( op, _op_sp) | match op {
282+ hir:: InlineAsmOperand :: Const { anon_const } if anon_const. hir_id == id => {
283+ // Inline assembly constants must be integers.
284+ Some ( fcx. next_int_var ( ) )
285+ }
286+ hir:: InlineAsmOperand :: SymFn { anon_const } if anon_const. hir_id == id => {
287+ Some ( fcx. next_ty_var ( TypeVariableOrigin {
288+ kind : TypeVariableOriginKind :: MiscVariable ,
289+ span,
290+ } ) )
291+ }
292+ _ => None ,
293+ } )
294+ }
295+ _ => None ,
296+ }
297+ } else {
298+ None
299+ } ;
300+ expected_type
301+ }
302+
299303/// When `check_fn` is invoked on a coroutine (i.e., a body that
300304/// includes yield), it returns back some information about the yield
301305/// points.
0 commit comments