@@ -24,6 +24,8 @@ impl<'a, 'tcx> PatCtxt<'a, 'tcx> {
24
24
/// Converts an evaluated constant to a pattern (if possible).
25
25
/// This means aggregate values (like structs and enums) are converted
26
26
/// to a pattern that matches the value (as if you'd compared via structural equality).
27
+ ///
28
+ /// `cv` must be a valtree or a `mir::ConstValue`.
27
29
#[ instrument( level = "debug" , skip( self ) , ret) ]
28
30
pub ( super ) fn const_to_pat (
29
31
& self ,
@@ -64,12 +66,10 @@ struct ConstToPat<'tcx> {
64
66
}
65
67
66
68
/// This error type signals that we encountered a non-struct-eq situation.
67
- /// We bubble this up in order to get back to the reference destructuring and make that emit
68
- /// a const pattern instead of a deref pattern. This allows us to simply call `PartialEq::eq`
69
- /// on such patterns (since that function takes a reference) and not have to jump through any
70
- /// hoops to get a reference to the value.
69
+ /// We will fall back to calling `PartialEq::eq` on such patterns,
70
+ /// and exhaustiveness checking will consider them as matching nothing.
71
71
#[ derive( Debug ) ]
72
- struct FallbackToConstRef ;
72
+ struct FallbackToOpaqueConst ;
73
73
74
74
impl < ' tcx > ConstToPat < ' tcx > {
75
75
fn new (
@@ -136,7 +136,7 @@ impl<'tcx> ConstToPat<'tcx> {
136
136
}
137
137
ty:: ConstKind :: Value ( valtree) => self
138
138
. recur ( valtree, cv. ty ( ) , mir_structural_match_violation. unwrap_or ( false ) )
139
- . unwrap_or_else ( |_| {
139
+ . unwrap_or_else ( |_: FallbackToOpaqueConst | {
140
140
Box :: new ( Pat {
141
141
span : self . span ,
142
142
ty : cv. ty ( ) ,
@@ -285,7 +285,7 @@ impl<'tcx> ConstToPat<'tcx> {
285
285
fn field_pats (
286
286
& self ,
287
287
vals : impl Iterator < Item = ( ValTree < ' tcx > , Ty < ' tcx > ) > ,
288
- ) -> Result < Vec < FieldPat < ' tcx > > , FallbackToConstRef > {
288
+ ) -> Result < Vec < FieldPat < ' tcx > > , FallbackToOpaqueConst > {
289
289
vals. enumerate ( )
290
290
. map ( |( idx, ( val, ty) ) | {
291
291
let field = FieldIdx :: new ( idx) ;
@@ -303,7 +303,7 @@ impl<'tcx> ConstToPat<'tcx> {
303
303
cv : ValTree < ' tcx > ,
304
304
ty : Ty < ' tcx > ,
305
305
mir_structural_match_violation : bool ,
306
- ) -> Result < Box < Pat < ' tcx > > , FallbackToConstRef > {
306
+ ) -> Result < Box < Pat < ' tcx > > , FallbackToOpaqueConst > {
307
307
let id = self . id ;
308
308
let span = self . span ;
309
309
let tcx = self . tcx ( ) ;
@@ -318,7 +318,7 @@ impl<'tcx> ConstToPat<'tcx> {
318
318
span,
319
319
FloatPattern ,
320
320
) ;
321
- return Err ( FallbackToConstRef ) ;
321
+ return Err ( FallbackToOpaqueConst ) ;
322
322
}
323
323
// If the type is not structurally comparable, just emit the constant directly,
324
324
// causing the pattern match code to treat it opaquely.
@@ -342,18 +342,20 @@ impl<'tcx> ConstToPat<'tcx> {
342
342
// Since we are behind a reference, we can just bubble the error up so we get a
343
343
// constant at reference type, making it easy to let the fallback call
344
344
// `PartialEq::eq` on it.
345
- return Err ( FallbackToConstRef ) ;
345
+ return Err ( FallbackToOpaqueConst ) ;
346
346
}
347
347
ty:: FnDef ( ..) => {
348
348
self . saw_const_match_error . set ( true ) ;
349
349
tcx. sess . emit_err ( InvalidPattern { span, non_sm_ty : ty } ) ;
350
+ // We errored, so the pattern we generate is irrelevant.
350
351
PatKind :: Wild
351
352
}
352
353
ty:: Adt ( adt_def, _) if !self . type_marked_structural ( ty) => {
353
354
debug ! ( "adt_def {:?} has !type_marked_structural for cv.ty: {:?}" , adt_def, ty, ) ;
354
355
self . saw_const_match_error . set ( true ) ;
355
356
let err = TypeNotStructural { span, non_sm_ty : ty } ;
356
357
tcx. sess . emit_err ( err) ;
358
+ // We errored, so the pattern we generate is irrelevant.
357
359
PatKind :: Wild
358
360
}
359
361
ty:: Adt ( adt_def, args) if adt_def. is_enum ( ) => {
@@ -423,13 +425,15 @@ impl<'tcx> ConstToPat<'tcx> {
423
425
IndirectStructuralMatch { non_sm_ty : * pointee_ty } ,
424
426
) ;
425
427
}
426
- return Err ( FallbackToConstRef ) ;
428
+ return Err ( FallbackToOpaqueConst ) ;
427
429
} else {
428
430
if !self . saw_const_match_error . get ( ) {
429
431
self . saw_const_match_error . set ( true ) ;
430
432
let err = TypeNotStructural { span, non_sm_ty : * pointee_ty } ;
431
433
tcx. sess . emit_err ( err) ;
432
434
}
435
+ tcx. sess . delay_span_bug ( span, "`saw_const_match_error` set but no error?" ) ;
436
+ // We errored, so the pattern we generate is irrelevant.
433
437
PatKind :: Wild
434
438
}
435
439
}
@@ -442,6 +446,7 @@ impl<'tcx> ConstToPat<'tcx> {
442
446
tcx. sess . emit_err ( err) ;
443
447
444
448
// FIXME: introduce PatKind::Error to silence follow up diagnostics due to unreachable patterns.
449
+ // We errored, so the pattern we generate is irrelevant.
445
450
PatKind :: Wild
446
451
} else {
447
452
let old = self . behind_reference . replace ( true ) ;
@@ -472,6 +477,7 @@ impl<'tcx> ConstToPat<'tcx> {
472
477
self . saw_const_match_error . set ( true ) ;
473
478
let err = InvalidPattern { span, non_sm_ty : ty } ;
474
479
tcx. sess . emit_err ( err) ;
480
+ // We errored, so the pattern we generate is irrelevant.
475
481
PatKind :: Wild
476
482
}
477
483
} ;
0 commit comments