@@ -58,6 +58,9 @@ struct ConstToPat<'a, 'tcx> {
58
58
include_lint_checks : bool ,
59
59
}
60
60
61
+ #[ derive( Debug ) ]
62
+ struct FallbackToConstRef ;
63
+
61
64
impl < ' a , ' tcx > ConstToPat < ' a , ' tcx > {
62
65
fn new (
63
66
pat_ctxt : & PatCtxt < ' _ , ' tcx > ,
@@ -103,7 +106,7 @@ impl<'a, 'tcx> ConstToPat<'a, 'tcx> {
103
106
// once indirect_structural_match is a full fledged error, this
104
107
// level of indirection can be eliminated
105
108
106
- let inlined_const_as_pat = self . recur ( cv, mir_structural_match_violation) ;
109
+ let inlined_const_as_pat = self . recur ( cv, mir_structural_match_violation) . unwrap ( ) ;
107
110
108
111
if self . include_lint_checks && !self . saw_const_match_error . get ( ) {
109
112
// If we were able to successfully convert the const to some pat,
@@ -216,18 +219,22 @@ impl<'a, 'tcx> ConstToPat<'a, 'tcx> {
216
219
}
217
220
218
221
// Recursive helper for `to_pat`; invoke that (instead of calling this directly).
219
- fn recur ( & self , cv : & ' tcx ty:: Const < ' tcx > , mir_structural_match_violation : bool ) -> Pat < ' tcx > {
222
+ fn recur (
223
+ & self ,
224
+ cv : & ' tcx ty:: Const < ' tcx > ,
225
+ mir_structural_match_violation : bool ,
226
+ ) -> Result < Pat < ' tcx > , FallbackToConstRef > {
220
227
let id = self . id ;
221
228
let span = self . span ;
222
229
let tcx = self . tcx ( ) ;
223
230
let param_env = self . param_env ;
224
231
225
- let field_pats = |vals : & [ & ' tcx ty:: Const < ' tcx > ] | {
232
+ let field_pats = |vals : & [ & ' tcx ty:: Const < ' tcx > ] | -> Result < _ , _ > {
226
233
vals. iter ( )
227
234
. enumerate ( )
228
235
. map ( |( idx, val) | {
229
236
let field = Field :: new ( idx) ;
230
- FieldPat { field, pattern : self . recur ( val, false ) }
237
+ Ok ( FieldPat { field, pattern : self . recur ( val, false ) ? } )
231
238
} )
232
239
. collect ( )
233
240
} ;
@@ -287,7 +294,10 @@ impl<'a, 'tcx> ConstToPat<'a, 'tcx> {
287
294
|lint| lint. build ( & msg) . emit ( ) ,
288
295
) ;
289
296
}
290
- PatKind :: Constant { value : cv }
297
+ // Since we are behind a reference, we can just bubble the error up so we get a
298
+ // constant at reference type, making it easy to let the fallback call
299
+ // `PartialEq::eq` on it.
300
+ return Err ( FallbackToConstRef ) ;
291
301
}
292
302
ty:: Adt ( adt_def, _) if !self . type_marked_structural ( cv. ty ) => {
293
303
debug ! ( "adt_def {:?} has !type_marked_structural for cv.ty: {:?}" , adt_def, cv. ty) ;
@@ -309,20 +319,20 @@ impl<'a, 'tcx> ConstToPat<'a, 'tcx> {
309
319
variant_index : destructured
310
320
. variant
311
321
. expect ( "destructed const of adt without variant id" ) ,
312
- subpatterns : field_pats ( destructured. fields ) ,
322
+ subpatterns : field_pats ( destructured. fields ) ? ,
313
323
}
314
324
}
315
325
ty:: Tuple ( _) | ty:: Adt ( _, _) => {
316
326
let destructured = tcx. destructure_const ( param_env. and ( cv) ) ;
317
- PatKind :: Leaf { subpatterns : field_pats ( destructured. fields ) }
327
+ PatKind :: Leaf { subpatterns : field_pats ( destructured. fields ) ? }
318
328
}
319
329
ty:: Array ( ..) => PatKind :: Array {
320
330
prefix : tcx
321
331
. destructure_const ( param_env. and ( cv) )
322
332
. fields
323
333
. iter ( )
324
334
. map ( |val| self . recur ( val, false ) )
325
- . collect ( ) ,
335
+ . collect :: < Result < _ , _ > > ( ) ? ,
326
336
slice : None ,
327
337
suffix : Vec :: new ( ) ,
328
338
} ,
@@ -355,7 +365,7 @@ impl<'a, 'tcx> ConstToPat<'a, 'tcx> {
355
365
. fields
356
366
. iter ( )
357
367
. map ( |val| self . recur ( val, false ) )
358
- . collect ( ) ,
368
+ . collect :: < Result < _ , _ > > ( ) ? ,
359
369
slice : None ,
360
370
suffix : vec ! [ ] ,
361
371
} ) ,
@@ -379,8 +389,13 @@ impl<'a, 'tcx> ConstToPat<'a, 'tcx> {
379
389
// deref pattern.
380
390
_ => {
381
391
let old = self . behind_reference . replace ( true ) ;
382
- let val = PatKind :: Deref {
383
- subpattern : self . recur ( tcx. deref_const ( self . param_env . and ( cv) ) , false ) ,
392
+ // In case there are structural-match violations somewhere in this subpattern,
393
+ // we fall back to a const pattern. If we do not do this, we may end up with
394
+ // a !structural-match constant that is not of reference type, which makes it
395
+ // very hard to invoke `PartialEq::eq` on it as a fallback.
396
+ let val = match self . recur ( tcx. deref_const ( self . param_env . and ( cv) ) , false ) {
397
+ Ok ( subpattern) => PatKind :: Deref { subpattern } ,
398
+ Err ( FallbackToConstRef ) => PatKind :: Constant { value : cv } ,
384
399
} ;
385
400
self . behind_reference . set ( old) ;
386
401
val
@@ -439,6 +454,6 @@ impl<'a, 'tcx> ConstToPat<'a, 'tcx> {
439
454
) ;
440
455
}
441
456
442
- Pat { span, ty : cv. ty , kind : Box :: new ( kind) }
457
+ Ok ( Pat { span, ty : cv. ty , kind : Box :: new ( kind) } )
443
458
}
444
459
}
0 commit comments