@@ -42,8 +42,11 @@ mod typeck_root_ctxt;
4242mod  upvar; 
4343mod  writeback; 
4444
45+ use  core:: ops:: ControlFlow ; 
46+ 
4547pub  use  coercion:: can_coerce; 
4648use  fn_ctxt:: FnCtxt ; 
49+ use  rustc_data_structures:: fx:: FxHashSet ; 
4750use  rustc_data_structures:: unord:: UnordSet ; 
4851use  rustc_errors:: codes:: * ; 
4952use  rustc_errors:: { struct_span_code_err,  Applicability ,  ErrorGuaranteed } ; 
@@ -55,7 +58,7 @@ use rustc_hir_analysis::check::check_abi;
5558use  rustc_hir_analysis:: hir_ty_lowering:: HirTyLowerer ; 
5659use  rustc_infer:: traits:: { ObligationCauseCode ,  ObligationInspector ,  WellFormedLoc } ; 
5760use  rustc_middle:: query:: Providers ; 
58- use  rustc_middle:: ty:: { self ,  Ty ,  TyCtxt } ; 
61+ use  rustc_middle:: ty:: { self ,  Ty ,  TyCtxt ,   TypeSuperVisitable ,   TypeVisitable ,   TypeVisitor } ; 
5962use  rustc_middle:: { bug,  span_bug} ; 
6063use  rustc_session:: config; 
6164use  rustc_span:: def_id:: LocalDefId ; 
@@ -116,6 +119,40 @@ pub fn inspect_typeck<'tcx>(
116119    typeck_with_fallback ( tcx,  def_id,  fallback,  Some ( inspect) ) 
117120} 
118121
122+ struct  RecursiveHasErrorVisitor < ' tcx >  { 
123+     tcx :  TyCtxt < ' tcx > , 
124+     // To avoid cycle when visiting recursive types. 
125+     visited_tys :  FxHashSet < Ty < ' tcx > > , 
126+ } 
127+ 
128+ impl < ' tcx >  RecursiveHasErrorVisitor < ' tcx >  { 
129+     fn  new ( tcx :  TyCtxt < ' tcx > )  -> Self  { 
130+         RecursiveHasErrorVisitor  {  tcx,  visited_tys :  Default :: default ( )  } 
131+     } 
132+ } 
133+ 
134+ impl < ' tcx >  TypeVisitor < TyCtxt < ' tcx > >  for  RecursiveHasErrorVisitor < ' tcx >  { 
135+     type  Result  = ControlFlow < ErrorGuaranteed > ; 
136+ 
137+     fn  visit_ty ( & mut  self ,  t :  Ty < ' tcx > )  -> Self :: Result  { 
138+         if  self . visited_tys . insert ( t. clone ( ) )  { 
139+             if  let  ty:: Adt ( def,  args)  = t. kind ( )  { 
140+                 let  field_tys:  Vec < _ >  = def. all_fields ( ) . map ( |f| f. ty ( self . tcx ,  args) ) . collect ( ) ; 
141+                 for  field_ty in  field_tys { 
142+                     field_ty. visit_with ( self ) ?; 
143+                 } 
144+             } 
145+             t. super_visit_with ( self ) 
146+         }  else  { 
147+             ControlFlow :: Continue ( ( ) ) 
148+         } 
149+     } 
150+ 
151+     fn  visit_error ( & mut  self ,  guar :  ErrorGuaranteed )  -> Self :: Result  { 
152+         ControlFlow :: Break ( guar) 
153+     } 
154+ } 
155+ 
119156#[ instrument( level = "debug" ,  skip( tcx,  fallback,  inspector) ,  ret) ]  
120157fn  typeck_with_fallback < ' tcx > ( 
121158    tcx :  TyCtxt < ' tcx > , 
@@ -168,6 +205,11 @@ fn typeck_with_fallback<'tcx>(
168205
169206        let  expected_type = fcx. normalize ( body. value . span ,  expected_type) ; 
170207
208+         let  mut  error_visitor = RecursiveHasErrorVisitor :: new ( tcx) ; 
209+         if  let  ControlFlow :: Break ( guar)  = expected_type. visit_with ( & mut  error_visitor)  { 
210+             fcx. set_tainted_by_errors ( guar) ; 
211+         } 
212+ 
171213        let  wf_code = ObligationCauseCode :: WellFormed ( Some ( WellFormedLoc :: Ty ( def_id) ) ) ; 
172214        fcx. register_wf_obligation ( expected_type. into ( ) ,  body. value . span ,  wf_code) ; 
173215
0 commit comments