@@ -111,50 +111,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
111111 self . check_pat_box ( pat. span , inner, expected, def_bm, discrim_span)
112112 }
113113 PatKind :: Ref ( ref inner, mutbl) => {
114- let expected = self . shallow_resolve ( expected) ;
115- if self . check_dereferencable ( pat. span , expected, & inner) {
116- // `demand::subtype` would be good enough, but using
117- // `eqtype` turns out to be equally general. See (*)
118- // below for details.
119-
120- // Take region, inner-type from expected type if we
121- // can, to avoid creating needless variables. This
122- // also helps with the bad interactions of the given
123- // hack detailed in (*) below.
124- debug ! ( "check_pat_walk: expected={:?}" , expected) ;
125- let ( rptr_ty, inner_ty) = match expected. sty {
126- ty:: Ref ( _, r_ty, r_mutbl) if r_mutbl == mutbl => {
127- ( expected, r_ty)
128- }
129- _ => {
130- let inner_ty = self . next_ty_var (
131- TypeVariableOrigin {
132- kind : TypeVariableOriginKind :: TypeInference ,
133- span : inner. span ,
134- }
135- ) ;
136- let mt = ty:: TypeAndMut { ty : inner_ty, mutbl : mutbl } ;
137- let region = self . next_region_var ( infer:: PatternRegion ( pat. span ) ) ;
138- let rptr_ty = tcx. mk_ref ( region, mt) ;
139- debug ! ( "check_pat_walk: demanding {:?} = {:?}" , expected, rptr_ty) ;
140- let err = self . demand_eqtype_diag ( pat. span , expected, rptr_ty) ;
141-
142- // Look for a case like `fn foo(&foo: u32)` and suggest
143- // `fn foo(foo: &u32)`
144- if let Some ( mut err) = err {
145- self . borrow_pat_suggestion ( & mut err, & pat, & inner, & expected) ;
146- err. emit ( ) ;
147- }
148- ( rptr_ty, inner_ty)
149- }
150- } ;
151-
152- self . check_pat_walk ( & inner, inner_ty, def_bm, discrim_span) ;
153- rptr_ty
154- } else {
155- self . check_pat_walk ( & inner, tcx. types . err , def_bm, discrim_span) ;
156- tcx. types . err
157- }
114+ self . check_pat_ref ( pat, inner, mutbl, expected, def_bm, discrim_span)
158115 }
159116 PatKind :: Slice ( ref before, ref slice, ref after) => {
160117 let expected_ty = self . structurally_resolved_type ( pat. span , expected) ;
@@ -1059,4 +1016,58 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
10591016 tcx. types . err
10601017 }
10611018 }
1019+
1020+ fn check_pat_ref (
1021+ & self ,
1022+ pat : & hir:: Pat ,
1023+ inner : & ' tcx hir:: Pat ,
1024+ mutbl : hir:: Mutability ,
1025+ expected : Ty < ' tcx > ,
1026+ def_bm : ty:: BindingMode ,
1027+ discrim_span : Option < Span > ,
1028+ ) -> Ty < ' tcx > {
1029+ let tcx = self . tcx ;
1030+ let expected = self . shallow_resolve ( expected) ;
1031+ if self . check_dereferencable ( pat. span , expected, & inner) {
1032+ // `demand::subtype` would be good enough, but using `eqtype` turns
1033+ // out to be equally general. See (*) below for details.
1034+
1035+ // Take region, inner-type from expected type if we can,
1036+ // to avoid creating needless variables. This also helps with
1037+ // the bad interactions of the given hack detailed in (*) below.
1038+ debug ! ( "check_pat_ref: expected={:?}" , expected) ;
1039+ let ( rptr_ty, inner_ty) = match expected. sty {
1040+ ty:: Ref ( _, r_ty, r_mutbl) if r_mutbl == mutbl => {
1041+ ( expected, r_ty)
1042+ }
1043+ _ => {
1044+ let inner_ty = self . next_ty_var (
1045+ TypeVariableOrigin {
1046+ kind : TypeVariableOriginKind :: TypeInference ,
1047+ span : inner. span ,
1048+ }
1049+ ) ;
1050+ let mt = ty:: TypeAndMut { ty : inner_ty, mutbl } ;
1051+ let region = self . next_region_var ( infer:: PatternRegion ( pat. span ) ) ;
1052+ let rptr_ty = tcx. mk_ref ( region, mt) ;
1053+ debug ! ( "check_pat_ref: demanding {:?} = {:?}" , expected, rptr_ty) ;
1054+ let err = self . demand_eqtype_diag ( pat. span , expected, rptr_ty) ;
1055+
1056+ // Look for a case like `fn foo(&foo: u32)` and suggest
1057+ // `fn foo(foo: &u32)`
1058+ if let Some ( mut err) = err {
1059+ self . borrow_pat_suggestion ( & mut err, & pat, & inner, & expected) ;
1060+ err. emit ( ) ;
1061+ }
1062+ ( rptr_ty, inner_ty)
1063+ }
1064+ } ;
1065+
1066+ self . check_pat_walk ( & inner, inner_ty, def_bm, discrim_span) ;
1067+ rptr_ty
1068+ } else {
1069+ self . check_pat_walk ( & inner, tcx. types . err , def_bm, discrim_span) ;
1070+ tcx. types . err
1071+ }
1072+ }
10621073}
0 commit comments