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