@@ -531,24 +531,9 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
531
531
// If `deref_patterns` is enabled, peel a smart pointer from the scrutinee type. See the
532
532
// examples in `tests/ui/pattern/deref_patterns/`.
533
533
_ if self . tcx . features ( ) . deref_patterns ( )
534
- && let AdjustMode :: Peel { kind : PeelKind :: Implicit { until_adt } } = adjust_mode
534
+ && let AdjustMode :: Peel { kind : peel_kind } = adjust_mode
535
535
&& pat. default_binding_modes
536
- // For simplicity, only apply overloaded derefs if `expected` is a known ADT.
537
- // FIXME(deref_patterns): we'll get better diagnostics for users trying to
538
- // implicitly deref generics if we allow them here, but primitives, tuples, and
539
- // inference vars definitely should be stopped. Figure out what makes most sense.
540
- && let ty:: Adt ( scrutinee_adt, _) = * expected. kind ( )
541
- // Don't peel if the pattern type already matches the scrutinee. E.g., stop here if
542
- // matching on a `Cow<'a, T>` scrutinee with a `Cow::Owned(_)` pattern.
543
- && until_adt != Some ( scrutinee_adt. did ( ) )
544
- // At this point, the pattern isn't able to match `expected` without peeling. Check
545
- // that it implements `Deref` before assuming it's a smart pointer, to get a normal
546
- // type error instead of a missing impl error if not. This only checks for `Deref`,
547
- // not `DerefPure`: we require that too, but we want a trait error if it's missing.
548
- && let Some ( deref_trait) = self . tcx . lang_items ( ) . deref_trait ( )
549
- && self
550
- . type_implements_trait ( deref_trait, [ expected] , self . param_env )
551
- . may_apply ( ) =>
536
+ && self . should_peel_smart_pointer ( peel_kind, expected) =>
552
537
{
553
538
debug ! ( "scrutinee ty {expected:?} is a smart pointer, inserting overloaded deref" ) ;
554
539
// The scrutinee is a smart pointer; implicitly dereference it. This adds a
@@ -720,6 +705,31 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
720
705
}
721
706
}
722
707
708
+ /// Determine whether `expected` is a smart pointer type that should be peeled before matching.
709
+ fn should_peel_smart_pointer ( & self , peel_kind : PeelKind , expected : Ty < ' tcx > ) -> bool {
710
+ // Explicit `deref!(_)` patterns match against smart pointers; don't peel in that case.
711
+ if let PeelKind :: Implicit { until_adt, .. } = peel_kind
712
+ // For simplicity, only apply overloaded derefs if `expected` is a known ADT.
713
+ // FIXME(deref_patterns): we'll get better diagnostics for users trying to
714
+ // implicitly deref generics if we allow them here, but primitives, tuples, and
715
+ // inference vars definitely should be stopped. Figure out what makes most sense.
716
+ && let ty:: Adt ( scrutinee_adt, _) = * expected. kind ( )
717
+ // Don't peel if the pattern type already matches the scrutinee. E.g., stop here if
718
+ // matching on a `Cow<'a, T>` scrutinee with a `Cow::Owned(_)` pattern.
719
+ && until_adt != Some ( scrutinee_adt. did ( ) )
720
+ // At this point, the pattern isn't able to match `expected` without peeling. Check
721
+ // that it implements `Deref` before assuming it's a smart pointer, to get a normal
722
+ // type error instead of a missing impl error if not. This only checks for `Deref`,
723
+ // not `DerefPure`: we require that too, but we want a trait error if it's missing.
724
+ && let Some ( deref_trait) = self . tcx . lang_items ( ) . deref_trait ( )
725
+ && self . type_implements_trait ( deref_trait, [ expected] , self . param_env ) . may_apply ( )
726
+ {
727
+ true
728
+ } else {
729
+ false
730
+ }
731
+ }
732
+
723
733
fn check_pat_expr_unadjusted ( & self , lt : & ' tcx hir:: PatExpr < ' tcx > ) -> Ty < ' tcx > {
724
734
let ty = match & lt. kind {
725
735
rustc_hir:: PatExprKind :: Lit { lit, negated } => {
0 commit comments