@@ -42,8 +42,11 @@ mod typeck_root_ctxt;
42
42
mod upvar;
43
43
mod writeback;
44
44
45
+ use core:: ops:: ControlFlow ;
46
+
45
47
pub use coercion:: can_coerce;
46
48
use fn_ctxt:: FnCtxt ;
49
+ use rustc_data_structures:: fx:: FxHashSet ;
47
50
use rustc_data_structures:: unord:: UnordSet ;
48
51
use rustc_errors:: codes:: * ;
49
52
use rustc_errors:: { struct_span_code_err, Applicability , ErrorGuaranteed } ;
@@ -55,7 +58,7 @@ use rustc_hir_analysis::check::check_abi;
55
58
use rustc_hir_analysis:: hir_ty_lowering:: HirTyLowerer ;
56
59
use rustc_infer:: traits:: { ObligationCauseCode , ObligationInspector , WellFormedLoc } ;
57
60
use rustc_middle:: query:: Providers ;
58
- use rustc_middle:: ty:: { self , Ty , TyCtxt } ;
61
+ use rustc_middle:: ty:: { self , Ty , TyCtxt , TypeSuperVisitable , TypeVisitable , TypeVisitor } ;
59
62
use rustc_middle:: { bug, span_bug} ;
60
63
use rustc_session:: config;
61
64
use rustc_span:: def_id:: LocalDefId ;
@@ -116,6 +119,40 @@ pub fn inspect_typeck<'tcx>(
116
119
typeck_with_fallback ( tcx, def_id, fallback, Some ( inspect) )
117
120
}
118
121
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
+
119
156
#[ instrument( level = "debug" , skip( tcx, fallback, inspector) , ret) ]
120
157
fn typeck_with_fallback < ' tcx > (
121
158
tcx : TyCtxt < ' tcx > ,
@@ -168,6 +205,11 @@ fn typeck_with_fallback<'tcx>(
168
205
169
206
let expected_type = fcx. normalize ( body. value . span , expected_type) ;
170
207
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
+
171
213
let wf_code = ObligationCauseCode :: WellFormed ( Some ( WellFormedLoc :: Ty ( def_id) ) ) ;
172
214
fcx. register_wf_obligation ( expected_type. into ( ) , body. value . span , wf_code) ;
173
215
0 commit comments