implement evec/estr subtyping/lub/glb/etc

This commit is contained in:
Niko Matsakis 2012-04-14 18:45:03 -07:00
parent eb935b8fcb
commit cc16165e40
5 changed files with 126 additions and 7 deletions

View File

@ -896,6 +896,8 @@ iface combine {
fn ret_styles(r1: ret_style, r2: ret_style) -> cres<ret_style>;
fn contraregions(a: ty::region, b: ty::region) -> cres<ty::region>;
fn regions(a: ty::region, b: ty::region) -> cres<ty::region>;
fn vstores(vk: ty::terr_vstore_kind,
a: ty::vstore, b: ty::vstore) -> cres<ty::vstore>;
}
enum sub = infer_ctxt; // "subtype", "subregion" etc
@ -951,6 +953,27 @@ fn super_args<C:combine>(
}
}
fn super_vstores<C:combine>(
self: C, vk: ty::terr_vstore_kind,
a: ty::vstore, b: ty::vstore) -> cres<ty::vstore> {
alt (a, b) {
(ty::vstore_slice(a_r), ty::vstore_slice(b_r)) {
self.contraregions(a_r, b_r).chain {|r|
ok(ty::vstore_slice(r))
}
}
_ if a == b {
ok(a)
}
_ {
err(ty::terr_vstores_differ(vk, b, a))
}
}
}
fn super_fns<C:combine>(
self: C, a_f: ty::fn_ty, b_f: ty::fn_ty) -> cres<ty::fn_ty> {
@ -1070,15 +1093,20 @@ fn super_tys<C:combine>(
}
}
(ty::ty_evec(a_mt, ty::vstore_slice(a_r)),
ty::ty_evec(b_mt, ty::vstore_slice(b_r))) {
self.contraregions(a_r, b_r).chain {|r|
self.mts(a_mt, b_mt).chain {|mt|
ok(ty::mk_evec(tcx, mt, ty::vstore_slice(r)))
(ty::ty_evec(a_mt, vs_a), ty::ty_evec(b_mt, vs_b)) {
self.mts(a_mt, b_mt).chain {|mt|
self.vstores(ty::terr_vec, vs_a, vs_b).chain {|vs|
ok(ty::mk_evec(tcx, mt, vs))
}
}
}
(ty::ty_estr(vs_a), ty::ty_estr(vs_b)) {
self.vstores(ty::terr_str, vs_a, vs_b).chain {|vs|
ok(ty::mk_estr(tcx,vs))
}
}
(ty::ty_res(a_id, a_t, a_tps), ty::ty_res(b_id, b_t, b_tps))
if a_id == b_id {
self.tys(a_t, b_t).chain {|t|
@ -1234,6 +1262,11 @@ impl of combine for sub {
super_flds(self, a, b)
}
fn vstores(vk: ty::terr_vstore_kind,
a: ty::vstore, b: ty::vstore) -> cres<ty::vstore> {
super_vstores(self, vk, a, b)
}
fn modes(a: ast::mode, b: ast::mode) -> cres<ast::mode> {
super_modes(self, a, b)
}
@ -1402,6 +1435,11 @@ impl of combine for lub {
super_flds(self, a, b)
}
fn vstores(vk: ty::terr_vstore_kind,
a: ty::vstore, b: ty::vstore) -> cres<ty::vstore> {
super_vstores(self, vk, a, b)
}
fn modes(a: ast::mode, b: ast::mode) -> cres<ast::mode> {
super_modes(self, a, b)
}
@ -1587,6 +1625,11 @@ impl of combine for glb {
super_flds(self, a, b)
}
fn vstores(vk: ty::terr_vstore_kind,
a: ty::vstore, b: ty::vstore) -> cres<ty::vstore> {
super_vstores(self, vk, a, b)
}
fn modes(a: ast::mode, b: ast::mode) -> cres<ast::mode> {
super_modes(self, a, b)
}

View File

@ -2616,7 +2616,7 @@ fn trans_arg_expr(cx: block, arg: ty::arg, lldestty: TypeRef, e: @ast::expr,
ret rslt(bcx, val);
}
fn adapt_borrowed_value(lv: lval_result, arg: ty::arg,
fn adapt_borrowed_value(lv: lval_result, _arg: ty::arg,
e: @ast::expr) -> lval_result {
let bcx = lv.bcx;
if !expr_is_borrowed(bcx, e) { ret lv; }

View File

@ -11,6 +11,7 @@ import syntax::codemap::span;
import metadata::csearch;
import util::common::*;
import util::ppaux::region_to_str;
import util::ppaux::vstore_to_str;
import util::ppaux::ty_to_str;
import util::ppaux::ty_constr_to_str;
import syntax::print::pprust::*;
@ -105,7 +106,7 @@ export ty_fn_args;
export type_constr;
export kind, kind_sendable, kind_copyable, kind_noncopyable;
export kind_can_be_copied, kind_can_be_sent, proto_kind, kind_lteq, type_kind;
export type_err;
export type_err, terr_vstore_kind;
export type_err_to_str;
export type_needs_drop;
export type_allows_implicit_copy;
@ -328,6 +329,10 @@ type constr_general<ARG> = spanned<constr_general_<ARG, def_id>>;
type type_constr = constr_general<@path>;
type constr = constr_general<uint>;
enum terr_vstore_kind {
terr_vec, terr_str
}
// Data structures used in type unification
enum type_err {
terr_mismatch,
@ -348,6 +353,7 @@ enum type_err {
terr_constr_len(uint, uint),
terr_constr_mismatch(@type_constr, @type_constr),
terr_regions_differ(region, region),
terr_vstores_differ(terr_vstore_kind, vstore, vstore),
terr_in_field(@type_err, str),
terr_sorts(t, t)
}
@ -1976,6 +1982,10 @@ fn ty_sort_str(cx: ctxt, t: t) -> str {
}
fn type_err_to_str(cx: ctxt, err: type_err) -> str {
fn terr_vstore_kind_to_str(k: terr_vstore_kind) -> str {
alt k { terr_vec { "[]" } terr_str { "str" } }
}
alt err {
terr_mismatch { ret "types differ"; }
terr_ret_style_mismatch(expect, actual) {
@ -2038,6 +2048,12 @@ fn type_err_to_str(cx: ctxt, err: type_err) -> str {
region_to_str(cx, subregion),
region_to_str(cx, superregion));
}
terr_vstores_differ(k, e_vs, a_vs) {
ret #fmt("%s storage differs: expected %s but found %s",
terr_vstore_kind_to_str(k),
vstore_to_str(cx, e_vs),
vstore_to_str(cx, a_vs));
}
terr_in_field(err, fname) {
ret #fmt("in field `%s`, %s", fname, type_err_to_str(cx, *err));
}

View File

@ -0,0 +1,30 @@
fn wants_box(x: str/@) { }
fn wants_uniq(x: str/~) { }
fn wants_three(x: str/3) { }
fn has_box(x: str/@) {
wants_box(x);
wants_uniq(x); //! ERROR str storage differs: expected ~ but found @
wants_three(x); //! ERROR str storage differs: expected 3 but found @
}
fn has_uniq(x: str/~) {
wants_box(x); //! ERROR str storage differs: expected @ but found ~
wants_uniq(x);
wants_three(x); //! ERROR str storage differs: expected 3 but found ~
}
fn has_three(x: str/3) {
wants_box(x); //! ERROR str storage differs: expected @ but found 3
wants_uniq(x); //! ERROR str storage differs: expected ~ but found 3
wants_three(x);
}
fn has_four(x: str/4) {
wants_box(x); //! ERROR str storage differs: expected @ but found 4
wants_uniq(x); //! ERROR str storage differs: expected ~ but found 4
wants_three(x); //! ERROR str storage differs: expected 3 but found 4
}
fn main() {
}

View File

@ -0,0 +1,30 @@
fn wants_box(x: [uint]/@) { }
fn wants_uniq(x: [uint]/~) { }
fn wants_three(x: [uint]/3) { }
fn has_box(x: [uint]/@) {
wants_box(x);
wants_uniq(x); //! ERROR [] storage differs: expected ~ but found @
wants_three(x); //! ERROR [] storage differs: expected 3 but found @
}
fn has_uniq(x: [uint]/~) {
wants_box(x); //! ERROR [] storage differs: expected @ but found ~
wants_uniq(x);
wants_three(x); //! ERROR [] storage differs: expected 3 but found ~
}
fn has_three(x: [uint]/3) {
wants_box(x); //! ERROR [] storage differs: expected @ but found 3
wants_uniq(x); //! ERROR [] storage differs: expected ~ but found 3
wants_three(x);
}
fn has_four(x: [uint]/4) {
wants_box(x); //! ERROR [] storage differs: expected @ but found 4
wants_uniq(x); //! ERROR [] storage differs: expected ~ but found 4
wants_three(x); //! ERROR [] storage differs: expected 3 but found 4
}
fn main() {
}