@@ -55,9 +55,7 @@ pub fn search_for_structural_match_violation<'tcx>(
55
55
) -> Option < NonStructuralMatchTy < ' tcx > > {
56
56
// FIXME: we should instead pass in an `infcx` from the outside.
57
57
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 ( )
61
59
} )
62
60
}
63
61
@@ -116,9 +114,6 @@ struct Search<'a, 'tcx> {
116
114
117
115
infcx : InferCtxt < ' a , ' tcx > ,
118
116
119
- /// Records first ADT that does not implement a structural-match trait.
120
- found : Option < NonStructuralMatchTy < ' tcx > > ,
121
-
122
117
/// Tracks ADTs previously encountered during search, so that
123
118
/// we will not recur on them again.
124
119
seen : FxHashSet < hir:: def_id:: DefId > ,
@@ -135,38 +130,33 @@ impl Search<'a, 'tcx> {
135
130
}
136
131
137
132
impl < ' a , ' tcx > TypeVisitor < ' tcx > for Search < ' a , ' tcx > {
133
+ type BreakTy = NonStructuralMatchTy < ' tcx > ;
134
+
138
135
fn visit_ty ( & mut self , ty : Ty < ' tcx > ) -> ControlFlow < Self :: BreakTy > {
139
136
debug ! ( "Search visiting ty: {:?}" , ty) ;
140
137
141
138
let ( adt_def, substs) = match * ty. kind ( ) {
142
139
ty:: Adt ( adt_def, substs) => ( adt_def, substs) ,
143
140
ty:: Param ( _) => {
144
- self . found = Some ( NonStructuralMatchTy :: Param ) ;
145
- return ControlFlow :: BREAK ;
141
+ return ControlFlow :: Break ( NonStructuralMatchTy :: Param ) ;
146
142
}
147
143
ty:: Dynamic ( ..) => {
148
- self . found = Some ( NonStructuralMatchTy :: Dynamic ) ;
149
- return ControlFlow :: BREAK ;
144
+ return ControlFlow :: Break ( NonStructuralMatchTy :: Dynamic ) ;
150
145
}
151
146
ty:: Foreign ( _) => {
152
- self . found = Some ( NonStructuralMatchTy :: Foreign ) ;
153
- return ControlFlow :: BREAK ;
147
+ return ControlFlow :: Break ( NonStructuralMatchTy :: Foreign ) ;
154
148
}
155
149
ty:: Opaque ( ..) => {
156
- self . found = Some ( NonStructuralMatchTy :: Opaque ) ;
157
- return ControlFlow :: BREAK ;
150
+ return ControlFlow :: Break ( NonStructuralMatchTy :: Opaque ) ;
158
151
}
159
152
ty:: Projection ( ..) => {
160
- self . found = Some ( NonStructuralMatchTy :: Projection ) ;
161
- return ControlFlow :: BREAK ;
153
+ return ControlFlow :: Break ( NonStructuralMatchTy :: Projection ) ;
162
154
}
163
155
ty:: Generator ( ..) | ty:: GeneratorWitness ( ..) => {
164
- self . found = Some ( NonStructuralMatchTy :: Generator ) ;
165
- return ControlFlow :: BREAK ;
156
+ return ControlFlow :: Break ( NonStructuralMatchTy :: Generator ) ;
166
157
}
167
158
ty:: Closure ( ..) => {
168
- self . found = Some ( NonStructuralMatchTy :: Closure ) ;
169
- return ControlFlow :: BREAK ;
159
+ return ControlFlow :: Break ( NonStructuralMatchTy :: Closure ) ;
170
160
}
171
161
ty:: RawPtr ( ..) => {
172
162
// structural-match ignores substructure of
@@ -206,8 +196,7 @@ impl<'a, 'tcx> TypeVisitor<'tcx> for Search<'a, 'tcx> {
206
196
207
197
ty:: Array ( ..) | ty:: Slice ( _) | ty:: Ref ( ..) | ty:: Tuple ( ..) => {
208
198
// 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 ) ;
211
200
}
212
201
ty:: Infer ( _) | ty:: Placeholder ( _) | ty:: Bound ( ..) => {
213
202
bug ! ( "unexpected type during structural-match checking: {:?}" , ty) ;
@@ -227,8 +216,7 @@ impl<'a, 'tcx> TypeVisitor<'tcx> for Search<'a, 'tcx> {
227
216
228
217
if !self . type_marked_structural ( ty) {
229
218
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) ) ;
232
220
}
233
221
234
222
// structural-match does not care about the
@@ -244,20 +232,11 @@ impl<'a, 'tcx> TypeVisitor<'tcx> for Search<'a, 'tcx> {
244
232
// even though we skip super_visit_with, we must recur on
245
233
// fields of ADT.
246
234
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| {
248
236
let ty = self . tcx ( ) . normalize_erasing_regions ( ty:: ParamEnv :: empty ( ) , field_ty) ;
249
237
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
+ } )
261
240
}
262
241
}
263
242
0 commit comments