@@ -503,8 +503,37 @@ impl<'a, 'gcx, 'tcx> MemCategorizationContext<'a, 'gcx, 'tcx> {
503
503
self . resolve_type_vars_or_error ( expr. hir_id , self . tables . expr_ty_adjusted_opt ( expr) )
504
504
}
505
505
506
+ /// Returns the type of value that this pattern matches against.
507
+ /// Some non-obvious cases:
508
+ ///
509
+ /// - a `ref x` binding matches against a value of type `T` and gives
510
+ /// `x` the type `&T`; we return `T`.
511
+ /// - a pattern with implicit derefs (thanks to default binding
512
+ /// modes #42640) may look like `Some(x)` but in fact have
513
+ /// implicit deref patterns attached (e.g., it is really
514
+ /// `&Some(x)`). In that case, we return the "outermost" type
515
+ /// (e.g., `&Option<T>).
506
516
fn pat_ty ( & self , pat : & hir:: Pat ) -> McResult < Ty < ' tcx > > {
517
+ // Check for implicit `&` types wrapping the pattern; note
518
+ // that these are never attached to binding patterns, so
519
+ // actually this is somewhat "disjoint" from the code below
520
+ // that aims to account for `ref x`.
521
+ if let Some ( vec) = self . tables . pat_adjustments ( ) . get ( pat. hir_id ) {
522
+ if let Some ( first_ty) = vec. first ( ) {
523
+ debug ! ( "pat_ty(pat={:?}) found adjusted ty `{:?}`" , pat, first_ty) ;
524
+ return Ok ( first_ty) ;
525
+ }
526
+ }
527
+
528
+ self . pat_ty_unadjusted ( pat)
529
+ }
530
+
531
+
532
+ /// Like `pat_ty`, but ignores implicit `&` patterns.
533
+ fn pat_ty_unadjusted ( & self , pat : & hir:: Pat ) -> McResult < Ty < ' tcx > > {
507
534
let base_ty = self . node_ty ( pat. hir_id ) ?;
535
+ debug ! ( "pat_ty(pat={:?}) base_ty={:?}" , pat, base_ty) ;
536
+
508
537
// This code detects whether we are looking at a `ref x`,
509
538
// and if so, figures out what the type *being borrowed* is.
510
539
let ret_ty = match pat. node {
@@ -531,8 +560,8 @@ impl<'a, 'gcx, 'tcx> MemCategorizationContext<'a, 'gcx, 'tcx> {
531
560
}
532
561
_ => base_ty,
533
562
} ;
534
- debug ! ( "pat_ty(pat={:?}) base_ty={:?} ret_ty={:?}" ,
535
- pat , base_ty , ret_ty ) ;
563
+ debug ! ( "pat_ty(pat={:?}) ret_ty={:?}" , pat , ret_ty ) ;
564
+
536
565
Ok ( ret_ty)
537
566
}
538
567
@@ -1246,7 +1275,7 @@ impl<'a, 'gcx, 'tcx> MemCategorizationContext<'a, 'gcx, 'tcx> {
1246
1275
self . tcx . adt_def ( enum_def) . variant_with_id ( def_id) . fields . len ( ) )
1247
1276
}
1248
1277
Def :: StructCtor ( _, CtorKind :: Fn ) => {
1249
- match self . pat_ty ( & pat) ?. sty {
1278
+ match self . pat_ty_unadjusted ( & pat) ?. sty {
1250
1279
ty:: TyAdt ( adt_def, _) => {
1251
1280
( cmt, adt_def. non_enum_variant ( ) . fields . len ( ) )
1252
1281
}
@@ -1297,7 +1326,7 @@ impl<'a, 'gcx, 'tcx> MemCategorizationContext<'a, 'gcx, 'tcx> {
1297
1326
1298
1327
PatKind :: Tuple ( ref subpats, ddpos) => {
1299
1328
// (p1, ..., pN)
1300
- let expected_len = match self . pat_ty ( & pat) ?. sty {
1329
+ let expected_len = match self . pat_ty_unadjusted ( & pat) ?. sty {
1301
1330
ty:: TyTuple ( ref tys) => tys. len ( ) ,
1302
1331
ref ty => span_bug ! ( pat. span, "tuple pattern unexpected type {:?}" , ty) ,
1303
1332
} ;
0 commit comments