@@ -13,6 +13,10 @@ pub enum NonStructuralMatchTy<'tcx> {
1313 Adt ( & ' tcx AdtDef ) ,
1414 Param ,
1515 Dynamic ,
16+ Foreign ,
17+ Opaque ,
18+ Generator ,
19+ Projection ,
1620}
1721
1822/// This method traverses the structure of `ty`, trying to find an
@@ -143,6 +147,22 @@ impl<'a, 'tcx> TypeVisitor<'tcx> for Search<'a, 'tcx> {
143147 self . found = Some ( NonStructuralMatchTy :: Dynamic ) ;
144148 return true ; // Stop visiting.
145149 }
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+ }
146166 ty:: RawPtr ( ..) => {
147167 // structural-match ignores substructure of
148168 // `*const _`/`*mut _`, so skip `super_visit_with`.
@@ -159,32 +179,55 @@ impl<'a, 'tcx> TypeVisitor<'tcx> for Search<'a, 'tcx> {
159179 // structural equality on `T` does not recur into the raw
160180 // pointer. Therefore, one can still use `C` in a pattern.
161181
162- // (But still tell caller to continue search.)
182+ // (But still tell the caller to continue search.)
163183 return false ;
164184 }
165185 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;
167187 // so we do not recur into them via `super_visit_with`
168188 //
169- // (But still tell caller to continue search.)
189+ // (But still tell the caller to continue search.)
170190 return false ;
171191 }
172192 ty:: Array ( _, n)
173193 if { n. try_eval_usize ( self . tcx ( ) , ty:: ParamEnv :: reveal_all ( ) ) == Some ( 0 ) } =>
174194 {
175195 // rust-lang/rust#62336: ignore type of contents
176196 // for empty array.
197+ //
198+ // (But still tell the caller to continue search.)
177199 return false ;
178200 }
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.
180212 ty. super_visit_with ( self ) ;
181213 return false ;
182214 }
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+ }
183226 } ;
184227
185228 if !self . seen . insert ( adt_def. did ) {
186229 debug ! ( "Search already seen adt_def: {:?}" , adt_def) ;
187- // let caller continue its search
230+ // Let caller continue its search.
188231 return false ;
189232 }
190233
0 commit comments