@@ -30,7 +30,9 @@ use syntax::print::pprust;
3030use syntax:: ptr:: P ;
3131
3232pub fn check_pat < ' a , ' tcx > ( pcx : & pat_ctxt < ' a , ' tcx > ,
33- pat : & ast:: Pat , expected : Ty < ' tcx > ) {
33+ pat : & ast:: Pat ,
34+ expected : Ty < ' tcx > )
35+ {
3436 let fcx = pcx. fcx ;
3537 let tcx = pcx. fcx . ccx . tcx ;
3638
@@ -46,6 +48,19 @@ pub fn check_pat<'a, 'tcx>(pcx: &pat_ctxt<'a, 'tcx>,
4648 check_expr ( fcx, & * * lt) ;
4749 let expr_ty = fcx. expr_ty ( & * * lt) ;
4850 fcx. write_ty ( pat. id , expr_ty) ;
51+
52+ // somewhat surprising: in this case, the subtyping
53+ // relation goes the opposite way as the other
54+ // cases. Actually what we really want is not a subtyping
55+ // relation at all but rather that there exists a LUB (so
56+ // that they can be compared). However, in practice,
57+ // constants are always scalars or strings. For scalars
58+ // subtyping is irrelevant, and for strings `expr_ty` is
59+ // type is `&'static str`, so if we say that
60+ //
61+ // &'static str <: expected
62+ //
63+ // that's equivalent to there existing a LUB.
4964 demand:: suptype ( fcx, pat. span , expected, expr_ty) ;
5065 }
5166 ast:: PatRange ( ref begin, ref end) => {
@@ -54,10 +69,16 @@ pub fn check_pat<'a, 'tcx>(pcx: &pat_ctxt<'a, 'tcx>,
5469
5570 let lhs_ty = fcx. expr_ty ( & * * begin) ;
5671 let rhs_ty = fcx. expr_ty ( & * * end) ;
57- if require_same_types (
58- tcx, Some ( fcx. infcx ( ) ) , false , pat. span , lhs_ty, rhs_ty,
59- || "mismatched types in range" . to_string ( ) )
60- && ( ty:: type_is_numeric ( lhs_ty) || ty:: type_is_char ( rhs_ty) ) {
72+
73+ let lhs_eq_rhs =
74+ require_same_types (
75+ tcx, Some ( fcx. infcx ( ) ) , false , pat. span , lhs_ty, rhs_ty,
76+ || "mismatched types in range" . to_string ( ) ) ;
77+
78+ let numeric_or_char =
79+ lhs_eq_rhs && ( ty:: type_is_numeric ( lhs_ty) || ty:: type_is_char ( lhs_ty) ) ;
80+
81+ if numeric_or_char {
6182 match valid_range_bounds ( fcx. ccx , & * * begin, & * * end) {
6283 Some ( false ) => {
6384 span_err ! ( tcx. sess, begin. span, E0030 ,
@@ -71,38 +92,59 @@ pub fn check_pat<'a, 'tcx>(pcx: &pat_ctxt<'a, 'tcx>,
7192 }
7293 } else {
7394 span_err ! ( tcx. sess, begin. span, E0029 ,
74- "only char and numeric types are allowed in range" ) ;
95+ "only char and numeric types are allowed in range" ) ;
7596 }
7697
7798 fcx. write_ty ( pat. id , lhs_ty) ;
99+
100+ // subtyping doens't matter here, as the value is some kind of scalar
78101 demand:: eqtype ( fcx, pat. span , expected, lhs_ty) ;
79102 }
80103 ast:: PatEnum ( ..) | ast:: PatIdent ( ..) if pat_is_const ( & tcx. def_map , pat) => {
81104 let const_did = tcx. def_map . borrow ( ) [ pat. id ] . clone ( ) . def_id ( ) ;
82105 let const_scheme = ty:: lookup_item_type ( tcx, const_did) ;
83- fcx. write_ty ( pat. id , const_scheme. ty ) ;
84- demand:: suptype ( fcx, pat. span , expected, const_scheme. ty ) ;
106+ assert ! ( const_scheme. generics. is_empty( ) ) ;
107+ let const_ty = pcx. fcx . instantiate_type_scheme ( pat. span ,
108+ & Substs :: empty ( ) ,
109+ & const_scheme. ty ) ;
110+ fcx. write_ty ( pat. id , const_ty) ;
111+
112+ // FIXME(#20489) -- we should limit the types here to scalars or something!
113+
114+ // As with PatLit, what we really want here is that there
115+ // exist a LUB, but for the cases that can occur, subtype
116+ // is good enough.
117+ demand:: suptype ( fcx, pat. span , expected, const_ty) ;
85118 }
86119 ast:: PatIdent ( bm, ref path, ref sub) if pat_is_binding ( & tcx. def_map , pat) => {
87120 let typ = fcx. local_ty ( pat. span , pat. id ) ;
88121 match bm {
89122 ast:: BindByRef ( mutbl) => {
90123 // if the binding is like
91124 // ref x | ref const x | ref mut x
92- // then the type of x is &M T where M is the mutability
93- // and T is the expected type
125+ // then `x` is assigned a value of type ` &M T` where M is the mutability
126+ // and T is the expected type.
94127 let region_var = fcx. infcx ( ) . next_region_var ( infer:: PatternRegion ( pat. span ) ) ;
95128 let mt = ty:: mt { ty : expected, mutbl : mutbl } ;
96129 let region_ty = ty:: mk_rptr ( tcx, tcx. mk_region ( region_var) , mt) ;
130+
131+ // `x` is assigned a value of type `&M T`, hence `&M T <: typeof(x)` is
132+ // required. However, we use equality, which is stronger. See (*) for
133+ // an explanation.
97134 demand:: eqtype ( fcx, pat. span , region_ty, typ) ;
98135 }
99136 // otherwise the type of x is the expected type T
100137 ast:: BindByValue ( _) => {
138+ // As above, `T <: typeof(x)` is required but we
139+ // use equality, see (*) below.
101140 demand:: eqtype ( fcx, pat. span , expected, typ) ;
102141 }
103142 }
143+
104144 fcx. write_ty ( pat. id , typ) ;
105145
146+ // if there are multiple arms, make sure they all agree on
147+ // what the type of the binding `x` ought to be
106148 let canon_id = pcx. map [ path. node ] ;
107149 if canon_id != pat. id {
108150 let ct = fcx. local_ty ( pat. span , canon_id) ;
@@ -124,8 +166,9 @@ pub fn check_pat<'a, 'tcx>(pcx: &pat_ctxt<'a, 'tcx>,
124166 check_pat_struct ( pcx, pat, path, fields. as_slice ( ) , etc, expected) ;
125167 }
126168 ast:: PatTup ( ref elements) => {
127- let element_tys: Vec < _ > = range ( 0 , elements. len ( ) ) . map ( |_| fcx. infcx ( )
128- . next_ty_var ( ) ) . collect ( ) ;
169+ let element_tys: Vec < _ > =
170+ range ( 0 , elements. len ( ) ) . map ( |_| fcx. infcx ( ) . next_ty_var ( ) )
171+ . collect ( ) ;
129172 let pat_ty = ty:: mk_tup ( tcx, element_tys. clone ( ) ) ;
130173 fcx. write_ty ( pat. id , pat_ty) ;
131174 demand:: eqtype ( fcx, pat. span , expected, pat_ty) ;
@@ -138,7 +181,10 @@ pub fn check_pat<'a, 'tcx>(pcx: &pat_ctxt<'a, 'tcx>,
138181 let uniq_ty = ty:: mk_uniq ( tcx, inner_ty) ;
139182
140183 if check_dereferencable ( pcx, pat. span , expected, & * * inner) {
141- demand:: suptype ( fcx, pat. span , expected, uniq_ty) ;
184+ // Here, `demand::subtype` is good enough, but I don't
185+ // think any errors can be introduced by using
186+ // `demand::eqtype`.
187+ demand:: eqtype ( fcx, pat. span , expected, uniq_ty) ;
142188 fcx. write_ty ( pat. id , uniq_ty) ;
143189 check_pat ( pcx, & * * inner, inner_ty) ;
144190 } else {
@@ -150,15 +196,18 @@ pub fn check_pat<'a, 'tcx>(pcx: &pat_ctxt<'a, 'tcx>,
150196 let inner_ty = fcx. infcx ( ) . next_ty_var ( ) ;
151197
152198 let mutbl =
153- ty:: deref ( fcx. infcx ( ) . shallow_resolve ( expected) , true )
154- . map_or ( ast:: MutImmutable , |mt| mt . mutbl ) ;
199+ ty:: deref ( fcx. infcx ( ) . shallow_resolve ( expected) , true ) . map ( |mt| mt . mutbl )
200+ . unwrap_or ( ast:: MutImmutable ) ;
155201
156202 let mt = ty:: mt { ty : inner_ty, mutbl : mutbl } ;
157203 let region = fcx. infcx ( ) . next_region_var ( infer:: PatternRegion ( pat. span ) ) ;
158204 let rptr_ty = ty:: mk_rptr ( tcx, tcx. mk_region ( region) , mt) ;
159205
160206 if check_dereferencable ( pcx, pat. span , expected, & * * inner) {
161- demand:: suptype ( fcx, pat. span , expected, rptr_ty) ;
207+ // `demand::subtype` would be good enough, but using
208+ // `eqtype` turns out to be equally general. See (*)
209+ // below for details.
210+ demand:: eqtype ( fcx, pat. span , expected, rptr_ty) ;
162211 fcx. write_ty ( pat. id , rptr_ty) ;
163212 check_pat ( pcx, & * * inner, inner_ty) ;
164213 } else {
@@ -181,14 +230,18 @@ pub fn check_pat<'a, 'tcx>(pcx: &pat_ctxt<'a, 'tcx>,
181230 let region = fcx. infcx ( ) . next_region_var ( infer:: PatternRegion ( pat. span ) ) ;
182231 ty:: mk_slice ( tcx, tcx. mk_region ( region) , ty:: mt {
183232 ty : inner_ty,
184- mutbl : ty:: deref ( expected_ty, true )
185- . map_or ( ast:: MutImmutable , |mt| mt . mutbl )
233+ mutbl : ty:: deref ( expected_ty, true ) . map ( |mt| mt . mutbl )
234+ . unwrap_or ( ast:: MutImmutable )
186235 } )
187236 }
188237 } ;
189238
190239 fcx. write_ty ( pat. id , pat_ty) ;
191- demand:: suptype ( fcx, pat. span , expected, pat_ty) ;
240+
241+ // `demand::subtype` would be good enough, but using
242+ // `eqtype` turns out to be equally general. See (*)
243+ // below for details.
244+ demand:: eqtype ( fcx, pat. span , expected, pat_ty) ;
192245
193246 for elt in before. iter ( ) {
194247 check_pat ( pcx, & * * elt, inner_ty) ;
@@ -210,6 +263,56 @@ pub fn check_pat<'a, 'tcx>(pcx: &pat_ctxt<'a, 'tcx>,
210263 }
211264 ast:: PatMac ( _) => tcx. sess . bug ( "unexpanded macro" )
212265 }
266+
267+
268+ // (*) In most of the cases above (literals and constants being
269+ // the exception), we relate types using strict equality, evewn
270+ // though subtyping would be sufficient. There are a few reasons
271+ // for this, some of which are fairly subtle and which cost me
272+ // (nmatsakis) an hour or two debugging to remember, so I thought
273+ // I'd write them down this time.
274+ //
275+ // 1. Most importantly, there is no loss of expressiveness
276+ // here. What we are saying is that the type of `x`
277+ // becomes *exactly* what is expected. This might seem
278+ // like it will cause errors in a case like this:
279+ //
280+ // ```
281+ // fn foo<'x>(x: &'x int) {
282+ // let a = 1;
283+ // let mut z = x;
284+ // z = &a;
285+ // }
286+ // ```
287+ //
288+ // The reason we might get an error is that `z` might be
289+ // assigned a type like `&'x int`, and then we would have
290+ // a problem when we try to assign `&a` to `z`, because
291+ // the lifetime of `&a` (i.e., the enclosing block) is
292+ // shorter than `'x`.
293+ //
294+ // HOWEVER, this code works fine. The reason is that the
295+ // expected type here is whatever type the user wrote, not
296+ // the initializer's type. In this case the user wrote
297+ // nothing, so we are going to create a type variable `Z`.
298+ // Then we will assign the type of the initializer (`&'x
299+ // int`) as a subtype of `Z`: `&'x int <: Z`. And hence we
300+ // will instantiate `Z` as a type `&'0 int` where `'0` is
301+ // a fresh region variable, with the constraint that `'x :
302+ // '0`. So basically we're all set.
303+ //
304+ // Note that there are two tests to check that this remains true
305+ // (`regions-reassign-{match,let}-bound-pointer.rs`).
306+ //
307+ // 2. Things go horribly wrong if we use subtype. The reason for
308+ // THIS is a fairly subtle case involving bound regions. See the
309+ // `givens` field in `region_inference`, as well as the test
310+ // `regions-relate-bound-regions-on-closures-to-inference-variables.rs`,
311+ // for details. Short version is that we must sometimes detect
312+ // relationships between specific region variables and regions
313+ // bound in a closure signature, and that detection gets thrown
314+ // off when we substitute fresh region variables here to enable
315+ // subtyping.
213316}
214317
215318pub fn check_dereferencable < ' a , ' tcx > ( pcx : & pat_ctxt < ' a , ' tcx > ,
0 commit comments