@@ -24,6 +24,8 @@ impl<'a, 'tcx> PatCtxt<'a, 'tcx> {
2424 /// Converts an evaluated constant to a pattern (if possible).
2525 /// This means aggregate values (like structs and enums) are converted
2626 /// 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`.
2729 #[ instrument( level = "debug" , skip( self ) , ret) ]
2830 pub ( super ) fn const_to_pat (
2931 & self ,
@@ -64,12 +66,10 @@ struct ConstToPat<'tcx> {
6466}
6567
6668/// 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.
7171#[ derive( Debug ) ]
72- struct FallbackToConstRef ;
72+ struct FallbackToOpaqueConst ;
7373
7474impl < ' tcx > ConstToPat < ' tcx > {
7575 fn new (
@@ -136,7 +136,7 @@ impl<'tcx> ConstToPat<'tcx> {
136136 }
137137 ty:: ConstKind :: Value ( valtree) => self
138138 . recur ( valtree, cv. ty ( ) , mir_structural_match_violation. unwrap_or ( false ) )
139- . unwrap_or_else ( |_| {
139+ . unwrap_or_else ( |_: FallbackToOpaqueConst | {
140140 Box :: new ( Pat {
141141 span : self . span ,
142142 ty : cv. ty ( ) ,
@@ -285,7 +285,7 @@ impl<'tcx> ConstToPat<'tcx> {
285285 fn field_pats (
286286 & self ,
287287 vals : impl Iterator < Item = ( ValTree < ' tcx > , Ty < ' tcx > ) > ,
288- ) -> Result < Vec < FieldPat < ' tcx > > , FallbackToConstRef > {
288+ ) -> Result < Vec < FieldPat < ' tcx > > , FallbackToOpaqueConst > {
289289 vals. enumerate ( )
290290 . map ( |( idx, ( val, ty) ) | {
291291 let field = FieldIdx :: new ( idx) ;
@@ -303,7 +303,7 @@ impl<'tcx> ConstToPat<'tcx> {
303303 cv : ValTree < ' tcx > ,
304304 ty : Ty < ' tcx > ,
305305 mir_structural_match_violation : bool ,
306- ) -> Result < Box < Pat < ' tcx > > , FallbackToConstRef > {
306+ ) -> Result < Box < Pat < ' tcx > > , FallbackToOpaqueConst > {
307307 let id = self . id ;
308308 let span = self . span ;
309309 let tcx = self . tcx ( ) ;
@@ -318,7 +318,7 @@ impl<'tcx> ConstToPat<'tcx> {
318318 span,
319319 FloatPattern ,
320320 ) ;
321- return Err ( FallbackToConstRef ) ;
321+ return Err ( FallbackToOpaqueConst ) ;
322322 }
323323 // If the type is not structurally comparable, just emit the constant directly,
324324 // causing the pattern match code to treat it opaquely.
@@ -342,18 +342,20 @@ impl<'tcx> ConstToPat<'tcx> {
342342 // Since we are behind a reference, we can just bubble the error up so we get a
343343 // constant at reference type, making it easy to let the fallback call
344344 // `PartialEq::eq` on it.
345- return Err ( FallbackToConstRef ) ;
345+ return Err ( FallbackToOpaqueConst ) ;
346346 }
347347 ty:: FnDef ( ..) => {
348348 self . saw_const_match_error . set ( true ) ;
349349 tcx. sess . emit_err ( InvalidPattern { span, non_sm_ty : ty } ) ;
350+ // We errored, so the pattern we generate is irrelevant.
350351 PatKind :: Wild
351352 }
352353 ty:: Adt ( adt_def, _) if !self . type_marked_structural ( ty) => {
353354 debug ! ( "adt_def {:?} has !type_marked_structural for cv.ty: {:?}" , adt_def, ty, ) ;
354355 self . saw_const_match_error . set ( true ) ;
355356 let err = TypeNotStructural { span, non_sm_ty : ty } ;
356357 tcx. sess . emit_err ( err) ;
358+ // We errored, so the pattern we generate is irrelevant.
357359 PatKind :: Wild
358360 }
359361 ty:: Adt ( adt_def, args) if adt_def. is_enum ( ) => {
@@ -423,13 +425,15 @@ impl<'tcx> ConstToPat<'tcx> {
423425 IndirectStructuralMatch { non_sm_ty : * pointee_ty } ,
424426 ) ;
425427 }
426- return Err ( FallbackToConstRef ) ;
428+ return Err ( FallbackToOpaqueConst ) ;
427429 } else {
428430 if !self . saw_const_match_error . get ( ) {
429431 self . saw_const_match_error . set ( true ) ;
430432 let err = TypeNotStructural { span, non_sm_ty : * pointee_ty } ;
431433 tcx. sess . emit_err ( err) ;
432434 }
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.
433437 PatKind :: Wild
434438 }
435439 }
@@ -442,6 +446,7 @@ impl<'tcx> ConstToPat<'tcx> {
442446 tcx. sess . emit_err ( err) ;
443447
444448 // FIXME: introduce PatKind::Error to silence follow up diagnostics due to unreachable patterns.
449+ // We errored, so the pattern we generate is irrelevant.
445450 PatKind :: Wild
446451 } else {
447452 let old = self . behind_reference . replace ( true ) ;
@@ -472,6 +477,7 @@ impl<'tcx> ConstToPat<'tcx> {
472477 self . saw_const_match_error . set ( true ) ;
473478 let err = InvalidPattern { span, non_sm_ty : ty } ;
474479 tcx. sess . emit_err ( err) ;
480+ // We errored, so the pattern we generate is irrelevant.
475481 PatKind :: Wild
476482 }
477483 } ;
0 commit comments