From cc16165e40ec730dd9b0e01f19e8056244ac3a57 Mon Sep 17 00:00:00 2001 From: Niko Matsakis Date: Sat, 14 Apr 2012 18:45:03 -0700 Subject: [PATCH] implement evec/estr subtyping/lub/glb/etc --- src/rustc/middle/infer.rs | 53 ++++++++++++++++++++++--- src/rustc/middle/trans/base.rs | 2 +- src/rustc/middle/ty.rs | 18 ++++++++- src/test/compile-fail/estr-subtyping.rs | 30 ++++++++++++++ src/test/compile-fail/evec-subtyping.rs | 30 ++++++++++++++ 5 files changed, 126 insertions(+), 7 deletions(-) create mode 100644 src/test/compile-fail/estr-subtyping.rs create mode 100644 src/test/compile-fail/evec-subtyping.rs diff --git a/src/rustc/middle/infer.rs b/src/rustc/middle/infer.rs index 6e48fb2f112..f7fb0829ff0 100644 --- a/src/rustc/middle/infer.rs +++ b/src/rustc/middle/infer.rs @@ -896,6 +896,8 @@ iface combine { fn ret_styles(r1: ret_style, r2: ret_style) -> cres; fn contraregions(a: ty::region, b: ty::region) -> cres; fn regions(a: ty::region, b: ty::region) -> cres; + fn vstores(vk: ty::terr_vstore_kind, + a: ty::vstore, b: ty::vstore) -> cres; } enum sub = infer_ctxt; // "subtype", "subregion" etc @@ -951,6 +953,27 @@ fn super_args( } } +fn super_vstores( + self: C, vk: ty::terr_vstore_kind, + a: ty::vstore, b: ty::vstore) -> cres { + + 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( self: C, a_f: ty::fn_ty, b_f: ty::fn_ty) -> cres { @@ -1070,15 +1093,20 @@ fn super_tys( } } - (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 { + super_vstores(self, vk, a, b) + } + fn modes(a: ast::mode, b: ast::mode) -> cres { 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 { + super_vstores(self, vk, a, b) + } + fn modes(a: ast::mode, b: ast::mode) -> cres { 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 { + super_vstores(self, vk, a, b) + } + fn modes(a: ast::mode, b: ast::mode) -> cres { super_modes(self, a, b) } diff --git a/src/rustc/middle/trans/base.rs b/src/rustc/middle/trans/base.rs index 7b6c5450eed..849d8af21b4 100644 --- a/src/rustc/middle/trans/base.rs +++ b/src/rustc/middle/trans/base.rs @@ -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; } diff --git a/src/rustc/middle/ty.rs b/src/rustc/middle/ty.rs index 0210edb60fb..506ccc4ab18 100644 --- a/src/rustc/middle/ty.rs +++ b/src/rustc/middle/ty.rs @@ -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 = spanned>; type type_constr = constr_general<@path>; type constr = constr_general; +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)); } diff --git a/src/test/compile-fail/estr-subtyping.rs b/src/test/compile-fail/estr-subtyping.rs new file mode 100644 index 00000000000..69b6d45baf7 --- /dev/null +++ b/src/test/compile-fail/estr-subtyping.rs @@ -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() { +} diff --git a/src/test/compile-fail/evec-subtyping.rs b/src/test/compile-fail/evec-subtyping.rs new file mode 100644 index 00000000000..843bd77625e --- /dev/null +++ b/src/test/compile-fail/evec-subtyping.rs @@ -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() { +}