@@ -62,21 +62,13 @@ struct ConstToPat<'tcx> {
6262 treat_byte_string_as_slice : bool ,
6363}
6464
65- mod fallback_to_const_ref {
66- #[ derive( Debug ) ]
67- /// This error type signals that we encountered a non-struct-eq situation behind a reference.
68- /// We bubble this up in order to get back to the reference destructuring and make that emit
69- /// a const pattern instead of a deref pattern. This allows us to simply call `PartialEq::eq`
70- /// on such patterns (since that function takes a reference) and not have to jump through any
71- /// hoops to get a reference to the value.
72- pub ( super ) struct FallbackToConstRef ( ( ) ) ;
73-
74- pub ( super ) fn fallback_to_const_ref ( c2p : & super :: ConstToPat < ' _ > ) -> FallbackToConstRef {
75- assert ! ( c2p. behind_reference. get( ) ) ;
76- FallbackToConstRef ( ( ) )
77- }
78- }
79- use fallback_to_const_ref:: { fallback_to_const_ref, FallbackToConstRef } ;
65+ /// This error type signals that we encountered a non-struct-eq situation.
66+ /// We bubble this up in order to get back to the reference destructuring and make that emit
67+ /// a const pattern instead of a deref pattern. This allows us to simply call `PartialEq::eq`
68+ /// on such patterns (since that function takes a reference) and not have to jump through any
69+ /// hoops to get a reference to the value.
70+ #[ derive( Debug ) ]
71+ struct FallbackToConstRef ;
8072
8173impl < ' tcx > ConstToPat < ' tcx > {
8274 fn new (
@@ -236,13 +228,13 @@ impl<'tcx> ConstToPat<'tcx> {
236228
237229 let kind = match cv. ty ( ) . kind ( ) {
238230 ty:: Float ( _) => {
239- tcx. emit_spanned_lint (
240- lint:: builtin:: ILLEGAL_FLOATING_POINT_LITERAL_PATTERN ,
241- id,
242- span,
243- FloatPattern ,
244- ) ;
245- PatKind :: Constant { value : cv }
231+ tcx. emit_spanned_lint (
232+ lint:: builtin:: ILLEGAL_FLOATING_POINT_LITERAL_PATTERN ,
233+ id,
234+ span,
235+ FloatPattern ,
236+ ) ;
237+ return Err ( FallbackToConstRef ) ;
246238 }
247239 ty:: Adt ( adt_def, _) if adt_def. is_union ( ) => {
248240 // Matching on union fields is unsafe, we can't hide it in constants
@@ -289,7 +281,7 @@ impl<'tcx> ConstToPat<'tcx> {
289281 // Since we are behind a reference, we can just bubble the error up so we get a
290282 // constant at reference type, making it easy to let the fallback call
291283 // `PartialEq::eq` on it.
292- return Err ( fallback_to_const_ref ( self ) ) ;
284+ return Err ( FallbackToConstRef ) ;
293285 }
294286 ty:: Adt ( adt_def, _) if !self . type_marked_structural ( cv. ty ( ) ) => {
295287 debug ! (
@@ -393,11 +385,11 @@ impl<'tcx> ConstToPat<'tcx> {
393385 self . behind_reference . set ( old) ;
394386 val
395387 }
396- // Backwards compatibility hack: support references to non-structural types.
397- // We'll lower
398- // this pattern to a `PartialEq::eq` comparison and `PartialEq::eq` takes a
399- // reference. This makes the rest of the matching logic simpler as it doesn't have
400- // to figure out how to get a reference again .
388+ // Backwards compatibility hack: support references to non-structural types,
389+ // but hard error if we aren't behind a double reference. We could just use
390+ // the fallback code path below, but that would allow *more* of this fishy
391+ // code to compile, as then it only goes through the future incompat lint
392+ // instead of a hard error .
401393 ty:: Adt ( _, _) if !self . type_marked_structural ( * pointee_ty) => {
402394 if self . behind_reference . get ( ) {
403395 if !self . saw_const_match_error . get ( )
@@ -411,7 +403,7 @@ impl<'tcx> ConstToPat<'tcx> {
411403 IndirectStructuralMatch { non_sm_ty : * pointee_ty } ,
412404 ) ;
413405 }
414- PatKind :: Constant { value : cv }
406+ return Err ( FallbackToConstRef ) ;
415407 } else {
416408 if !self . saw_const_match_error . get ( ) {
417409 self . saw_const_match_error . set ( true ) ;
@@ -435,24 +427,17 @@ impl<'tcx> ConstToPat<'tcx> {
435427 PatKind :: Wild
436428 } else {
437429 let old = self . behind_reference . replace ( true ) ;
438- // In case there are structural-match violations somewhere in this subpattern,
439- // we fall back to a const pattern. If we do not do this, we may end up with
440- // a !structural-match constant that is not of reference type, which makes it
441- // very hard to invoke `PartialEq::eq` on it as a fallback.
442- let val = match self . recur ( tcx. deref_mir_constant ( self . param_env . and ( cv) ) , false ) {
443- Ok ( subpattern) => PatKind :: Deref { subpattern } ,
444- Err ( _) => PatKind :: Constant { value : cv } ,
445- } ;
430+ let subpattern = self . recur ( tcx. deref_mir_constant ( self . param_env . and ( cv) ) , false ) ?;
446431 self . behind_reference . set ( old) ;
447- val
432+ PatKind :: Deref { subpattern }
448433 }
449434 }
450435 } ,
451436 ty:: Bool | ty:: Char | ty:: Int ( _) | ty:: Uint ( _) | ty:: FnDef ( ..) => {
452437 PatKind :: Constant { value : cv }
453438 }
454439 ty:: RawPtr ( pointee) if pointee. ty . is_sized ( tcx, param_env) => {
455- PatKind :: Constant { value : cv }
440+ return Err ( FallbackToConstRef ) ;
456441 }
457442 // FIXME: these can have very surprising behaviour where optimization levels or other
458443 // compilation choices change the runtime behaviour of the match.
@@ -469,7 +454,7 @@ impl<'tcx> ConstToPat<'tcx> {
469454 PointerPattern
470455 ) ;
471456 }
472- PatKind :: Constant { value : cv }
457+ return Err ( FallbackToConstRef ) ;
473458 }
474459 _ => {
475460 self . saw_const_match_error . set ( true ) ;
0 commit comments