@@ -55,9 +55,7 @@ pub fn search_for_structural_match_violation<'tcx>(
5555) -> Option < NonStructuralMatchTy < ' tcx > > {
5656 // FIXME: we should instead pass in an `infcx` from the outside.
5757 tcx. infer_ctxt ( ) . enter ( |infcx| {
58- let mut search = Search { infcx, span, found : None , seen : FxHashSet :: default ( ) } ;
59- ty. visit_with ( & mut search) ;
60- search. found
58+ ty. visit_with ( & mut Search { infcx, span, seen : FxHashSet :: default ( ) } ) . break_value ( )
6159 } )
6260}
6361
@@ -116,9 +114,6 @@ struct Search<'a, 'tcx> {
116114
117115 infcx : InferCtxt < ' a , ' tcx > ,
118116
119- /// Records first ADT that does not implement a structural-match trait.
120- found : Option < NonStructuralMatchTy < ' tcx > > ,
121-
122117 /// Tracks ADTs previously encountered during search, so that
123118 /// we will not recur on them again.
124119 seen : FxHashSet < hir:: def_id:: DefId > ,
@@ -135,38 +130,33 @@ impl Search<'a, 'tcx> {
135130}
136131
137132impl < ' a , ' tcx > TypeVisitor < ' tcx > for Search < ' a , ' tcx > {
133+ type BreakTy = NonStructuralMatchTy < ' tcx > ;
134+
138135 fn visit_ty ( & mut self , ty : Ty < ' tcx > ) -> ControlFlow < Self :: BreakTy > {
139136 debug ! ( "Search visiting ty: {:?}" , ty) ;
140137
141138 let ( adt_def, substs) = match * ty. kind ( ) {
142139 ty:: Adt ( adt_def, substs) => ( adt_def, substs) ,
143140 ty:: Param ( _) => {
144- self . found = Some ( NonStructuralMatchTy :: Param ) ;
145- return ControlFlow :: BREAK ;
141+ return ControlFlow :: Break ( NonStructuralMatchTy :: Param ) ;
146142 }
147143 ty:: Dynamic ( ..) => {
148- self . found = Some ( NonStructuralMatchTy :: Dynamic ) ;
149- return ControlFlow :: BREAK ;
144+ return ControlFlow :: Break ( NonStructuralMatchTy :: Dynamic ) ;
150145 }
151146 ty:: Foreign ( _) => {
152- self . found = Some ( NonStructuralMatchTy :: Foreign ) ;
153- return ControlFlow :: BREAK ;
147+ return ControlFlow :: Break ( NonStructuralMatchTy :: Foreign ) ;
154148 }
155149 ty:: Opaque ( ..) => {
156- self . found = Some ( NonStructuralMatchTy :: Opaque ) ;
157- return ControlFlow :: BREAK ;
150+ return ControlFlow :: Break ( NonStructuralMatchTy :: Opaque ) ;
158151 }
159152 ty:: Projection ( ..) => {
160- self . found = Some ( NonStructuralMatchTy :: Projection ) ;
161- return ControlFlow :: BREAK ;
153+ return ControlFlow :: Break ( NonStructuralMatchTy :: Projection ) ;
162154 }
163155 ty:: Generator ( ..) | ty:: GeneratorWitness ( ..) => {
164- self . found = Some ( NonStructuralMatchTy :: Generator ) ;
165- return ControlFlow :: BREAK ;
156+ return ControlFlow :: Break ( NonStructuralMatchTy :: Generator ) ;
166157 }
167158 ty:: Closure ( ..) => {
168- self . found = Some ( NonStructuralMatchTy :: Closure ) ;
169- return ControlFlow :: BREAK ;
159+ return ControlFlow :: Break ( NonStructuralMatchTy :: Closure ) ;
170160 }
171161 ty:: RawPtr ( ..) => {
172162 // structural-match ignores substructure of
@@ -206,8 +196,7 @@ impl<'a, 'tcx> TypeVisitor<'tcx> for Search<'a, 'tcx> {
206196
207197 ty:: Array ( ..) | ty:: Slice ( _) | ty:: Ref ( ..) | ty:: Tuple ( ..) => {
208198 // First check all contained types and then tell the caller to continue searching.
209- ty. super_visit_with ( self ) ;
210- return ControlFlow :: CONTINUE ;
199+ return ty. super_visit_with ( self ) ;
211200 }
212201 ty:: Infer ( _) | ty:: Placeholder ( _) | ty:: Bound ( ..) => {
213202 bug ! ( "unexpected type during structural-match checking: {:?}" , ty) ;
@@ -227,8 +216,7 @@ impl<'a, 'tcx> TypeVisitor<'tcx> for Search<'a, 'tcx> {
227216
228217 if !self . type_marked_structural ( ty) {
229218 debug ! ( "Search found ty: {:?}" , ty) ;
230- self . found = Some ( NonStructuralMatchTy :: Adt ( & adt_def) ) ;
231- return ControlFlow :: BREAK ;
219+ return ControlFlow :: Break ( NonStructuralMatchTy :: Adt ( & adt_def) ) ;
232220 }
233221
234222 // structural-match does not care about the
@@ -244,20 +232,11 @@ impl<'a, 'tcx> TypeVisitor<'tcx> for Search<'a, 'tcx> {
244232 // even though we skip super_visit_with, we must recur on
245233 // fields of ADT.
246234 let tcx = self . tcx ( ) ;
247- for field_ty in adt_def. all_fields ( ) . map ( |field| field. ty ( tcx, substs) ) {
235+ adt_def. all_fields ( ) . map ( |field| field. ty ( tcx, substs) ) . try_for_each ( |field_ty| {
248236 let ty = self . tcx ( ) . normalize_erasing_regions ( ty:: ParamEnv :: empty ( ) , field_ty) ;
249237 debug ! ( "structural-match ADT: field_ty={:?}, ty={:?}" , field_ty, ty) ;
250-
251- if ty. visit_with ( self ) . is_break ( ) {
252- // found an ADT without structural-match; halt visiting!
253- assert ! ( self . found. is_some( ) ) ;
254- return ControlFlow :: BREAK ;
255- }
256- }
257-
258- // Even though we do not want to recur on substs, we do
259- // want our caller to continue its own search.
260- ControlFlow :: CONTINUE
238+ ty. visit_with ( self )
239+ } )
261240 }
262241}
263242
0 commit comments