@@ -13,6 +13,10 @@ pub enum NonStructuralMatchTy<'tcx> {
13
13
Adt ( & ' tcx AdtDef ) ,
14
14
Param ,
15
15
Dynamic ,
16
+ Foreign ,
17
+ Opaque ,
18
+ Generator ,
19
+ Projection ,
16
20
}
17
21
18
22
/// This method traverses the structure of `ty`, trying to find an
@@ -143,6 +147,22 @@ impl<'a, 'tcx> TypeVisitor<'tcx> for Search<'a, 'tcx> {
143
147
self . found = Some ( NonStructuralMatchTy :: Dynamic ) ;
144
148
return true ; // Stop visiting.
145
149
}
150
+ ty:: Foreign ( _) => {
151
+ self . found = Some ( NonStructuralMatchTy :: Foreign ) ;
152
+ return true ; // Stop visiting.
153
+ }
154
+ ty:: Opaque ( ..) => {
155
+ self . found = Some ( NonStructuralMatchTy :: Opaque ) ;
156
+ return true ; // Stop visiting.
157
+ }
158
+ ty:: Projection ( ..) => {
159
+ self . found = Some ( NonStructuralMatchTy :: Projection ) ;
160
+ return true ; // Stop visiting.
161
+ }
162
+ ty:: Generator ( ..) | ty:: GeneratorWitness ( ..) => {
163
+ self . found = Some ( NonStructuralMatchTy :: Generator ) ;
164
+ return true ; // Stop visiting.
165
+ }
146
166
ty:: RawPtr ( ..) => {
147
167
// structural-match ignores substructure of
148
168
// `*const _`/`*mut _`, so skip `super_visit_with`.
@@ -159,32 +179,55 @@ impl<'a, 'tcx> TypeVisitor<'tcx> for Search<'a, 'tcx> {
159
179
// structural equality on `T` does not recur into the raw
160
180
// pointer. Therefore, one can still use `C` in a pattern.
161
181
162
- // (But still tell caller to continue search.)
182
+ // (But still tell the caller to continue search.)
163
183
return false ;
164
184
}
165
185
ty:: FnDef ( ..) | ty:: FnPtr ( ..) => {
166
- // types of formals and return in `fn(_) -> _` are also irrelevant;
186
+ // Types of formals and return in `fn(_) -> _` are also irrelevant;
167
187
// so we do not recur into them via `super_visit_with`
168
188
//
169
- // (But still tell caller to continue search.)
189
+ // (But still tell the caller to continue search.)
170
190
return false ;
171
191
}
172
192
ty:: Array ( _, n)
173
193
if { n. try_eval_usize ( self . tcx ( ) , ty:: ParamEnv :: reveal_all ( ) ) == Some ( 0 ) } =>
174
194
{
175
195
// rust-lang/rust#62336: ignore type of contents
176
196
// for empty array.
197
+ //
198
+ // (But still tell the caller to continue search.)
177
199
return false ;
178
200
}
179
- _ => {
201
+ ty:: Bool | ty:: Char | ty:: Int ( _) | ty:: Uint ( _) | ty:: Float ( _) | ty:: Str | ty:: Never => {
202
+ // These primitive types are always structural match.
203
+ //
204
+ // `Never` is kind of special here, but as it is not inhabitable, this should be fine.
205
+ //
206
+ // (But still tell the caller to continue search.)
207
+ return false ;
208
+ }
209
+
210
+ ty:: Array ( ..) | ty:: Slice ( _) | ty:: Ref ( ..) | ty:: Tuple ( ..) => {
211
+ // First check all contained types and then tell the caller to continue searching.
180
212
ty. super_visit_with ( self ) ;
181
213
return false ;
182
214
}
215
+ ty:: Closure ( ..) | ty:: Infer ( _) | ty:: Placeholder ( _) | ty:: Bound ( ..) => {
216
+ bug ! ( "unexpected type during structural-match checking: {:?}" , ty) ;
217
+ }
218
+ ty:: Error => {
219
+ self . tcx ( ) . sess . delay_span_bug ( self . span , "ty::Error in structural-match check" ) ;
220
+ // We still want to check other types after encountering an error,
221
+ // as this may still emit relevant errors.
222
+ //
223
+ // So we continue searching here.
224
+ return false ;
225
+ }
183
226
} ;
184
227
185
228
if !self . seen . insert ( adt_def. did ) {
186
229
debug ! ( "Search already seen adt_def: {:?}" , adt_def) ;
187
- // let caller continue its search
230
+ // Let caller continue its search.
188
231
return false ;
189
232
}
190
233
0 commit comments