parent
0475406178
commit
9169a1b26a
3 changed files with 97 additions and 33 deletions
|
@ -168,7 +168,8 @@ export bound_const;
|
|||
export terr_no_integral_type, terr_ty_param_size, terr_self_substs;
|
||||
export terr_in_field, terr_record_fields, terr_vstores_differ, terr_arg_count;
|
||||
export terr_sorts, terr_vec, terr_str, terr_record_size, terr_tuple_size;
|
||||
export terr_regions_differ, terr_mutability, terr_purity_mismatch;
|
||||
export terr_regions_does_not_outlive, terr_mutability, terr_purity_mismatch;
|
||||
export terr_regions_not_same, terr_regions_no_overlap;
|
||||
export terr_proto_mismatch;
|
||||
export terr_ret_style_mismatch;
|
||||
export purity_to_str;
|
||||
|
@ -463,7 +464,9 @@ enum type_err {
|
|||
terr_record_fields(ast::ident, ast::ident),
|
||||
terr_arg_count,
|
||||
terr_mode_mismatch(mode, mode),
|
||||
terr_regions_differ(region, region),
|
||||
terr_regions_does_not_outlive(region, region),
|
||||
terr_regions_not_same(region, region),
|
||||
terr_regions_no_overlap(region, region),
|
||||
terr_vstores_differ(terr_vstore_kind, vstore, vstore),
|
||||
terr_in_field(@type_err, ast::ident),
|
||||
terr_sorts(t, t),
|
||||
|
@ -2631,11 +2634,21 @@ fn type_err_to_str(cx: ctxt, err: &type_err) -> ~str {
|
|||
return ~"expected argument mode " + mode_to_str(e_mode) +
|
||||
~" but found " + mode_to_str(a_mode);
|
||||
}
|
||||
terr_regions_differ(subregion, superregion) => {
|
||||
terr_regions_does_not_outlive(subregion, superregion) => {
|
||||
return fmt!{"%s does not necessarily outlive %s",
|
||||
explain_region(cx, subregion),
|
||||
explain_region(cx, superregion)};
|
||||
}
|
||||
terr_regions_not_same(region1, region2) => {
|
||||
return fmt!{"%s is not the same as %s",
|
||||
explain_region(cx, region1),
|
||||
explain_region(cx, region2)};
|
||||
}
|
||||
terr_regions_no_overlap(region1, region2) => {
|
||||
return fmt!{"%s does not intersect %s",
|
||||
explain_region(cx, region1),
|
||||
explain_region(cx, region2)};
|
||||
}
|
||||
terr_vstores_differ(k, e_vs, a_vs) => {
|
||||
return fmt!{"%s storage differs: expected %s but found %s",
|
||||
terr_vstore_kind_to_str(k),
|
||||
|
|
|
@ -394,7 +394,8 @@ enum infer_ctxt = @{
|
|||
ty_var_integral_bindings: vals_and_bindings<ty::tvi_vid, int_ty_set>,
|
||||
|
||||
// For region variables.
|
||||
region_var_bindings: vals_and_bindings<ty::region_vid, bounds<ty::region>>,
|
||||
region_var_bindings: vals_and_bindings<ty::region_vid,
|
||||
bounds<ty::region>>,
|
||||
|
||||
// For keeping track of existing type and region variables.
|
||||
ty_var_counter: @mut uint,
|
||||
|
@ -1053,7 +1054,7 @@ impl infer_ctxt {
|
|||
nde_a.rank)
|
||||
}
|
||||
|
||||
fn var_sub_t_integral<V: copy vid>(
|
||||
fn var_integral_sub_t<V: copy vid>(
|
||||
vb: &vals_and_bindings<V, int_ty_set>,
|
||||
a_id: V, b: ty::t) -> ures {
|
||||
|
||||
|
@ -1146,9 +1147,19 @@ impl infer_ctxt {
|
|||
debug!{"eq_regions(%s, %s)",
|
||||
a.to_str(self), b.to_str(self)};
|
||||
do indent {
|
||||
do self.sub_regions(a, b).then {
|
||||
self.sub_regions(b, a)
|
||||
}
|
||||
self.try(|| {
|
||||
do self.sub_regions(a, b).then {
|
||||
self.sub_regions(b, a)
|
||||
}
|
||||
}).chain_err(|e| {
|
||||
// substitute a better error, but use the regions
|
||||
// found in the original error
|
||||
match e {
|
||||
ty::terr_regions_does_not_outlive(a1, b1) =>
|
||||
err(ty::terr_regions_not_same(a1, b1)),
|
||||
_ => err(e)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1847,15 +1858,15 @@ fn super_tys<C:combine>(
|
|||
}
|
||||
(ty::ty_var_integral(a_id), ty::ty_int(_)) |
|
||||
(ty::ty_var_integral(a_id), ty::ty_uint(_)) => {
|
||||
self.infcx().vart_integral(&self.infcx().ty_var_integral_bindings,
|
||||
a_id, b)
|
||||
.then(|| ok(a) )
|
||||
self.infcx().var_integral_sub_t(
|
||||
&self.infcx().ty_var_integral_bindings,
|
||||
a_id, b).then(|| ok(a) )
|
||||
}
|
||||
(ty::ty_int(_), ty::ty_var_integral(b_id)) |
|
||||
(ty::ty_uint(_), ty::ty_var_integral(b_id)) => {
|
||||
self.infcx().t_sub_var_integral(&self.infcx().ty_var_integral_bindings,
|
||||
a, b_id)
|
||||
.then(|| ok(a) )
|
||||
self.infcx().t_sub_var_integral(
|
||||
&self.infcx().ty_var_integral_bindings,
|
||||
a, b_id).then(|| ok(a) )
|
||||
}
|
||||
|
||||
(ty::ty_int(_), _) |
|
||||
|
@ -2015,8 +2026,8 @@ impl sub: combine {
|
|||
}
|
||||
_ => {
|
||||
do (&self.lub()).regions(a, b).compare(b) {
|
||||
ty::terr_regions_differ(b, a)
|
||||
}
|
||||
ty::terr_regions_does_not_outlive(b, a)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -2460,20 +2471,26 @@ impl glb: combine {
|
|||
let rm = self.infcx().tcx.region_map;
|
||||
match region::nearest_common_ancestor(rm, f_id, s_id) {
|
||||
some(r_id) if r_id == f_id => ok(s),
|
||||
_ => err(ty::terr_regions_differ(b, a))
|
||||
_ => err(ty::terr_regions_no_overlap(b, a))
|
||||
}
|
||||
}
|
||||
|
||||
(ty::re_scope(a_id), ty::re_scope(b_id)) |
|
||||
(ty::re_free(a_id, _), ty::re_free(b_id, _)) => {
|
||||
// We want to generate a region that is contained by both of
|
||||
// these: so, if one of these scopes is a subscope of the
|
||||
// other, return it. Otherwise fail.
|
||||
let rm = self.infcx().tcx.region_map;
|
||||
match region::nearest_common_ancestor(rm, a_id, b_id) {
|
||||
some(r_id) if a_id == r_id => ok(b),
|
||||
some(r_id) if b_id == r_id => ok(a),
|
||||
_ => err(ty::terr_regions_differ(b, a))
|
||||
if a == b {
|
||||
// Same scope or same free identifier, easy case.
|
||||
ok(a)
|
||||
} else {
|
||||
// We want to generate the intersection of two
|
||||
// scopes or two free regions. So, if one of
|
||||
// these scopes is a subscope of the other, return
|
||||
// it. Otherwise fail.
|
||||
let rm = self.infcx().tcx.region_map;
|
||||
match region::nearest_common_ancestor(rm, a_id, b_id) {
|
||||
some(r_id) if a_id == r_id => ok(ty::re_scope(b_id)),
|
||||
some(r_id) if b_id == r_id => ok(ty::re_scope(a_id)),
|
||||
_ => err(ty::terr_regions_no_overlap(b, a))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -2487,7 +2504,7 @@ impl glb: combine {
|
|||
if a == b {
|
||||
ok(a)
|
||||
} else {
|
||||
err(ty::terr_regions_differ(b, a))
|
||||
err(ty::terr_regions_no_overlap(b, a))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -2589,13 +2606,13 @@ fn lattice_tys<L:lattice_ops combine>(
|
|||
}
|
||||
|
||||
(ty::ty_var(a_id), _) => {
|
||||
lattice_var_t(self, &self.infcx().ty_var_bindings, a_id, b,
|
||||
|x, y| self.tys(x, y) )
|
||||
lattice_var_and_t(self, &self.infcx().ty_var_bindings, a_id, b,
|
||||
|x, y| self.tys(x, y) )
|
||||
}
|
||||
|
||||
(_, ty::ty_var(b_id)) => {
|
||||
lattice_var_t(self, &self.infcx().ty_var_bindings, b_id, a,
|
||||
|x, y| self.tys(x, y) )
|
||||
lattice_var_and_t(self, &self.infcx().ty_var_bindings, b_id, a,
|
||||
|x, y| self.tys(x, y) )
|
||||
}
|
||||
_ => {
|
||||
super_tys(self, a, b)
|
||||
|
@ -2616,9 +2633,9 @@ fn lattice_rvars<L:lattice_ops combine>(
|
|||
}
|
||||
|
||||
(ty::re_var(v_id), r) | (r, ty::re_var(v_id)) => {
|
||||
lattice_var_t(self, &self.infcx().region_var_bindings,
|
||||
v_id, r,
|
||||
|x, y| self.regions(x, y) )
|
||||
lattice_var_and_t(self, &self.infcx().region_var_bindings,
|
||||
v_id, r,
|
||||
|x, y| self.regions(x, y) )
|
||||
}
|
||||
|
||||
_ => {
|
||||
|
|
34
src/test/compile-fail/regions-glb-free-free.rs
Normal file
34
src/test/compile-fail/regions-glb-free-free.rs
Normal file
|
@ -0,0 +1,34 @@
|
|||
mod argparse {
|
||||
use std;
|
||||
|
||||
import std::map;
|
||||
import either::{either, left, right};
|
||||
|
||||
struct Flag {
|
||||
name: &str;
|
||||
desc: &str;
|
||||
max_count: uint;
|
||||
mut value: uint;
|
||||
}
|
||||
|
||||
fn flag(name: &str, desc: &str) -> Flag {
|
||||
Flag { name: name, desc: desc, max_count: 1, value: 0 }
|
||||
}
|
||||
|
||||
impl Flag {
|
||||
fn set_desc(self, s: &str) -> Flag {
|
||||
Flag { //~ ERROR mismatched types
|
||||
name: self.name,
|
||||
desc: s,
|
||||
max_count: self.max_count,
|
||||
value: self.value
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn main () {
|
||||
let f : argparse::Flag = argparse::flag(~"flag", ~"My flag");
|
||||
let updated_flag = f.set_desc(~"My new flag");
|
||||
assert updated_flag.desc == "My new flag";
|
||||
}
|
Loading…
Reference in a new issue