@@ -337,7 +337,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
337337 expected : Ty < ' tcx > ,
338338 pat_info : PatInfo < ' tcx > ,
339339 ) {
340- let PatInfo { binding_mode, max_ref_mutbl , top_info : ti , current_depth, .. } = pat_info;
340+ let PatInfo { mut binding_mode, mut max_ref_mutbl , current_depth, .. } = pat_info;
341341 #[ cfg( debug_assertions) ]
342342 if binding_mode == ByRef :: Yes ( Mutability :: Mut )
343343 && max_ref_mutbl != MutblCap :: Mut
@@ -346,72 +346,76 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
346346 span_bug ! ( pat. span, "Pattern mutability cap violated!" ) ;
347347 }
348348
349- let ( expected , binding_mode , max_ref_mutbl ) = match adjust_mode {
349+ if !pat . default_binding_modes {
350350 // When we perform destructuring assignment, we disable default match bindings, which
351351 // are unintuitive in this context.
352- _ if !pat. default_binding_modes => ( expected, ByRef :: No , MutblCap :: Mut ) ,
353- AdjustMode :: Pass => ( expected, binding_mode, max_ref_mutbl) ,
354- // Peel an immediately nested `& mut?` from the expected type if possible and return the
355- // new expected type and binding default binding mode.
356- AdjustMode :: Peel => {
357- let expected = self . try_structurally_resolve_type ( pat. span , expected) ;
358- // Peel off a `&` or `&mut` from the scrutinee type. For each ampersand peeled off,
359- // update the binding mode and push the original type into the adjustments vector.
360- //
361- // See the examples in `tests/ui/rfcs/rfc-2005-default-binding-mode`.
362- if let ty:: Ref ( _, inner_ty, inner_mutability) = * expected. kind ( ) {
363- debug ! ( "inspecting {:?}" , expected) ;
364-
365- debug ! ( "current discriminant is Ref, inserting implicit deref" ) ;
366- // Preserve the reference type. We'll need it later during THIR lowering.
367- self . typeck_results
368- . borrow_mut ( )
369- . pat_adjustments_mut ( )
370- . entry ( pat. hir_id )
371- . or_default ( )
372- . push ( expected) ;
373-
374- let mut binding_mode = ByRef :: Yes ( match binding_mode {
375- // If default binding mode is by value, make it `ref` or `ref mut`
376- // (depending on whether we observe `&` or `&mut`).
377- ByRef :: No |
378- // When `ref mut`, stay a `ref mut` (on `&mut`) or downgrade to `ref` (on `&`).
379- ByRef :: Yes ( Mutability :: Mut ) => inner_mutability,
380- // Once a `ref`, always a `ref`.
381- // This is because a `& &mut` cannot mutate the underlying value.
382- ByRef :: Yes ( Mutability :: Not ) => Mutability :: Not ,
383- } ) ;
384-
385- if self . downgrade_mut_inside_shared ( ) {
386- binding_mode = binding_mode. cap_ref_mutability ( max_ref_mutbl. as_mutbl ( ) ) ;
387- }
388- let mut max_ref_mutbl = max_ref_mutbl;
389- if binding_mode == ByRef :: Yes ( Mutability :: Not ) {
390- max_ref_mutbl = MutblCap :: Not ;
391- }
392- debug ! ( "default binding mode is now {:?}" , binding_mode) ;
393- let pat_info = PatInfo { binding_mode, max_ref_mutbl, ..pat_info } ;
394- return self . check_pat_inner (
395- pat,
396- opt_path_res,
397- adjust_mode,
398- inner_ty,
399- pat_info,
400- ) ;
401- } else {
402- ( expected, binding_mode, max_ref_mutbl)
403- }
404- }
352+ binding_mode = ByRef :: No ;
353+ max_ref_mutbl = MutblCap :: Mut ;
354+ } ;
355+ // Resolve type if needed.
356+ let expected = if let AdjustMode :: Peel = adjust_mode
357+ && pat. default_binding_modes
358+ {
359+ self . try_structurally_resolve_type ( pat. span , expected)
360+ } else {
361+ expected
405362 } ;
363+ let old_pat_info = pat_info;
406364 let pat_info = PatInfo {
407365 binding_mode,
408366 max_ref_mutbl,
409- top_info : ti,
410- decl_origin : pat_info. decl_origin ,
411367 current_depth : current_depth + 1 ,
368+ top_info : old_pat_info. top_info ,
369+ decl_origin : old_pat_info. decl_origin ,
412370 } ;
413371
414372 let ty = match pat. kind {
373+ // Peel off a `&` or `&mut` from the scrutinee type. See the examples in
374+ // `tests/ui/rfcs/rfc-2005-default-binding-mode`.
375+ _ if let AdjustMode :: Peel = adjust_mode
376+ && pat. default_binding_modes
377+ && let ty:: Ref ( _, inner_ty, inner_mutability) = * expected. kind ( ) =>
378+ {
379+ debug ! ( "inspecting {:?}" , expected) ;
380+
381+ debug ! ( "current discriminant is Ref, inserting implicit deref" ) ;
382+ // Preserve the reference type. We'll need it later during THIR lowering.
383+ self . typeck_results
384+ . borrow_mut ( )
385+ . pat_adjustments_mut ( )
386+ . entry ( pat. hir_id )
387+ . or_default ( )
388+ . push ( expected) ;
389+
390+ binding_mode = ByRef :: Yes ( match binding_mode {
391+ // If default binding mode is by value, make it `ref` or `ref mut`
392+ // (depending on whether we observe `&` or `&mut`).
393+ ByRef :: No |
394+ // When `ref mut`, stay a `ref mut` (on `&mut`) or downgrade to `ref` (on `&`).
395+ ByRef :: Yes ( Mutability :: Mut ) => inner_mutability,
396+ // Once a `ref`, always a `ref`.
397+ // This is because a `& &mut` cannot mutate the underlying value.
398+ ByRef :: Yes ( Mutability :: Not ) => Mutability :: Not ,
399+ } ) ;
400+
401+ if self . downgrade_mut_inside_shared ( ) {
402+ binding_mode = binding_mode. cap_ref_mutability ( max_ref_mutbl. as_mutbl ( ) ) ;
403+ }
404+ if binding_mode == ByRef :: Yes ( Mutability :: Not ) {
405+ max_ref_mutbl = MutblCap :: Not ;
406+ }
407+ debug ! ( "default binding mode is now {:?}" , binding_mode) ;
408+
409+ // Use the old pat info to keep `current_depth` to its old value.
410+ let new_pat_info = PatInfo { binding_mode, max_ref_mutbl, ..old_pat_info } ;
411+ return self . check_pat_inner (
412+ pat,
413+ opt_path_res,
414+ adjust_mode,
415+ inner_ty,
416+ new_pat_info,
417+ ) ;
418+ }
415419 PatKind :: Missing | PatKind :: Wild | PatKind :: Err ( _) => expected,
416420 // We allow any type here; we ensure that the type is uninhabited during match checking.
417421 PatKind :: Never => expected,
0 commit comments