Skip to content

Commit 9169a1b

Browse files
committed
correct glb computation, improve region error msgs
cc #3180
1 parent 0475406 commit 9169a1b

File tree

3 files changed

+97
-33
lines changed

3 files changed

+97
-33
lines changed

src/rustc/middle/ty.rs

Lines changed: 16 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -168,7 +168,8 @@ export bound_const;
168168
export terr_no_integral_type, terr_ty_param_size, terr_self_substs;
169169
export terr_in_field, terr_record_fields, terr_vstores_differ, terr_arg_count;
170170
export terr_sorts, terr_vec, terr_str, terr_record_size, terr_tuple_size;
171-
export terr_regions_differ, terr_mutability, terr_purity_mismatch;
171+
export terr_regions_does_not_outlive, terr_mutability, terr_purity_mismatch;
172+
export terr_regions_not_same, terr_regions_no_overlap;
172173
export terr_proto_mismatch;
173174
export terr_ret_style_mismatch;
174175
export purity_to_str;
@@ -463,7 +464,9 @@ enum type_err {
463464
terr_record_fields(ast::ident, ast::ident),
464465
terr_arg_count,
465466
terr_mode_mismatch(mode, mode),
466-
terr_regions_differ(region, region),
467+
terr_regions_does_not_outlive(region, region),
468+
terr_regions_not_same(region, region),
469+
terr_regions_no_overlap(region, region),
467470
terr_vstores_differ(terr_vstore_kind, vstore, vstore),
468471
terr_in_field(@type_err, ast::ident),
469472
terr_sorts(t, t),
@@ -2631,11 +2634,21 @@ fn type_err_to_str(cx: ctxt, err: &type_err) -> ~str {
26312634
return ~"expected argument mode " + mode_to_str(e_mode) +
26322635
~" but found " + mode_to_str(a_mode);
26332636
}
2634-
terr_regions_differ(subregion, superregion) => {
2637+
terr_regions_does_not_outlive(subregion, superregion) => {
26352638
return fmt!{"%s does not necessarily outlive %s",
26362639
explain_region(cx, subregion),
26372640
explain_region(cx, superregion)};
26382641
}
2642+
terr_regions_not_same(region1, region2) => {
2643+
return fmt!{"%s is not the same as %s",
2644+
explain_region(cx, region1),
2645+
explain_region(cx, region2)};
2646+
}
2647+
terr_regions_no_overlap(region1, region2) => {
2648+
return fmt!{"%s does not intersect %s",
2649+
explain_region(cx, region1),
2650+
explain_region(cx, region2)};
2651+
}
26392652
terr_vstores_differ(k, e_vs, a_vs) => {
26402653
return fmt!{"%s storage differs: expected %s but found %s",
26412654
terr_vstore_kind_to_str(k),

src/rustc/middle/typeck/infer.rs

Lines changed: 47 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -394,7 +394,8 @@ enum infer_ctxt = @{
394394
ty_var_integral_bindings: vals_and_bindings<ty::tvi_vid, int_ty_set>,
395395

396396
// For region variables.
397-
region_var_bindings: vals_and_bindings<ty::region_vid, bounds<ty::region>>,
397+
region_var_bindings: vals_and_bindings<ty::region_vid,
398+
bounds<ty::region>>,
398399

399400
// For keeping track of existing type and region variables.
400401
ty_var_counter: @mut uint,
@@ -1053,7 +1054,7 @@ impl infer_ctxt {
10531054
nde_a.rank)
10541055
}
10551056

1056-
fn var_sub_t_integral<V: copy vid>(
1057+
fn var_integral_sub_t<V: copy vid>(
10571058
vb: &vals_and_bindings<V, int_ty_set>,
10581059
a_id: V, b: ty::t) -> ures {
10591060

@@ -1146,9 +1147,19 @@ impl infer_ctxt {
11461147
debug!{"eq_regions(%s, %s)",
11471148
a.to_str(self), b.to_str(self)};
11481149
do indent {
1149-
do self.sub_regions(a, b).then {
1150-
self.sub_regions(b, a)
1151-
}
1150+
self.try(|| {
1151+
do self.sub_regions(a, b).then {
1152+
self.sub_regions(b, a)
1153+
}
1154+
}).chain_err(|e| {
1155+
// substitute a better error, but use the regions
1156+
// found in the original error
1157+
match e {
1158+
ty::terr_regions_does_not_outlive(a1, b1) =>
1159+
err(ty::terr_regions_not_same(a1, b1)),
1160+
_ => err(e)
1161+
}
1162+
})
11521163
}
11531164
}
11541165
}
@@ -1847,15 +1858,15 @@ fn super_tys<C:combine>(
18471858
}
18481859
(ty::ty_var_integral(a_id), ty::ty_int(_)) |
18491860
(ty::ty_var_integral(a_id), ty::ty_uint(_)) => {
1850-
self.infcx().vart_integral(&self.infcx().ty_var_integral_bindings,
1851-
a_id, b)
1852-
.then(|| ok(a) )
1861+
self.infcx().var_integral_sub_t(
1862+
&self.infcx().ty_var_integral_bindings,
1863+
a_id, b).then(|| ok(a) )
18531864
}
18541865
(ty::ty_int(_), ty::ty_var_integral(b_id)) |
18551866
(ty::ty_uint(_), ty::ty_var_integral(b_id)) => {
1856-
self.infcx().t_sub_var_integral(&self.infcx().ty_var_integral_bindings,
1857-
a, b_id)
1858-
.then(|| ok(a) )
1867+
self.infcx().t_sub_var_integral(
1868+
&self.infcx().ty_var_integral_bindings,
1869+
a, b_id).then(|| ok(a) )
18591870
}
18601871

18611872
(ty::ty_int(_), _) |
@@ -2015,8 +2026,8 @@ impl sub: combine {
20152026
}
20162027
_ => {
20172028
do (&self.lub()).regions(a, b).compare(b) {
2018-
ty::terr_regions_differ(b, a)
2019-
}
2029+
ty::terr_regions_does_not_outlive(b, a)
2030+
}
20202031
}
20212032
}
20222033
}
@@ -2460,20 +2471,26 @@ impl glb: combine {
24602471
let rm = self.infcx().tcx.region_map;
24612472
match region::nearest_common_ancestor(rm, f_id, s_id) {
24622473
some(r_id) if r_id == f_id => ok(s),
2463-
_ => err(ty::terr_regions_differ(b, a))
2474+
_ => err(ty::terr_regions_no_overlap(b, a))
24642475
}
24652476
}
24662477

24672478
(ty::re_scope(a_id), ty::re_scope(b_id)) |
24682479
(ty::re_free(a_id, _), ty::re_free(b_id, _)) => {
2469-
// We want to generate a region that is contained by both of
2470-
// these: so, if one of these scopes is a subscope of the
2471-
// other, return it. Otherwise fail.
2472-
let rm = self.infcx().tcx.region_map;
2473-
match region::nearest_common_ancestor(rm, a_id, b_id) {
2474-
some(r_id) if a_id == r_id => ok(b),
2475-
some(r_id) if b_id == r_id => ok(a),
2476-
_ => err(ty::terr_regions_differ(b, a))
2480+
if a == b {
2481+
// Same scope or same free identifier, easy case.
2482+
ok(a)
2483+
} else {
2484+
// We want to generate the intersection of two
2485+
// scopes or two free regions. So, if one of
2486+
// these scopes is a subscope of the other, return
2487+
// it. Otherwise fail.
2488+
let rm = self.infcx().tcx.region_map;
2489+
match region::nearest_common_ancestor(rm, a_id, b_id) {
2490+
some(r_id) if a_id == r_id => ok(ty::re_scope(b_id)),
2491+
some(r_id) if b_id == r_id => ok(ty::re_scope(a_id)),
2492+
_ => err(ty::terr_regions_no_overlap(b, a))
2493+
}
24772494
}
24782495
}
24792496

@@ -2487,7 +2504,7 @@ impl glb: combine {
24872504
if a == b {
24882505
ok(a)
24892506
} else {
2490-
err(ty::terr_regions_differ(b, a))
2507+
err(ty::terr_regions_no_overlap(b, a))
24912508
}
24922509
}
24932510
}
@@ -2589,13 +2606,13 @@ fn lattice_tys<L:lattice_ops combine>(
25892606
}
25902607

25912608
(ty::ty_var(a_id), _) => {
2592-
lattice_var_t(self, &self.infcx().ty_var_bindings, a_id, b,
2593-
|x, y| self.tys(x, y) )
2609+
lattice_var_and_t(self, &self.infcx().ty_var_bindings, a_id, b,
2610+
|x, y| self.tys(x, y) )
25942611
}
25952612

25962613
(_, ty::ty_var(b_id)) => {
2597-
lattice_var_t(self, &self.infcx().ty_var_bindings, b_id, a,
2598-
|x, y| self.tys(x, y) )
2614+
lattice_var_and_t(self, &self.infcx().ty_var_bindings, b_id, a,
2615+
|x, y| self.tys(x, y) )
25992616
}
26002617
_ => {
26012618
super_tys(self, a, b)
@@ -2616,9 +2633,9 @@ fn lattice_rvars<L:lattice_ops combine>(
26162633
}
26172634

26182635
(ty::re_var(v_id), r) | (r, ty::re_var(v_id)) => {
2619-
lattice_var_t(self, &self.infcx().region_var_bindings,
2620-
v_id, r,
2621-
|x, y| self.regions(x, y) )
2636+
lattice_var_and_t(self, &self.infcx().region_var_bindings,
2637+
v_id, r,
2638+
|x, y| self.regions(x, y) )
26222639
}
26232640

26242641
_ => {
Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
mod argparse {
2+
use std;
3+
4+
import std::map;
5+
import either::{either, left, right};
6+
7+
struct Flag {
8+
name: &str;
9+
desc: &str;
10+
max_count: uint;
11+
mut value: uint;
12+
}
13+
14+
fn flag(name: &str, desc: &str) -> Flag {
15+
Flag { name: name, desc: desc, max_count: 1, value: 0 }
16+
}
17+
18+
impl Flag {
19+
fn set_desc(self, s: &str) -> Flag {
20+
Flag { //~ ERROR mismatched types
21+
name: self.name,
22+
desc: s,
23+
max_count: self.max_count,
24+
value: self.value
25+
}
26+
}
27+
}
28+
}
29+
30+
fn main () {
31+
let f : argparse::Flag = argparse::flag(~"flag", ~"My flag");
32+
let updated_flag = f.set_desc(~"My new flag");
33+
assert updated_flag.desc == "My new flag";
34+
}

0 commit comments

Comments
 (0)