@@ -15,6 +15,7 @@ use rustc_hir::{
15
15
self as hir, BindingMode , ByRef , ExprKind , HirId , LangItem , Mutability , Pat , PatExpr ,
16
16
PatExprKind , PatKind , expr_needs_parens,
17
17
} ;
18
+ use rustc_hir_analysis:: autoderef:: report_autoderef_recursion_limit_error;
18
19
use rustc_infer:: infer;
19
20
use rustc_middle:: traits:: PatternOriginExpr ;
20
21
use rustc_middle:: ty:: { self , Ty , TypeVisitableExt } ;
@@ -552,17 +553,28 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
552
553
debug ! ( "scrutinee ty {expected:?} is a smart pointer, inserting overloaded deref" ) ;
553
554
// The scrutinee is a smart pointer; implicitly dereference it. This adds a
554
555
// 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) ;
556
557
// Once we've checked `pat`, we'll add a `DerefMut` bound if it contains any
557
558
// `ref mut` bindings. See `Self::register_deref_mut_bounds_if_needed`.
558
559
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) ;
566
578
567
579
// Recurse, using the old pat info to keep `current_depth` to its old value.
568
580
// Peeling smart pointers does not update the default binding mode.
0 commit comments