@@ -62,21 +62,13 @@ struct ConstToPat<'tcx> {
62
62
treat_byte_string_as_slice : bool ,
63
63
}
64
64
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 ;
80
72
81
73
impl < ' tcx > ConstToPat < ' tcx > {
82
74
fn new (
@@ -236,13 +228,13 @@ impl<'tcx> ConstToPat<'tcx> {
236
228
237
229
let kind = match cv. ty ( ) . kind ( ) {
238
230
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 ) ;
246
238
}
247
239
ty:: Adt ( adt_def, _) if adt_def. is_union ( ) => {
248
240
// Matching on union fields is unsafe, we can't hide it in constants
@@ -289,7 +281,7 @@ impl<'tcx> ConstToPat<'tcx> {
289
281
// Since we are behind a reference, we can just bubble the error up so we get a
290
282
// constant at reference type, making it easy to let the fallback call
291
283
// `PartialEq::eq` on it.
292
- return Err ( fallback_to_const_ref ( self ) ) ;
284
+ return Err ( FallbackToConstRef ) ;
293
285
}
294
286
ty:: Adt ( adt_def, _) if !self . type_marked_structural ( cv. ty ( ) ) => {
295
287
debug ! (
@@ -393,11 +385,11 @@ impl<'tcx> ConstToPat<'tcx> {
393
385
self . behind_reference . set ( old) ;
394
386
val
395
387
}
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 .
401
393
ty:: Adt ( _, _) if !self . type_marked_structural ( * pointee_ty) => {
402
394
if self . behind_reference . get ( ) {
403
395
if !self . saw_const_match_error . get ( )
@@ -411,7 +403,7 @@ impl<'tcx> ConstToPat<'tcx> {
411
403
IndirectStructuralMatch { non_sm_ty : * pointee_ty } ,
412
404
) ;
413
405
}
414
- PatKind :: Constant { value : cv }
406
+ return Err ( FallbackToConstRef ) ;
415
407
} else {
416
408
if !self . saw_const_match_error . get ( ) {
417
409
self . saw_const_match_error . set ( true ) ;
@@ -435,24 +427,17 @@ impl<'tcx> ConstToPat<'tcx> {
435
427
PatKind :: Wild
436
428
} else {
437
429
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 ) ?;
446
431
self . behind_reference . set ( old) ;
447
- val
432
+ PatKind :: Deref { subpattern }
448
433
}
449
434
}
450
435
} ,
451
436
ty:: Bool | ty:: Char | ty:: Int ( _) | ty:: Uint ( _) | ty:: FnDef ( ..) => {
452
437
PatKind :: Constant { value : cv }
453
438
}
454
439
ty:: RawPtr ( pointee) if pointee. ty . is_sized ( tcx, param_env) => {
455
- PatKind :: Constant { value : cv }
440
+ return Err ( FallbackToConstRef ) ;
456
441
}
457
442
// FIXME: these can have very surprising behaviour where optimization levels or other
458
443
// compilation choices change the runtime behaviour of the match.
@@ -469,7 +454,7 @@ impl<'tcx> ConstToPat<'tcx> {
469
454
PointerPattern
470
455
) ;
471
456
}
472
- PatKind :: Constant { value : cv }
457
+ return Err ( FallbackToConstRef ) ;
473
458
}
474
459
_ => {
475
460
self . saw_const_match_error . set ( true ) ;
0 commit comments