@@ -503,8 +503,37 @@ impl<'a, 'gcx, 'tcx> MemCategorizationContext<'a, 'gcx, 'tcx> {
503503 self . resolve_type_vars_or_error ( expr. hir_id , self . tables . expr_ty_adjusted_opt ( expr) )
504504 }
505505
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>).
506516 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 > > {
507534 let base_ty = self . node_ty ( pat. hir_id ) ?;
535+ debug ! ( "pat_ty(pat={:?}) base_ty={:?}" , pat, base_ty) ;
536+
508537 // This code detects whether we are looking at a `ref x`,
509538 // and if so, figures out what the type *being borrowed* is.
510539 let ret_ty = match pat. node {
@@ -531,8 +560,8 @@ impl<'a, 'gcx, 'tcx> MemCategorizationContext<'a, 'gcx, 'tcx> {
531560 }
532561 _ => base_ty,
533562 } ;
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+
536565 Ok ( ret_ty)
537566 }
538567
@@ -1246,7 +1275,7 @@ impl<'a, 'gcx, 'tcx> MemCategorizationContext<'a, 'gcx, 'tcx> {
12461275 self . tcx . adt_def ( enum_def) . variant_with_id ( def_id) . fields . len ( ) )
12471276 }
12481277 Def :: StructCtor ( _, CtorKind :: Fn ) => {
1249- match self . pat_ty ( & pat) ?. sty {
1278+ match self . pat_ty_unadjusted ( & pat) ?. sty {
12501279 ty:: TyAdt ( adt_def, _) => {
12511280 ( cmt, adt_def. non_enum_variant ( ) . fields . len ( ) )
12521281 }
@@ -1297,7 +1326,7 @@ impl<'a, 'gcx, 'tcx> MemCategorizationContext<'a, 'gcx, 'tcx> {
12971326
12981327 PatKind :: Tuple ( ref subpats, ddpos) => {
12991328 // (p1, ..., pN)
1300- let expected_len = match self . pat_ty ( & pat) ?. sty {
1329+ let expected_len = match self . pat_ty_unadjusted ( & pat) ?. sty {
13011330 ty:: TyTuple ( ref tys) => tys. len ( ) ,
13021331 ref ty => span_bug ! ( pat. span, "tuple pattern unexpected type {:?}" , ty) ,
13031332 } ;
0 commit comments