@@ -46,6 +46,19 @@ pub fn check_pat<'a, 'tcx>(pcx: &pat_ctxt<'a, 'tcx>,
4646 check_expr ( fcx, & * * lt) ;
4747 let expr_ty = fcx. expr_ty ( & * * lt) ;
4848 fcx. write_ty ( pat. id , expr_ty) ;
49+
50+ // somewhat surprising: in this case, the subtyping
51+ // relation goes the opposite way as the other
52+ // cases. Actually what we really want is not a subtyping
53+ // relation at all but rather that there exists a LUB (so
54+ // that they can be compared). However, in practice,
55+ // constants are always scalars or strings. For scalars
56+ // subtyping is irrelevant, and for strings `expr_ty` is
57+ // type is `&'static str`, so if we say that
58+ //
59+ // &'static str <: expected
60+ //
61+ // that's equivalent to there existing a LUB.
4962 demand:: suptype ( fcx, pat. span , expected, expr_ty) ;
5063 }
5164 ast:: PatRange ( ref begin, ref end) => {
@@ -54,10 +67,16 @@ pub fn check_pat<'a, 'tcx>(pcx: &pat_ctxt<'a, 'tcx>,
5467
5568 let lhs_ty = fcx. expr_ty ( & * * begin) ;
5669 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) ) {
70+
71+ let lhs_eq_rhs =
72+ require_same_types (
73+ tcx, Some ( fcx. infcx ( ) ) , false , pat. span , lhs_ty, rhs_ty,
74+ || "mismatched types in range" . to_string ( ) ) ;
75+
76+ let numeric_or_char =
77+ lhs_eq_rhs && ( ty:: type_is_numeric ( lhs_ty) || ty:: type_is_char ( lhs_ty) ) ;
78+
79+ if numeric_or_char {
6180 match valid_range_bounds ( fcx. ccx , & * * begin, & * * end) {
6281 Some ( false ) => {
6382 span_err ! ( tcx. sess, begin. span, E0030 ,
@@ -75,6 +94,8 @@ pub fn check_pat<'a, 'tcx>(pcx: &pat_ctxt<'a, 'tcx>,
7594 }
7695
7796 fcx. write_ty ( pat. id , lhs_ty) ;
97+
98+ // subtyping doens't matter here, as the value is some kind of scalar
7899 demand:: eqtype ( fcx, pat. span , expected, lhs_ty) ;
79100 }
80101 ast:: PatEnum ( ..) | ast:: PatIdent ( ..) if pat_is_const ( & tcx. def_map , pat) => {
@@ -89,20 +110,29 @@ pub fn check_pat<'a, 'tcx>(pcx: &pat_ctxt<'a, 'tcx>,
89110 ast:: BindByRef ( mutbl) => {
90111 // if the binding is like
91112 // 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
113+ // then `x` is assigned a value of type ` &M T` where M is the mutability
114+ // and T is the expected type.
94115 let region_var = fcx. infcx ( ) . next_region_var ( infer:: PatternRegion ( pat. span ) ) ;
95116 let mt = ty:: mt { ty : expected, mutbl : mutbl } ;
96117 let region_ty = ty:: mk_rptr ( tcx, tcx. mk_region ( region_var) , mt) ;
118+
119+ // `x` is assigned a value of type `&M T`, hence `&M T <: typeof(x)` is
120+ // required. However, we use equality, which is stronger. See (*) for
121+ // an explanation.
97122 demand:: eqtype ( fcx, pat. span , region_ty, typ) ;
98123 }
99124 // otherwise the type of x is the expected type T
100125 ast:: BindByValue ( _) => {
126+ // As above, `T <: typeof(x)` is required but we
127+ // use equality, see (*) below.
101128 demand:: eqtype ( fcx, pat. span , expected, typ) ;
102129 }
103130 }
131+
104132 fcx. write_ty ( pat. id , typ) ;
105133
134+ // if there are multiple arms, make sure they all agree on
135+ // what the type of the binding `x` ought to be
106136 let canon_id = pcx. map [ path. node ] ;
107137 if canon_id != pat. id {
108138 let ct = fcx. local_ty ( pat. span , canon_id) ;
@@ -138,7 +168,10 @@ pub fn check_pat<'a, 'tcx>(pcx: &pat_ctxt<'a, 'tcx>,
138168 let uniq_ty = ty:: mk_uniq ( tcx, inner_ty) ;
139169
140170 if check_dereferencable ( pcx, pat. span , expected, & * * inner) {
141- demand:: suptype ( fcx, pat. span , expected, uniq_ty) ;
171+ // Here, `demand::subtype` is good enough, but I don't
172+ // think any errors can be introduced by using
173+ // `demand::eqtype`.
174+ demand:: eqtype ( fcx, pat. span , expected, uniq_ty) ;
142175 fcx. write_ty ( pat. id , uniq_ty) ;
143176 check_pat ( pcx, & * * inner, inner_ty) ;
144177 } else {
@@ -158,7 +191,10 @@ pub fn check_pat<'a, 'tcx>(pcx: &pat_ctxt<'a, 'tcx>,
158191 let rptr_ty = ty:: mk_rptr ( tcx, tcx. mk_region ( region) , mt) ;
159192
160193 if check_dereferencable ( pcx, pat. span , expected, & * * inner) {
161- demand:: suptype ( fcx, pat. span , expected, rptr_ty) ;
194+ // `demand::subtype` would be good enough, but using
195+ // `eqtype` turns out to be equally general. See (*)
196+ // below for details.
197+ demand:: eqtype ( fcx, pat. span , expected, rptr_ty) ;
162198 fcx. write_ty ( pat. id , rptr_ty) ;
163199 check_pat ( pcx, & * * inner, inner_ty) ;
164200 } else {
@@ -188,7 +224,11 @@ pub fn check_pat<'a, 'tcx>(pcx: &pat_ctxt<'a, 'tcx>,
188224 } ;
189225
190226 fcx. write_ty ( pat. id , pat_ty) ;
191- demand:: suptype ( fcx, pat. span , expected, pat_ty) ;
227+
228+ // `demand::subtype` would be good enough, but using
229+ // `eqtype` turns out to be equally general. See (*)
230+ // below for details.
231+ demand:: eqtype ( fcx, pat. span , expected, pat_ty) ;
192232
193233 for elt in before. iter ( ) {
194234 check_pat ( pcx, & * * elt, inner_ty) ;
@@ -210,6 +250,56 @@ pub fn check_pat<'a, 'tcx>(pcx: &pat_ctxt<'a, 'tcx>,
210250 }
211251 ast:: PatMac ( _) => tcx. sess . bug ( "unexpanded macro" )
212252 }
253+
254+
255+ // (*) In most of the cases above (literals and constants being
256+ // the exception), we relate types using strict equality, evewn
257+ // though subtyping would be sufficient. There are a few reasons
258+ // for this, some of which are fairly subtle and which cost me
259+ // (nmatsakis) an hour or two debugging to remember, so I thought
260+ // I'd write them down this time.
261+ //
262+ // 1. Most importantly, there is no loss of expressiveness
263+ // here. What we are saying is that the type of `x`
264+ // becomes *exactly* what is expected. This might seem
265+ // like it will cause errors in a case like this:
266+ //
267+ // ```
268+ // fn foo<'x>(x: &'x int) {
269+ // let a = 1;
270+ // let mut z = x;
271+ // z = &a;
272+ // }
273+ // ```
274+ //
275+ // The reason we might get an error is that `z` might be
276+ // assigned a type like `&'x int`, and then we would have
277+ // a problem when we try to assign `&a` to `z`, because
278+ // the lifetime of `&a` (i.e., the enclosing block) is
279+ // shorter than `'x`.
280+ //
281+ // HOWEVER, this code works fine. The reason is that the
282+ // expected type here is whatever type the user wrote, not
283+ // the initializer's type. In this case the user wrote
284+ // nothing, so we are going to create a type variable `Z`.
285+ // Then we will assign the type of the initializer (`&'x
286+ // int`) as a subtype of `Z`: `&'x int <: Z`. And hence we
287+ // will instantiate `Z` as a type `&'0 int` where `'0` is
288+ // a fresh region variable, with the constraint that `'x :
289+ // '0`. So basically we're all set.
290+ //
291+ // Note that there are two tests to check that this remains true
292+ // (`regions-reassign-{match,let}-bound-pointer.rs`).
293+ //
294+ // 2. Things go horribly wrong if we use subtype. The reason for
295+ // THIS is a fairly subtle case involving bound regions. See the
296+ // `givens` field in `region_inference`, as well as the test
297+ // `regions-relate-bound-regions-on-closures-to-inference-variables.rs`,
298+ // for details. Short version is that we must sometimes detect
299+ // relationships between specific region variables and regions
300+ // bound in a closure signature, and that detection gets thrown
301+ // off when we substitute fresh region variables here to enable
302+ // subtyping.
213303}
214304
215305pub fn check_dereferencable < ' a , ' tcx > ( pcx : & pat_ctxt < ' a , ' tcx > ,
0 commit comments