@@ -163,9 +163,6 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
163163enum AdjustMode {
164164 /// Peel off all immediate reference types.
165165 Peel ,
166- /// Reset binding mode to the initial mode.
167- /// Used for destructuring assignment, where we don't want any match ergonomics.
168- Reset ,
169166 /// Pass on the input binding mode and expected type.
170167 Pass ,
171168}
@@ -322,6 +319,13 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
322319 #[ instrument( level = "debug" , skip( self , pat_info) ) ]
323320 fn check_pat ( & self , pat : & ' tcx Pat < ' tcx > , expected : Ty < ' tcx > , pat_info : PatInfo < ' tcx > ) {
324321 let PatInfo { binding_mode, max_ref_mutbl, top_info : ti, current_depth, .. } = pat_info;
322+ #[ cfg( debug_assertions) ]
323+ if binding_mode == ByRef :: Yes ( Mutability :: Mut )
324+ && max_ref_mutbl != MutblCap :: Mut
325+ && self . downgrade_mut_inside_shared ( )
326+ {
327+ span_bug ! ( pat. span, "Pattern mutability cap violated!" ) ;
328+ }
325329
326330 let path_res = match pat. kind {
327331 PatKind :: Expr ( PatExpr { kind : PatExprKind :: Path ( qpath) , hir_id, span } ) => {
@@ -330,8 +334,65 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
330334 _ => None ,
331335 } ;
332336 let adjust_mode = self . calc_adjust_mode ( pat, path_res. map ( |( res, ..) | res) ) ;
333- let ( expected, binding_mode, max_ref_mutbl) =
334- self . calc_default_binding_mode ( pat, expected, binding_mode, adjust_mode, max_ref_mutbl) ;
337+ let ( expected, binding_mode, max_ref_mutbl) = match adjust_mode {
338+ // When we perform destructuring assignment, we disable default match bindings, which
339+ // are unintuitive in this context.
340+ _ if !pat. default_binding_modes => ( expected, ByRef :: No , MutblCap :: Mut ) ,
341+ AdjustMode :: Pass => ( expected, binding_mode, max_ref_mutbl) ,
342+ // Peel off as many immediately nested `& mut?` from the expected type as possible
343+ // and return the new expected type and binding default binding mode.
344+ // The adjustments vector, if non-empty is stored in a table.
345+ AdjustMode :: Peel => {
346+ let mut binding_mode = binding_mode;
347+ let mut max_ref_mutbl = max_ref_mutbl;
348+ let mut expected = self . try_structurally_resolve_type ( pat. span , expected) ;
349+ // Peel off as many `&` or `&mut` from the scrutinee type as possible. For example,
350+ // for `match &&&mut Some(5)` the loop runs three times, aborting when it reaches
351+ // the `Some(5)` which is not of type Ref.
352+ //
353+ // For each ampersand peeled off, update the binding mode and push the original
354+ // type into the adjustments vector.
355+ //
356+ // See the examples in `ui/match-defbm*.rs`.
357+ let mut pat_adjustments = vec ! [ ] ;
358+ while let ty:: Ref ( _, inner_ty, inner_mutability) = * expected. kind ( ) {
359+ debug ! ( "inspecting {:?}" , expected) ;
360+
361+ debug ! ( "current discriminant is Ref, inserting implicit deref" ) ;
362+ // Preserve the reference type. We'll need it later during THIR lowering.
363+ pat_adjustments. push ( expected) ;
364+
365+ expected = self . try_structurally_resolve_type ( pat. span , inner_ty) ;
366+ binding_mode = ByRef :: Yes ( match binding_mode {
367+ // If default binding mode is by value, make it `ref` or `ref mut`
368+ // (depending on whether we observe `&` or `&mut`).
369+ ByRef :: No |
370+ // When `ref mut`, stay a `ref mut` (on `&mut`) or downgrade to `ref` (on `&`).
371+ ByRef :: Yes ( Mutability :: Mut ) => inner_mutability,
372+ // Once a `ref`, always a `ref`.
373+ // This is because a `& &mut` cannot mutate the underlying value.
374+ ByRef :: Yes ( Mutability :: Not ) => Mutability :: Not ,
375+ } ) ;
376+ }
377+
378+ if self . downgrade_mut_inside_shared ( ) {
379+ binding_mode = binding_mode. cap_ref_mutability ( max_ref_mutbl. as_mutbl ( ) ) ;
380+ }
381+ if binding_mode == ByRef :: Yes ( Mutability :: Not ) {
382+ max_ref_mutbl = MutblCap :: Not ;
383+ }
384+
385+ if !pat_adjustments. is_empty ( ) {
386+ debug ! ( "default binding mode is now {:?}" , binding_mode) ;
387+ self . typeck_results
388+ . borrow_mut ( )
389+ . pat_adjustments_mut ( )
390+ . insert ( pat. hir_id , pat_adjustments) ;
391+ }
392+
393+ ( expected, binding_mode, max_ref_mutbl)
394+ }
395+ } ;
335396 let pat_info = PatInfo {
336397 binding_mode,
337398 max_ref_mutbl,
@@ -437,39 +498,10 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
437498 // `regions-relate-bound-regions-on-closures-to-inference-variables.rs`,
438499 }
439500
440- /// Compute the new expected type and default binding mode from the old ones
441- /// as well as the pattern form we are currently checking.
442- fn calc_default_binding_mode (
443- & self ,
444- pat : & ' tcx Pat < ' tcx > ,
445- expected : Ty < ' tcx > ,
446- def_br : ByRef ,
447- adjust_mode : AdjustMode ,
448- max_ref_mutbl : MutblCap ,
449- ) -> ( Ty < ' tcx > , ByRef , MutblCap ) {
450- #[ cfg( debug_assertions) ]
451- if def_br == ByRef :: Yes ( Mutability :: Mut )
452- && max_ref_mutbl != MutblCap :: Mut
453- && self . downgrade_mut_inside_shared ( )
454- {
455- span_bug ! ( pat. span, "Pattern mutability cap violated!" ) ;
456- }
457- match adjust_mode {
458- AdjustMode :: Pass => ( expected, def_br, max_ref_mutbl) ,
459- AdjustMode :: Reset => ( expected, ByRef :: No , MutblCap :: Mut ) ,
460- AdjustMode :: Peel => self . peel_off_references ( pat, expected, def_br, max_ref_mutbl) ,
461- }
462- }
463-
464501 /// How should the binding mode and expected type be adjusted?
465502 ///
466503 /// When the pattern is a path pattern, `opt_path_res` must be `Some(res)`.
467504 fn calc_adjust_mode ( & self , pat : & ' tcx Pat < ' tcx > , opt_path_res : Option < Res > ) -> AdjustMode {
468- // When we perform destructuring assignment, we disable default match bindings, which are
469- // unintuitive in this context.
470- if !pat. default_binding_modes {
471- return AdjustMode :: Reset ;
472- }
473505 match & pat. kind {
474506 // Type checking these product-like types successfully always require
475507 // that the expected type be of those types and not reference types.
@@ -526,64 +558,6 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
526558 }
527559 }
528560
529- /// Peel off as many immediately nested `& mut?` from the expected type as possible
530- /// and return the new expected type and binding default binding mode.
531- /// The adjustments vector, if non-empty is stored in a table.
532- fn peel_off_references (
533- & self ,
534- pat : & ' tcx Pat < ' tcx > ,
535- expected : Ty < ' tcx > ,
536- mut def_br : ByRef ,
537- mut max_ref_mutbl : MutblCap ,
538- ) -> ( Ty < ' tcx > , ByRef , MutblCap ) {
539- let mut expected = self . try_structurally_resolve_type ( pat. span , expected) ;
540- // Peel off as many `&` or `&mut` from the scrutinee type as possible. For example,
541- // for `match &&&mut Some(5)` the loop runs three times, aborting when it reaches
542- // the `Some(5)` which is not of type Ref.
543- //
544- // For each ampersand peeled off, update the binding mode and push the original
545- // type into the adjustments vector.
546- //
547- // See the examples in `ui/match-defbm*.rs`.
548- let mut pat_adjustments = vec ! [ ] ;
549- while let ty:: Ref ( _, inner_ty, inner_mutability) = * expected. kind ( ) {
550- debug ! ( "inspecting {:?}" , expected) ;
551-
552- debug ! ( "current discriminant is Ref, inserting implicit deref" ) ;
553- // Preserve the reference type. We'll need it later during THIR lowering.
554- pat_adjustments. push ( expected) ;
555-
556- expected = self . try_structurally_resolve_type ( pat. span , inner_ty) ;
557- def_br = ByRef :: Yes ( match def_br {
558- // If default binding mode is by value, make it `ref` or `ref mut`
559- // (depending on whether we observe `&` or `&mut`).
560- ByRef :: No |
561- // When `ref mut`, stay a `ref mut` (on `&mut`) or downgrade to `ref` (on `&`).
562- ByRef :: Yes ( Mutability :: Mut ) => inner_mutability,
563- // Once a `ref`, always a `ref`.
564- // This is because a `& &mut` cannot mutate the underlying value.
565- ByRef :: Yes ( Mutability :: Not ) => Mutability :: Not ,
566- } ) ;
567- }
568-
569- if self . downgrade_mut_inside_shared ( ) {
570- def_br = def_br. cap_ref_mutability ( max_ref_mutbl. as_mutbl ( ) ) ;
571- }
572- if def_br == ByRef :: Yes ( Mutability :: Not ) {
573- max_ref_mutbl = MutblCap :: Not ;
574- }
575-
576- if !pat_adjustments. is_empty ( ) {
577- debug ! ( "default binding mode is now {:?}" , def_br) ;
578- self . typeck_results
579- . borrow_mut ( )
580- . pat_adjustments_mut ( )
581- . insert ( pat. hir_id , pat_adjustments) ;
582- }
583-
584- ( expected, def_br, max_ref_mutbl)
585- }
586-
587561 fn check_pat_expr_unadjusted ( & self , lt : & ' tcx hir:: PatExpr < ' tcx > ) -> Ty < ' tcx > {
588562 let ty = match & lt. kind {
589563 rustc_hir:: PatExprKind :: Lit { lit, negated } => {
0 commit comments