@@ -77,53 +77,8 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
7777 }
7878 }
7979 PatKind :: Binding ( ba, var_id, _, ref sub) => {
80- let bm = if ba == hir:: BindingAnnotation :: Unannotated {
81- def_bm
82- } else {
83- ty:: BindingMode :: convert ( ba)
84- } ;
85- self . inh
86- . tables
87- . borrow_mut ( )
88- . pat_binding_modes_mut ( )
89- . insert ( pat. hir_id , bm) ;
90- debug ! ( "check_pat_walk: pat.hir_id={:?} bm={:?}" , pat. hir_id, bm) ;
91- let local_ty = self . local_ty ( pat. span , pat. hir_id ) . decl_ty ;
92- match bm {
93- ty:: BindByReference ( mutbl) => {
94- // If the binding is like
95- // ref x | ref const x | ref mut x
96- // then `x` is assigned a value of type `&M T` where M is the mutability
97- // and T is the expected type.
98- let region_var = self . next_region_var ( infer:: PatternRegion ( pat. span ) ) ;
99- let mt = ty:: TypeAndMut { ty : expected, mutbl : mutbl } ;
100- let region_ty = tcx. mk_ref ( region_var, mt) ;
101-
102- // `x` is assigned a value of type `&M T`, hence `&M T <: typeof(x)` is
103- // required. However, we use equality, which is stronger. See (*) for
104- // an explanation.
105- self . demand_eqtype_pat ( pat. span , region_ty, local_ty, discrim_span) ;
106- }
107- // Otherwise, the type of x is the expected type `T`.
108- ty:: BindByValue ( _) => {
109- // As above, `T <: typeof(x)` is required, but we
110- // use equality, see (*) below.
111- self . demand_eqtype_pat ( pat. span , expected, local_ty, discrim_span) ;
112- }
113- }
114-
115- // If there are multiple arms, make sure they all agree on
116- // what the type of the binding `x` ought to be.
117- if var_id != pat. hir_id {
118- let vt = self . local_ty ( pat. span , var_id) . decl_ty ;
119- self . demand_eqtype_pat ( pat. span , vt, local_ty, discrim_span) ;
120- }
121-
122- if let Some ( ref p) = * sub {
123- self . check_pat_walk ( & p, expected, def_bm, discrim_span) ;
124- }
125-
126- local_ty
80+ let sub = sub. as_deref ( ) ;
81+ self . check_pat_ident ( pat, ba, var_id, sub, expected, def_bm, discrim_span)
12782 }
12883 PatKind :: TupleStruct ( ref qpath, ref subpats, ddpos) => {
12984 self . check_pat_tuple_struct (
@@ -611,6 +566,67 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
611566 Some ( common_type)
612567 }
613568
569+ fn check_pat_ident (
570+ & self ,
571+ pat : & hir:: Pat ,
572+ ba : hir:: BindingAnnotation ,
573+ var_id : hir:: HirId ,
574+ sub : Option < & ' tcx hir:: Pat > ,
575+ expected : Ty < ' tcx > ,
576+ def_bm : ty:: BindingMode ,
577+ discrim_span : Option < Span > ,
578+ ) -> Ty < ' tcx > {
579+ // Determine the binding mode...
580+ let bm = match ba {
581+ hir:: BindingAnnotation :: Unannotated => def_bm,
582+ _ => ty:: BindingMode :: convert ( ba) ,
583+ } ;
584+ // ...and store it in a side table:
585+ self . inh
586+ . tables
587+ . borrow_mut ( )
588+ . pat_binding_modes_mut ( )
589+ . insert ( pat. hir_id , bm) ;
590+
591+ debug ! ( "check_pat_ident: pat.hir_id={:?} bm={:?}" , pat. hir_id, bm) ;
592+
593+ let local_ty = self . local_ty ( pat. span , pat. hir_id ) . decl_ty ;
594+ let eq_ty = match bm {
595+ ty:: BindByReference ( mutbl) => {
596+ // If the binding is like `ref x | ref const x | ref mut x`
597+ // then `x` is assigned a value of type `&M T` where M is the
598+ // mutability and T is the expected type.
599+ let region_var = self . next_region_var ( infer:: PatternRegion ( pat. span ) ) ;
600+ let mt = ty:: TypeAndMut { ty : expected, mutbl } ;
601+ let region_ty = self . tcx . mk_ref ( region_var, mt) ;
602+
603+ // `x` is assigned a value of type `&M T`, hence `&M T <: typeof(x)`
604+ // is required. However, we use equality, which is stronger.
605+ // See (*) for an explanation.
606+ region_ty
607+ }
608+ // Otherwise, the type of x is the expected type `T`.
609+ ty:: BindByValue ( _) => {
610+ // As above, `T <: typeof(x)` is required, but we use equality, see (*) below.
611+ expected
612+ }
613+ } ;
614+ self . demand_eqtype_pat ( pat. span , eq_ty, local_ty, discrim_span) ;
615+
616+ // If there are multiple arms, make sure they all agree on
617+ // what the type of the binding `x` ought to be.
618+ if var_id != pat. hir_id {
619+ let vt = self . local_ty ( pat. span , var_id) . decl_ty ;
620+ self . demand_eqtype_pat ( pat. span , vt, local_ty, discrim_span) ;
621+ }
622+
623+ if let Some ( p) = sub {
624+ self . check_pat_walk ( & p, expected, def_bm, discrim_span) ;
625+ }
626+
627+ local_ty
628+ }
629+
614630 fn borrow_pat_suggestion (
615631 & self ,
616632 err : & mut DiagnosticBuilder < ' _ > ,
0 commit comments