@@ -318,6 +318,25 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
318
318
/// Conversely, inside this module, `check_pat_top` should never be used.
319
319
#[ instrument( level = "debug" , skip( self , pat_info) ) ]
320
320
fn check_pat ( & self , pat : & ' tcx Pat < ' tcx > , expected : Ty < ' tcx > , pat_info : PatInfo < ' tcx > ) {
321
+ let opt_path_res = match pat. kind {
322
+ PatKind :: Expr ( PatExpr { kind : PatExprKind :: Path ( qpath) , hir_id, span } ) => {
323
+ Some ( self . resolve_ty_and_res_fully_qualified_call ( qpath, * hir_id, * span) )
324
+ }
325
+ _ => None ,
326
+ } ;
327
+ let adjust_mode = self . calc_adjust_mode ( pat, opt_path_res. map ( |( res, ..) | res) ) ;
328
+ self . check_pat_inner ( pat, opt_path_res, adjust_mode, expected, pat_info) ;
329
+ }
330
+
331
+ // Helper to avoid resolving the same path pattern several times.
332
+ fn check_pat_inner (
333
+ & self ,
334
+ pat : & ' tcx Pat < ' tcx > ,
335
+ opt_path_res : Option < ( Res , Option < LoweredTy < ' tcx > > , & ' tcx [ hir:: PathSegment < ' tcx > ] ) > ,
336
+ adjust_mode : AdjustMode ,
337
+ expected : Ty < ' tcx > ,
338
+ pat_info : PatInfo < ' tcx > ,
339
+ ) {
321
340
let PatInfo { binding_mode, max_ref_mutbl, top_info : ti, current_depth, .. } = pat_info;
322
341
#[ cfg( debug_assertions) ]
323
342
if binding_mode == ByRef :: Yes ( Mutability :: Mut )
@@ -327,34 +346,20 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
327
346
span_bug ! ( pat. span, "Pattern mutability cap violated!" ) ;
328
347
}
329
348
330
- let path_res = match pat. kind {
331
- PatKind :: Expr ( PatExpr { kind : PatExprKind :: Path ( qpath) , hir_id, span } ) => {
332
- Some ( self . resolve_ty_and_res_fully_qualified_call ( qpath, * hir_id, * span) )
333
- }
334
- _ => None ,
335
- } ;
336
- let adjust_mode = self . calc_adjust_mode ( pat, path_res. map ( |( res, ..) | res) ) ;
337
349
let ( expected, binding_mode, max_ref_mutbl) = match adjust_mode {
338
350
// When we perform destructuring assignment, we disable default match bindings, which
339
351
// are unintuitive in this context.
340
352
_ if !pat. default_binding_modes => ( expected, ByRef :: No , MutblCap :: Mut ) ,
341
353
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.
354
+ // Peel an immediately nested `& mut?` from the expected type if possible and return the
355
+ // new expected type and binding default binding mode.
345
356
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.
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.
355
360
//
356
- // See the examples in `ui/match-defbm*.rs `.
357
- while let ty:: Ref ( _, inner_ty, inner_mutability) = * expected. kind ( ) {
361
+ // See the examples in `tests/ ui/rfcs/rfc-2005-default-binding-mode `.
362
+ if let ty:: Ref ( _, inner_ty, inner_mutability) = * expected. kind ( ) {
358
363
debug ! ( "inspecting {:?}" , expected) ;
359
364
360
365
debug ! ( "current discriminant is Ref, inserting implicit deref" ) ;
@@ -366,8 +371,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
366
371
. or_default ( )
367
372
. push ( expected) ;
368
373
369
- expected = self . try_structurally_resolve_type ( pat. span , inner_ty) ;
370
- binding_mode = ByRef :: Yes ( match binding_mode {
374
+ let mut binding_mode = ByRef :: Yes ( match binding_mode {
371
375
// If default binding mode is by value, make it `ref` or `ref mut`
372
376
// (depending on whether we observe `&` or `&mut`).
373
377
ByRef :: No |
@@ -377,18 +381,26 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
377
381
// This is because a `& &mut` cannot mutate the underlying value.
378
382
ByRef :: Yes ( Mutability :: Not ) => Mutability :: Not ,
379
383
} ) ;
380
- }
381
384
382
- if self . downgrade_mut_inside_shared ( ) {
383
- binding_mode = binding_mode. cap_ref_mutability ( max_ref_mutbl. as_mutbl ( ) ) ;
384
- }
385
- if binding_mode == ByRef :: Yes ( Mutability :: Not ) {
386
- max_ref_mutbl = MutblCap :: Not ;
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)
387
403
}
388
-
389
- debug ! ( "default binding mode is now {:?}" , binding_mode) ;
390
-
391
- ( expected, binding_mode, max_ref_mutbl)
392
404
}
393
405
} ;
394
406
let pat_info = PatInfo {
@@ -409,7 +421,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
409
421
pat. hir_id ,
410
422
* span,
411
423
qpath,
412
- path_res . unwrap ( ) ,
424
+ opt_path_res . unwrap ( ) ,
413
425
expected,
414
426
& pat_info. top_info ,
415
427
) ;
0 commit comments