@@ -14,6 +14,7 @@ use rustc_hir::{
14
14
self as hir, BindingMode , ByRef , ExprKind , HirId , LangItem , Mutability , Pat , PatExpr ,
15
15
PatExprKind , PatKind , expr_needs_parens,
16
16
} ;
17
+ use rustc_hir_analysis:: autoderef:: report_autoderef_recursion_limit_error;
17
18
use rustc_infer:: infer;
18
19
use rustc_middle:: traits:: PatternOriginExpr ;
19
20
use rustc_middle:: ty:: { self , AdtDef , Ty , TypeVisitableExt } ;
@@ -551,17 +552,28 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
551
552
debug ! ( "scrutinee ty {expected:?} is a smart pointer, inserting overloaded deref" ) ;
552
553
// The scrutinee is a smart pointer; implicitly dereference it. This adds a
553
554
// requirement that `expected: DerefPure`.
554
- let inner_ty = self . deref_pat_target ( pat. span , expected) ;
555
+ let mut inner_ty = self . deref_pat_target ( pat. span , expected) ;
555
556
// Once we've checked `pat`, we'll add a `DerefMut` bound if it contains any
556
557
// `ref mut` bindings. See `Self::register_deref_mut_bounds_if_needed`.
557
558
558
- // Preserve the smart pointer type for THIR lowering and upvar analysis.
559
- self . typeck_results
560
- . borrow_mut ( )
561
- . pat_adjustments_mut ( )
562
- . entry ( pat. hir_id )
563
- . or_default ( )
564
- . push ( PatAdjustment { kind : PatAdjust :: OverloadedDeref , source : expected } ) ;
559
+ let mut typeck_results = self . typeck_results . borrow_mut ( ) ;
560
+ let mut pat_adjustments_table = typeck_results. pat_adjustments_mut ( ) ;
561
+ let pat_adjustments = pat_adjustments_table. entry ( pat. hir_id ) . or_default ( ) ;
562
+ // We may reach the recursion limit if a user matches on a type `T` satisfying
563
+ // `T: Deref<Target = T>`; error gracefully in this case.
564
+ // FIXME(deref_patterns): If `deref_patterns` stabilizes, it may make sense to move
565
+ // this check out of this branch. Alternatively, this loop could be implemented with
566
+ // autoderef and this check removed. For now though, don't break code compiling on
567
+ // stable with lots of `&`s and a low recursion limit, if anyone's done that.
568
+ if self . tcx . recursion_limit ( ) . value_within_limit ( pat_adjustments. len ( ) ) {
569
+ // Preserve the smart pointer type for THIR lowering and closure upvar analysis.
570
+ pat_adjustments
571
+ . push ( PatAdjustment { kind : PatAdjust :: OverloadedDeref , source : expected } ) ;
572
+ } else {
573
+ let guar = report_autoderef_recursion_limit_error ( self . tcx , pat. span , expected) ;
574
+ inner_ty = Ty :: new_error ( self . tcx , guar) ;
575
+ }
576
+ drop ( typeck_results) ;
565
577
566
578
// Recurse, using the old pat info to keep `current_depth` to its old value.
567
579
// Peeling smart pointers does not update the default binding mode.
0 commit comments