@@ -14,6 +14,7 @@ use rustc_hir::{
1414 self as hir, BindingMode , ByRef , ExprKind , HirId , LangItem , Mutability , Pat , PatExpr ,
1515 PatExprKind , PatKind , expr_needs_parens,
1616} ;
17+ use rustc_hir_analysis:: autoderef:: report_autoderef_recursion_limit_error;
1718use rustc_infer:: infer;
1819use rustc_middle:: traits:: PatternOriginExpr ;
1920use rustc_middle:: ty:: { self , AdtDef , Ty , TypeVisitableExt } ;
@@ -551,17 +552,30 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
551552 debug ! ( "scrutinee ty {expected:?} is a smart pointer, inserting overloaded deref" ) ;
552553 // The scrutinee is a smart pointer; implicitly dereference it. This adds a
553554 // 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) ;
555556 // Once we've checked `pat`, we'll add a `DerefMut` bound if it contains any
556557 // `ref mut` bindings. See `Self::register_deref_mut_bounds_if_needed`.
557558
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+ // FIXME(deref_patterns): To allow moving out of boxes, set `kind` to
571+ // `PatAdjust::BuiltinDeref` when `expected.is_box()`.
572+ pat_adjustments
573+ . push ( PatAdjustment { kind : PatAdjust :: OverloadedDeref , source : expected } ) ;
574+ } else {
575+ let guar = report_autoderef_recursion_limit_error ( self . tcx , pat. span , expected) ;
576+ inner_ty = Ty :: new_error ( self . tcx , guar) ;
577+ }
578+ drop ( typeck_results) ;
565579
566580 // Recurse, using the old pat info to keep `current_depth` to its old value.
567581 // Peeling smart pointers does not update the default binding mode.
0 commit comments