@@ -111,50 +111,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
111
111
self . check_pat_box ( pat. span , inner, expected, def_bm, discrim_span)
112
112
}
113
113
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)
158
115
}
159
116
PatKind :: Slice ( ref before, ref slice, ref after) => {
160
117
let expected_ty = self . structurally_resolved_type ( pat. span , expected) ;
@@ -1059,4 +1016,58 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
1059
1016
tcx. types . err
1060
1017
}
1061
1018
}
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
+ }
1062
1073
}
0 commit comments