diff options
| author | Graydon Hoare <graydon@mozilla.com> | 2012-04-09 17:32:49 -0700 |
|---|---|---|
| committer | Graydon Hoare <graydon@mozilla.com> | 2012-04-11 11:08:40 -0700 |
| commit | 7a3b29024548e1dcb13590002d5cf4dd94ddd4d4 (patch) | |
| tree | a0cc34e4635bb317347ca1b5424e494ec68e9909 /src/rustc | |
| parent | 0c94cd5d431816c68825a08bcb24754d09b8dc31 (diff) | |
| download | rust-7a3b29024548e1dcb13590002d5cf4dd94ddd4d4.tar.gz rust-7a3b29024548e1dcb13590002d5cf4dd94ddd4d4.zip | |
Add vstore/evec/estr to compiler.
Diffstat (limited to 'src/rustc')
| -rw-r--r-- | src/rustc/metadata/tyencode.rs | 2 | ||||
| -rw-r--r-- | src/rustc/middle/mutbl.rs | 2 | ||||
| -rw-r--r-- | src/rustc/middle/region.rs | 1 | ||||
| -rw-r--r-- | src/rustc/middle/trans/base.rs | 73 | ||||
| -rw-r--r-- | src/rustc/middle/trans/shape.rs | 58 | ||||
| -rw-r--r-- | src/rustc/middle/trans/tvec.rs | 43 | ||||
| -rw-r--r-- | src/rustc/middle/trans/type_of.rs | 23 | ||||
| -rw-r--r-- | src/rustc/middle/trans/type_use.rs | 4 | ||||
| -rw-r--r-- | src/rustc/middle/tstate/pre_post_conditions.rs | 9 | ||||
| -rw-r--r-- | src/rustc/middle/tstate/states.rs | 6 | ||||
| -rw-r--r-- | src/rustc/middle/ty.rs | 165 | ||||
| -rw-r--r-- | src/rustc/middle/typeck.rs | 101 |
12 files changed, 427 insertions, 60 deletions
diff --git a/src/rustc/metadata/tyencode.rs b/src/rustc/metadata/tyencode.rs index fb0a84b603f..0739764b08b 100644 --- a/src/rustc/metadata/tyencode.rs +++ b/src/rustc/metadata/tyencode.rs @@ -176,6 +176,7 @@ fn enc_sty(w: io::writer, cx: @ctxt, st: ty::sty) { ty_f64 { w.write_str("MF"); } } } + ty::ty_estr(_) { cx.tcx.sess.unimpl("tyencode::enc_sty on estr"); } ty::ty_str { w.write_char('S'); } ty::ty_enum(def, tys) { w.write_str("t["); @@ -204,6 +205,7 @@ fn enc_sty(w: io::writer, cx: @ctxt, st: ty::sty) { enc_region(w, r); enc_mt(w, cx, mt); } + ty::ty_evec(_, _) { cx.tcx.sess.unimpl("tyencode::enc_sty on evec"); } ty::ty_vec(mt) { w.write_char('I'); enc_mt(w, cx, mt); } ty::ty_rec(fields) { w.write_str("R["); diff --git a/src/rustc/middle/mutbl.rs b/src/rustc/middle/mutbl.rs index d6488334311..fa2e8ddb0d7 100644 --- a/src/rustc/middle/mutbl.rs +++ b/src/rustc/middle/mutbl.rs @@ -92,12 +92,14 @@ fn expr_root_(tcx: ty::ctxt, ctor_self: option<node_id>, expr_index(base, _) { let auto_unbox = maybe_auto_unbox(tcx, ty::expr_ty(tcx, base)); alt ty::get(auto_unbox.t).struct { + ty::ty_evec(mt, _) | ty::ty_vec(mt) { ds += [@{mutbl: mt.mutbl == m_mutbl, kind: index, outer_t: auto_unbox.t}]; } + ty::ty_estr(_) | ty::ty_str { ds += [@{mutbl: false, kind: index, outer_t: auto_unbox.t}]; } diff --git a/src/rustc/middle/region.rs b/src/rustc/middle/region.rs index c66f09f8836..39f08983b4b 100644 --- a/src/rustc/middle/region.rs +++ b/src/rustc/middle/region.rs @@ -414,6 +414,7 @@ fn resolve_ty(ty: @ast::ty, cx: ctxt, visitor: visit::vt<ctxt>) { cx.region_map.ast_type_to_inferred_region.insert(ty.id, inferred_region); alt ty.node { + ast::ty_vstore(_, ast::vstore_slice(r)) | ast::ty_rptr(r, _) { resolve_region_binding(cx, ty.span, r); } diff --git a/src/rustc/middle/trans/base.rs b/src/rustc/middle/trans/base.rs index fcb983a7291..dbf3ca841ba 100644 --- a/src/rustc/middle/trans/base.rs +++ b/src/rustc/middle/trans/base.rs @@ -573,7 +573,8 @@ fn make_take_glue(bcx: block, v: ValueRef, t: ty::t) { let _icx = bcx.insn_ctxt("make_take_glue"); // NB: v is a *pointer* to type t here, not a direct value. let bcx = alt ty::get(t).struct { - ty::ty_box(_) | ty::ty_opaque_box { + ty::ty_box(_) | ty::ty_opaque_box | + ty::ty_evec(_, ty::vstore_box) | ty::ty_estr(ty::vstore_box) { incr_refcnt_of_boxed(bcx, Load(bcx, v)); bcx } ty::ty_uniq(_) { @@ -581,7 +582,8 @@ fn make_take_glue(bcx: block, v: ValueRef, t: ty::t) { Store(bcx, val, v); bcx } - ty::ty_vec(_) | ty::ty_str { + ty::ty_vec(_) | ty::ty_str | + ty::ty_evec(_, ty::vstore_uniq) | ty::ty_estr(ty::vstore_uniq) { let {bcx, val} = tvec::duplicate(bcx, Load(bcx, v), t); Store(bcx, val, v); bcx @@ -629,6 +631,12 @@ fn make_free_glue(bcx: block, v: ValueRef, t: ty::t) { let bcx = drop_ty(bcx, body, body_mt.ty); trans_free(bcx, v) } + + ty::ty_estr(ty::vstore_box) { + let v = PointerCast(bcx, v, type_of(ccx, t)); + trans_free(bcx, v) + } + ty::ty_opaque_box { let v = PointerCast(bcx, v, type_of(ccx, t)); let td = Load(bcx, GEPi(bcx, v, [0, abi::box_field_tydesc])); @@ -641,9 +649,13 @@ fn make_free_glue(bcx: block, v: ValueRef, t: ty::t) { let v = PointerCast(bcx, v, type_of(ccx, t)); uniq::make_free_glue(bcx, v, t) } + ty::ty_evec(_, ty::vstore_uniq) | ty::ty_estr(ty::vstore_uniq) | ty::ty_vec(_) | ty::ty_str { tvec::make_free_glue(bcx, PointerCast(bcx, v, type_of(ccx, t)), t) } + ty::ty_evec(_, _) { + bcx.sess().unimpl("trans::base::make_free_glue on other evec"); + } ty::ty_fn(_) { closure::make_fn_glue(bcx, v, t, free_ty) } @@ -660,7 +672,8 @@ fn make_drop_glue(bcx: block, v0: ValueRef, t: ty::t) { let _icx = bcx.insn_ctxt("make_drop_glue"); let ccx = bcx.ccx(); let bcx = alt ty::get(t).struct { - ty::ty_box(_) | ty::ty_opaque_box { + ty::ty_box(_) | ty::ty_opaque_box | + ty::ty_estr(ty::vstore_box) { decr_refcnt_maybe_free(bcx, Load(bcx, v0), t) } ty::ty_uniq(_) | ty::ty_vec(_) | ty::ty_str { @@ -900,6 +913,10 @@ fn iter_structural_ty(cx: block, av: ValueRef, t: ty::t, cx = f(cx, llfld_a, fld.mt.ty); } } + ty::ty_estr(ty::vstore_fixed(n)) | + ty::ty_evec(_, ty::vstore_fixed(n)) { + cx = tvec::iter_vec_raw(cx, av, t, C_uint(cx.ccx(), n), f); + } ty::ty_tup(args) { for vec::eachi(args) {|i, arg| let llfld_a = GEPi(cx, av, [0, i as int]); @@ -1111,8 +1128,14 @@ fn drop_ty(cx: block, v: ValueRef, t: ty::t) -> block { fn drop_ty_immediate(bcx: block, v: ValueRef, t: ty::t) -> block { let _icx = bcx.insn_ctxt("drop_ty_immediate"); alt ty::get(t).struct { - ty::ty_uniq(_) | ty::ty_vec(_) | ty::ty_str { free_ty(bcx, v, t) } - ty::ty_box(_) | ty::ty_opaque_box { + ty::ty_uniq(_) | ty::ty_vec(_) | ty::ty_str | + ty::ty_evec(_, ty::vstore_uniq) | + ty::ty_estr(ty::vstore_uniq) { + free_ty(bcx, v, t) + } + ty::ty_box(_) | ty::ty_opaque_box | + ty::ty_evec(_, ty::vstore_box) | + ty::ty_estr(ty::vstore_box) { decr_refcnt_maybe_free(bcx, v, t) } _ { bcx.tcx().sess.bug("drop_ty_immediate: non-box ty"); } @@ -1122,14 +1145,20 @@ fn drop_ty_immediate(bcx: block, v: ValueRef, t: ty::t) -> block { fn take_ty_immediate(bcx: block, v: ValueRef, t: ty::t) -> result { let _icx = bcx.insn_ctxt("take_ty_immediate"); alt ty::get(t).struct { - ty::ty_box(_) | ty::ty_opaque_box { + ty::ty_box(_) | ty::ty_opaque_box | + ty::ty_evec(_, ty::vstore_box) | + ty::ty_estr(ty::vstore_box) { incr_refcnt_of_boxed(bcx, v); rslt(bcx, v) } ty::ty_uniq(_) { uniq::duplicate(bcx, v, t) } - ty::ty_str | ty::ty_vec(_) { tvec::duplicate(bcx, v, t) } + ty::ty_str | ty::ty_vec(_) | + ty::ty_evec(_, ty::vstore_uniq) | + ty::ty_estr(ty::vstore_uniq) { + tvec::duplicate(bcx, v, t) + } _ { rslt(bcx, v) } } } @@ -1299,9 +1328,9 @@ fn trans_lit(cx: block, lit: ast::lit, dest: dest) -> block { let _icx = cx.insn_ctxt("trans_lit"); if dest == ignore { ret cx; } alt lit.node { - ast::lit_str(s) { ret tvec::trans_str(cx, s, dest); } + ast::lit_str(s) { tvec::trans_str(cx, s, dest) } _ { - ret store_in_dest(cx, trans_crate_lit(cx.ccx(), lit), dest); + store_in_dest(cx, trans_crate_lit(cx.ccx(), lit), dest) } } } @@ -2255,8 +2284,29 @@ fn trans_index(cx: block, ex: @ast::expr, base: @ast::expr, maybe_name_value(cx.ccx(), unit_sz, "unit_sz"); let scaled_ix = Mul(bcx, ix_val, unit_sz); maybe_name_value(cx.ccx(), scaled_ix, "scaled_ix"); - let lim = tvec::get_fill(bcx, v); - let body = tvec::get_dataptr(bcx, v, type_of(ccx, unit_ty)); + + let (lim, body) = alt ty::get(base_ty).struct { + ty::ty_estr(ty::vstore_fixed(n)) | + ty::ty_evec(_, ty::vstore_fixed(n)) { + // FIXME: support static bounds-check elimination + // and/or error checking here. + let lim = C_uint(bcx.ccx(), n); + let body = GEPi(bcx, v, [0, 0]); + (lim, body) + } + ty::ty_estr(_) | ty::ty_evec(_, _) { + bcx.sess().unimpl(#fmt("unsupported evec/estr type trans_index")); + } + _ { + let lim = tvec::get_fill(bcx, v); + let body = tvec::get_dataptr(bcx, v, type_of(ccx, unit_ty)); + (lim, body) + } + }; + + #debug("trans_index: lim %s", val_str(bcx.ccx().tn, lim)); + #debug("trans_index: body %s", val_str(bcx.ccx().tn, body)); + let bounds_check = ICmp(bcx, lib::llvm::IntUGE, scaled_ix, lim); let bcx = with_cond(bcx, bounds_check) {|bcx| // fail: bad bounds check. @@ -3017,6 +3067,7 @@ fn trans_expr(bcx: block, e: @ast::expr, dest: dest) -> block { ret trans_rec(bcx, args, base, e.id, dest); } ast::expr_tup(args) { ret trans_tup(bcx, args, dest); } + ast::expr_vstore(e, v) { ret tvec::trans_vstore(bcx, e, v, dest); } ast::expr_lit(lit) { ret trans_lit(bcx, *lit, dest); } ast::expr_vec(args, _) { ret tvec::trans_vec(bcx, args, e.id, dest); } ast::expr_binary(op, lhs, rhs) { diff --git a/src/rustc/middle/trans/shape.rs b/src/rustc/middle/trans/shape.rs index 5460b4c8f28..f79a77ce1d6 100644 --- a/src/rustc/middle/trans/shape.rs +++ b/src/rustc/middle/trans/shape.rs @@ -58,6 +58,8 @@ const shape_bare_fn: u8 = 27u8; const shape_tydesc: u8 = 28u8; const shape_send_tydesc: u8 = 29u8; const shape_rptr: u8 = 31u8; +const shape_fixedvec: u8 = 32u8; +const shape_slice: u8 = 33u8; fn hash_res_info(ri: res_info) -> uint { let mut h = 5381u; @@ -305,6 +307,7 @@ fn shape_of(ccx: @crate_ctxt, t: ty::t, ty_param_map: [uint]) -> [u8] { ty::ty_int(ast::ty_i64) { [shape_i64] } ty::ty_float(ast::ty_f32) { [shape_f32] } ty::ty_float(ast::ty_f64) { [shape_f64] } + ty::ty_estr(ty::vstore_uniq) | ty::ty_str { let mut s = [shape_vec]; add_bool(s, true); // type is POD @@ -340,18 +343,67 @@ fn shape_of(ccx: @crate_ctxt, t: ty::t, ty_param_map: [uint]) -> [u8] { } } } + ty::ty_estr(ty::vstore_box) | + ty::ty_evec(_, ty::vstore_box) | ty::ty_box(_) | ty::ty_opaque_box { [shape_box] } ty::ty_uniq(mt) { let mut s = [shape_uniq]; add_substr(s, shape_of(ccx, mt.ty, ty_param_map)); s } + ty::ty_evec(mt, ty::vstore_uniq) | ty::ty_vec(mt) { let mut s = [shape_vec]; add_bool(s, ty::type_is_pod(ccx.tcx, mt.ty)); add_substr(s, shape_of(ccx, mt.ty, ty_param_map)); s } + + // FIXME: grotesque hacks for encoding fixed-size evecs and estrs. + + ty::ty_estr(ty::vstore_fixed(n)) { + let mut s = [shape_struct], sub = []; + let mut i = 0u; + let u8_t = ty::mk_mach_uint(ccx.tcx, ast::ty_u8); + while i < n { + sub += shape_of(ccx, u8_t, ty_param_map); + } + add_substr(s, sub); + s + } + + ty::ty_evec(mt, ty::vstore_fixed(n)) { + let mut s = [shape_struct], sub = []; + let mut i = 0u; + while i < n { + sub += shape_of(ccx, mt.ty, ty_param_map); + } + add_substr(s, sub); + s + } + + + // FIXME: slightly-less-grotesque hack for encoding slic,e evecs and + // estrs. + + ty::ty_estr(ty::vstore_slice(r)) { + let mut s = [shape_struct], sub = []; + let u8_mt = {ty: ty::mk_mach_uint(ccx.tcx, ast::ty_u8), + mutbl: ast::m_imm }; + sub += shape_of(ccx, ty::mk_rptr(ccx.tcx, r, u8_mt), ty_param_map); + sub += shape_of(ccx, ty::mk_uint(ccx.tcx), ty_param_map); + add_substr(s, sub); + s + } + + ty::ty_evec(mt, ty::vstore_slice(r)) { + let mut s = [shape_struct], sub = []; + sub += shape_of(ccx, ty::mk_rptr(ccx.tcx, r, mt), ty_param_map); + sub += shape_of(ccx, ty::mk_uint(ccx.tcx), ty_param_map); + add_substr(s, sub); + s + } + ty::ty_rec(fields) { let mut s = [shape_struct], sub = []; for vec::each(fields) {|f| @@ -632,12 +684,18 @@ fn simplify_type(tcx: ty::ctxt, typ: ty::t) -> ty::t { fn simplifier(tcx: ty::ctxt, typ: ty::t) -> ty::t { alt ty::get(typ).struct { ty::ty_box(_) | ty::ty_opaque_box | ty::ty_uniq(_) | ty::ty_vec(_) | + ty::ty_evec(_, ty::vstore_uniq) | ty::ty_evec(_, ty::vstore_box) | + ty::ty_estr(ty::vstore_uniq) | ty::ty_estr(ty::vstore_box) | ty::ty_ptr(_) | ty::ty_rptr(_,_) { nilptr(tcx) } ty::ty_fn(_) { ty::mk_tup(tcx, [nilptr(tcx), nilptr(tcx)]) } ty::ty_res(_, sub, tps) { let sub1 = ty::substitute_type_params(tcx, tps, sub); ty::mk_tup(tcx, [ty::mk_int(tcx), simplify_type(tcx, sub1)]) } + ty::ty_evec(_, ty::vstore_slice(_)) | + ty::ty_estr(ty::vstore_slice(_)) { + ty::mk_tup(tcx, [nilptr(tcx), ty::mk_int(tcx)]) + } _ { typ } } } diff --git a/src/rustc/middle/trans/tvec.rs b/src/rustc/middle/trans/tvec.rs index f3d06591942..bce423e37e4 100644 --- a/src/rustc/middle/trans/tvec.rs +++ b/src/rustc/middle/trans/tvec.rs @@ -6,6 +6,7 @@ import base::{call_memmove, shared_malloc, INIT, copy_val, load_if_immediate, get_tydesc, sub_block, do_spill_noroot, dest, bcx_icx}; +import syntax::codemap::span; import shape::llsize_of; import build::*; import common::*; @@ -129,6 +130,48 @@ fn trans_vec(bcx: block, args: [@ast::expr], id: ast::node_id, ret base::store_in_dest(bcx, vptr, dest); } +fn trans_vstore(bcx: block, e: @ast::expr, + v: ast::vstore, dest: dest) -> block { + alt e.node { + ast::expr_lit(@{node: ast::lit_str(s), span: _}) { + ret trans_estr(bcx, s, v, e.span, dest); + } + ast::expr_vec(es, mutbl) { + bcx.ccx().sess.span_unimpl(e.span, "unhandled tvec::trans_vstore"); + } + _ { + bcx.sess().span_bug(e.span, "vstore on non-sequence type"); + } + } +} + +fn trans_estr(bcx: block, s: str, vstore: ast::vstore, + sp: span, dest: dest) -> block { + let _icx = bcx.insn_ctxt("tvec::trans_estr"); + alt vstore { + ast::vstore_fixed(_) + { + let c = str::as_bytes(s) {|bytes| + // NB: The byte vector we have here includes the trailing \0, + // but we are doing a fixed-size str, meaning we _exclude_ + // the trailing \0. And we don't let LLVM null-terminate + // either. + unsafe { + lib::llvm::llvm::LLVMConstString( + unsafe::reinterpret_cast(vec::unsafe::to_ptr(bytes)), + (bytes.len() - 1u) as libc::c_uint, lib::llvm::True) + } + }; + + #debug("trans_estr: src %s",val_str(bcx.ccx().tn, c)); + ret base::store_in_dest(bcx, c, dest); + } + _ { + bcx.ccx().sess.span_unimpl(sp, "unhandled tvec::trans_estr"); + } + } +} + fn trans_str(bcx: block, s: str, dest: dest) -> block { let _icx = bcx.insn_ctxt("tvec::trans_str"); let ccx = bcx.ccx(); diff --git a/src/rustc/middle/trans/type_of.rs b/src/rustc/middle/trans/type_of.rs index 7f471e76bb7..6e24b4c72a1 100644 --- a/src/rustc/middle/trans/type_of.rs +++ b/src/rustc/middle/trans/type_of.rs @@ -48,14 +48,37 @@ fn type_of(cx: @crate_ctxt, t: ty::t) -> TypeRef { ty::ty_int(t) { T_int_ty(cx, t) } ty::ty_uint(t) { T_uint_ty(cx, t) } ty::ty_float(t) { T_float_ty(cx, t) } + ty::ty_estr(ty::vstore_uniq) | ty::ty_str { T_ptr(T_vec(cx, T_i8())) } ty::ty_enum(did, _) { type_of_enum(cx, did, t) } + ty::ty_estr(ty::vstore_box) { T_ptr(T_box(cx, T_i8())) } + ty::ty_evec(mt, ty::vstore_box) | ty::ty_box(mt) { T_ptr(T_box(cx, type_of(cx, mt.ty))) } ty::ty_opaque_box { T_ptr(T_box(cx, T_i8())) } ty::ty_uniq(mt) { T_ptr(type_of(cx, mt.ty)) } + ty::ty_evec(mt, ty::vstore_uniq) | ty::ty_vec(mt) { T_ptr(T_vec(cx, type_of(cx, mt.ty))) } ty::ty_ptr(mt) { T_ptr(type_of(cx, mt.ty)) } ty::ty_rptr(_, mt) { T_ptr(type_of(cx, mt.ty)) } + + ty::ty_evec(mt, ty::vstore_slice(_)) { + T_struct([T_ptr(type_of(cx, mt.ty)), + T_uint_ty(cx, ast::ty_u)]) + } + + ty::ty_estr(ty::vstore_slice(_)) { + T_struct([T_ptr(T_i8()), + T_uint_ty(cx, ast::ty_u)]) + } + + ty::ty_estr(ty::vstore_fixed(n)) { + T_array(T_i8(), n) + } + + ty::ty_evec(mt, ty::vstore_fixed(n)) { + T_array(type_of(cx, mt.ty), n) + } + ty::ty_rec(fields) { let mut tys: [TypeRef] = []; for vec::each(fields) {|f| diff --git a/src/rustc/middle/trans/type_use.rs b/src/rustc/middle/trans/type_use.rs index cbed8a0dbc5..4b993f8224c 100644 --- a/src/rustc/middle/trans/type_use.rs +++ b/src/rustc/middle/trans/type_use.rs @@ -136,7 +136,9 @@ fn node_type_needs(cx: ctx, use: uint, id: node_id) { fn mark_for_expr(cx: ctx, e: @expr) { alt e.node { - expr_vec(_, _) | expr_rec(_, _) | expr_tup(_) | + expr_vstore(_, _) | + expr_vec(_, _) | + expr_rec(_, _) | expr_tup(_) | expr_unary(box(_), _) | expr_unary(uniq(_), _) | expr_cast(_, _) | expr_binary(add, _, _) | expr_copy(_) | expr_move(_, _) { diff --git a/src/rustc/middle/tstate/pre_post_conditions.rs b/src/rustc/middle/tstate/pre_post_conditions.rs index ec7c8354d8c..fc74db67b37 100644 --- a/src/rustc/middle/tstate/pre_post_conditions.rs +++ b/src/rustc/middle/tstate/pre_post_conditions.rs @@ -321,7 +321,14 @@ fn find_pre_post_expr(fcx: fn_ctxt, e: @expr) { _ { } } } - expr_vec(args, _) { find_pre_post_exprs(fcx, args, e.id); } + expr_vstore(ee, _) { + find_pre_post_expr(fcx, ee); + let p = expr_pp(fcx.ccx, ee); + set_pre_and_post(fcx.ccx, e.id, p.precondition, p.postcondition); + } + expr_vec(args, _) { + find_pre_post_exprs(fcx, args, e.id); + } expr_path(p) { let rslt = expr_pp(fcx.ccx, e); clear_pp(rslt); diff --git a/src/rustc/middle/tstate/states.rs b/src/rustc/middle/tstate/states.rs index 8ec37b9c0cb..7d3016a6636 100644 --- a/src/rustc/middle/tstate/states.rs +++ b/src/rustc/middle/tstate/states.rs @@ -358,6 +358,12 @@ fn find_pre_post_state_expr(fcx: fn_ctxt, pres: prestate, e: @expr) -> bool { expr_new(p, _, v) { ret find_pre_post_state_two(fcx, pres, p, v, e.id, oper_pure); } + expr_vstore(ee, _) { + let mut changed = find_pre_post_state_expr(fcx, pres, ee); + set_prestate_ann(fcx.ccx, e.id, expr_prestate(fcx.ccx, ee)); + set_poststate_ann(fcx.ccx, e.id, expr_poststate(fcx.ccx, ee)); + ret changed; + } expr_vec(elts, _) { ret find_pre_post_state_exprs(fcx, pres, e.id, vec::from_elem(vec::len(elts), diff --git a/src/rustc/middle/ty.rs b/src/rustc/middle/ty.rs index f4d134459be..4994fe24ed3 100644 --- a/src/rustc/middle/ty.rs +++ b/src/rustc/middle/ty.rs @@ -80,6 +80,9 @@ export ty_fn_proto, ty_fn_ret, ty_fn_ret_style; export ty_int, mk_int, mk_mach_int, mk_char; export ty_str, mk_str, type_is_str; export ty_vec, mk_vec, type_is_vec; +export ty_estr, mk_estr; +export ty_evec, mk_evec; +export vstore, vstore_fixed, vstore_uniq, vstore_box, vstore_slice; export ty_nil, mk_nil, type_is_nil; export ty_iface, mk_iface; export ty_res, mk_res; @@ -164,6 +167,13 @@ type constr_table = hashmap<ast::node_id, [constr]>; type mt = {ty: t, mutbl: ast::mutability}; +enum vstore { + vstore_fixed(uint), + vstore_uniq, + vstore_box, + vstore_slice(region) +} + type field_ty = { ident: ident, id: def_id, @@ -293,10 +303,12 @@ enum sty { ty_uint(ast::uint_ty), ty_float(ast::float_ty), ty_str, + ty_estr(vstore), ty_enum(def_id, [t]), ty_box(mt), ty_uniq(mt), ty_vec(mt), + ty_evec(mt, vstore), ty_ptr(mt), ty_rptr(region, mt), ty_rec([field]), @@ -458,8 +470,15 @@ fn mk_t_with_id(cx: ctxt, st: sty, o_def_id: option<ast::def_id>) -> t { has_rptrs |= t.has_rptrs; } alt st { + ty_estr(vstore_slice(_)) { + has_rptrs = true; + } + ty_evec(mt, vstore_slice(_)) { + has_rptrs = true; + derive_flags(has_params, has_vars, has_rptrs, mt.ty); + } ty_nil | ty_bot | ty_bool | ty_int(_) | ty_float(_) | ty_uint(_) | - ty_str | ty_type | ty_opaque_closure_ptr(_) | + ty_str | ty_estr(_) | ty_type | ty_opaque_closure_ptr(_) | ty_opaque_box {} ty_param(_, _) { has_params = true; } ty_var(_) | ty_self(_) { has_vars = true; } @@ -468,7 +487,7 @@ fn mk_t_with_id(cx: ctxt, st: sty, o_def_id: option<ast::def_id>) -> t { derive_flags(has_params, has_vars, has_rptrs, tt); } } - ty_box(m) | ty_uniq(m) | ty_vec(m) | ty_ptr(m) { + ty_box(m) | ty_uniq(m) | ty_vec(m) | ty_evec(m, _) | ty_ptr(m) { derive_flags(has_params, has_vars, has_rptrs, m.ty); } ty_rptr(r, m) { @@ -536,6 +555,10 @@ fn mk_char(cx: ctxt) -> t { mk_t(cx, ty_int(ast::ty_char)) } fn mk_str(cx: ctxt) -> t { mk_t(cx, ty_str) } +fn mk_estr(cx: ctxt, t: vstore) -> t { + mk_t(cx, ty_estr(t)) +} + fn mk_enum(cx: ctxt, did: ast::def_id, tys: [t]) -> t { mk_t(cx, ty_enum(did, tys)) } @@ -567,6 +590,10 @@ fn mk_nil_ptr(cx: ctxt) -> t { fn mk_vec(cx: ctxt, tm: mt) -> t { mk_t(cx, ty_vec(tm)) } +fn mk_evec(cx: ctxt, tm: mt, t: vstore) -> t { + mk_t(cx, ty_evec(tm, t)) +} + fn mk_rec(cx: ctxt, fs: [field]) -> t { mk_t(cx, ty_rec(fs)) } fn mk_constr(cx: ctxt, t: t, cs: [@type_constr]) -> t { @@ -630,9 +657,10 @@ fn maybe_walk_ty(ty: t, f: fn(t) -> bool) { if !f(ty) { ret; } alt get(ty).struct { ty_nil | ty_bot | ty_bool | ty_int(_) | ty_uint(_) | ty_float(_) | - ty_str | ty_type | ty_opaque_box | + ty_str | ty_estr(_) | ty_type | ty_opaque_box | ty_opaque_closure_ptr(_) | ty_var(_) | ty_param(_, _) {} - ty_box(tm) | ty_vec(tm) | ty_ptr(tm) | ty_rptr(_, tm) { + ty_box(tm) | ty_vec(tm) | ty_evec(tm, _) | + ty_ptr(tm) | ty_rptr(_, tm) { maybe_walk_ty(tm.ty, f); } ty_enum(_, subtys) | ty_iface(_, subtys) | ty_class(_, subtys) @@ -674,6 +702,9 @@ fn fold_sty(sty: sty, fldop: fn(t) -> t) -> sty { ty_vec(tm) { ty_vec({ty: fldop(tm.ty), mutbl: tm.mutbl}) } + ty_evec(tm, vst) { + ty_evec({ty: fldop(tm.ty), mutbl: tm.mutbl}, vst) + } ty_enum(tid, subtys) { ty_enum(tid, vec::map(subtys) {|t| fldop(t) }) } @@ -718,7 +749,7 @@ fn fold_sty(sty: sty, fldop: fn(t) -> t) -> sty { ty_class(did, new_tps) } ty_nil | ty_bot | ty_bool | ty_int(_) | ty_uint(_) | ty_float(_) | - ty_str | ty_type | ty_opaque_closure_ptr(_) | + ty_str | ty_estr(_) | ty_type | ty_opaque_closure_ptr(_) | ty_opaque_box | ty_var(_) | ty_param(_, _) { sty } @@ -751,6 +782,15 @@ fn fold_region(cx: ctxt, t0: t, fldop: fn(region, bool) -> region) -> t { let m_t1 = do_fold(cx, t1, true, fldop); ty::mk_rptr(cx, m_r, {ty: m_t1, mutbl: m}) } + ty_estr(vstore_slice(r)) { + let m_r = fldop(r, under_r); + ty::mk_estr(cx, vstore_slice(m_r)) + } + ty_evec({ty: t1, mutbl: m}, vstore_slice(r)) { + let m_r = fldop(r, under_r); + let m_t1 = do_fold(cx, t1, true, fldop); + ty::mk_evec(cx, {ty: m_t1, mutbl: m}, vstore_slice(m_r)) + } ty_fn(_) { // do not recurse into functions, which introduce fresh bindings t0 @@ -786,7 +826,8 @@ fn type_is_bool(ty: t) -> bool { get(ty).struct == ty_bool } fn type_is_structural(ty: t) -> bool { alt get(ty).struct { ty_rec(_) | ty_class(_,_) | ty_tup(_) | ty_enum(_, _) | ty_fn(_) | - ty_iface(_, _) | ty_res(_, _, _) { true } + ty_iface(_, _) | ty_res(_, _, _) | ty_evec(_, vstore_fixed(_)) + | ty_estr(vstore_fixed(_)) { true } _ { false } } } @@ -797,18 +838,22 @@ fn type_is_copyable(cx: ctxt, ty: t) -> bool { fn type_is_sequence(ty: t) -> bool { alt get(ty).struct { - ty_str { ret true; } - ty_vec(_) { ret true; } - _ { ret false; } + ty_str | ty_estr(_) | ty_vec(_) | ty_evec(_, _) { true } + _ { false } } } -fn type_is_str(ty: t) -> bool { get(ty).struct == ty_str } +fn type_is_str(ty: t) -> bool { + alt get(ty).struct { + ty_str | ty_estr(_) { true } + _ { false } + } +} fn sequence_element_type(cx: ctxt, ty: t) -> t { alt get(ty).struct { - ty_str { ret mk_mach_uint(cx, ast::ty_u8); } - ty_vec(mt) { ret mt.ty; } + ty_str | ty_estr(_) { ret mk_mach_uint(cx, ast::ty_u8); } + ty_vec(mt) | ty_evec(mt, _) { ret mt.ty; } _ { cx.sess.bug("sequence_element_type called on non-sequence value"); } } } @@ -858,8 +903,8 @@ pure fn type_is_unsafe_ptr(ty: t) -> bool { pure fn type_is_vec(ty: t) -> bool { ret alt get(ty).struct { - ty_vec(_) { true } - ty_str { true } + ty_vec(_) | ty_evec(_, _) { true } + ty_str | ty_estr(_) { true } _ { false } }; } @@ -867,8 +912,8 @@ pure fn type_is_vec(ty: t) -> bool { pure fn type_is_unique(ty: t) -> bool { alt get(ty).struct { ty_uniq(_) { ret true; } - ty_vec(_) { true } - ty_str { true } + ty_vec(_) | ty_evec(_, vstore_uniq) { true } + ty_str | ty_estr(vstore_uniq) { true } _ { ret false; } } } @@ -897,7 +942,10 @@ fn type_needs_drop(cx: ctxt, ty: t) -> bool { let result = alt get(ty).struct { // scalar types ty_nil | ty_bot | ty_bool | ty_int(_) | ty_float(_) | ty_uint(_) | - ty_type | ty_ptr(_) | ty_rptr(_, _) { false } + ty_type | ty_ptr(_) | ty_rptr(_, _) | + ty_estr(vstore_fixed(_)) | ty_estr(vstore_slice(_)) | + ty_evec(_, vstore_slice(_)) { false } + ty_evec(mt, vstore_fixed(_)) { type_needs_drop(cx, mt.ty) } ty_rec(flds) { for flds.each {|f| if type_needs_drop(cx, f.mt.ty) { accum = true; } } accum @@ -983,7 +1031,12 @@ fn type_needs_unwind_cleanup_(cx: ctxt, ty: t, } !needs_unwind_cleanup } - ty_uniq(_) | ty_str | ty_vec(_) | ty_res(_, _, _) { + ty_uniq(_) | ty_str | ty_vec(_) | ty_res(_, _, _) | + ty_estr(vstore_uniq) | + ty_estr(vstore_box) | + ty_evec(_, vstore_uniq) | + ty_evec(_, vstore_box) + { // Once we're inside a box, the annihilator will find // it and destroy it. if !encountered_box { @@ -1046,6 +1099,17 @@ fn lower_kind(a: kind, b: kind) -> kind { if kind_lteq(a, b) { a } else { b } } +#[test] +fn test_kinds() { + // The kind "lattice" is nocopy <= copy <= send + assert kind_lteq(kind_sendable, kind_sendable); + assert kind_lteq(kind_copyable, kind_sendable); + assert kind_lteq(kind_copyable, kind_copyable); + assert kind_lteq(kind_noncopyable, kind_sendable); + assert kind_lteq(kind_noncopyable, kind_copyable); + assert kind_lteq(kind_noncopyable, kind_noncopyable); +} + fn type_kind(cx: ctxt, ty: t) -> kind { alt cx.kind_cache.find(ty) { some(result) { ret result; } @@ -1061,15 +1125,33 @@ fn type_kind(cx: ctxt, ty: t) -> kind { ty_ptr(_) | ty_str { kind_sendable } ty_type { kind_copyable } ty_fn(f) { proto_kind(f.proto) } + + // Closures have kind determined by capture mode ty_opaque_closure_ptr(ck_block) { kind_noncopyable } ty_opaque_closure_ptr(ck_box) { kind_copyable } ty_opaque_closure_ptr(ck_uniq) { kind_sendable } - // Those with refcounts-to-inner raise pinned to shared, - // lower unique to shared. Therefore just set result to shared. + + // Those with refcounts raise noncopyable to copyable, + // lower sendable to copyable. Therefore just set result to copyable. ty_box(_) | ty_iface(_, _) | ty_opaque_box { kind_copyable } ty_rptr(_, _) { kind_copyable } - // Boxes and unique pointers raise pinned to shared. + + // Unique boxes and vecs have the kind of their contained type. ty_vec(tm) | ty_uniq(tm) { type_kind(cx, tm.ty) } + + // Slice and refcounted evecs are copyable; uniques and interiors + // depend on the their contained type. + ty_evec(_, vstore_box) | + ty_evec(_, vstore_slice(_)) { kind_copyable } + ty_evec(tm, vstore_uniq) | + ty_evec(tm, vstore_fixed(_)) { type_kind(cx, tm.ty) } + + // All estrs are copyable; uniques and interiors are sendable. + ty_estr(vstore_box) | + ty_estr(vstore_slice(_)) { kind_copyable } + ty_estr(vstore_uniq) | + ty_estr(vstore_fixed(_)) { kind_sendable } + // Records lower to the lowest of their members. ty_rec(flds) { let mut lowest = kind_sendable; @@ -1152,6 +1234,7 @@ fn is_instantiable(cx: ctxt, r_ty: t) -> bool { ty_uint(_) | ty_float(_) | ty_str | + ty_estr(_) | ty_fn(_) | ty_var(_) | ty_param(_, _) | @@ -1159,6 +1242,7 @@ fn is_instantiable(cx: ctxt, r_ty: t) -> bool { ty_type | ty_opaque_box | ty_opaque_closure_ptr(_) | + ty_evec(_, _) | ty_vec(_) { false } @@ -1277,6 +1361,9 @@ fn type_structurally_contains(cx: ctxt, ty: t, test: fn(sty) -> bool) -> let sty = substitute_type_params(cx, tps, sub); ret type_structurally_contains(cx, sty, test); } + ty_evec(mt, vstore_fixed(_)) { + ret type_structurally_contains(cx, mt.ty, test); + } _ { ret false; } } } @@ -1288,6 +1375,11 @@ fn type_allows_implicit_copy(cx: ctxt, ty: t) -> bool { ret !type_structurally_contains(cx, ty, {|sty| alt sty { ty_param(_, _) { true } + + ty_evec(_, _) | ty_estr(_) { + cx.sess.unimpl("estr/evec in type_allows_implicit_copy"); + } + ty_vec(mt) { mt.mutbl != ast::m_imm } @@ -1302,9 +1394,11 @@ fn type_allows_implicit_copy(cx: ctxt, ty: t) -> bool { fn type_structurally_contains_uniques(cx: ctxt, ty: t) -> bool { ret type_structurally_contains(cx, ty, {|sty| alt sty { - ty_uniq(_) { true } - ty_vec(_) { true } - ty_str { true } + ty_uniq(_) | + ty_vec(_) | + ty_evec(_, vstore_uniq) | + ty_str | + ty_estr(vstore_uniq) { true } _ { false } } }); @@ -1365,6 +1459,10 @@ fn type_is_pod(cx: ctxt, ty: t) -> bool { ty_tup(elts) { for elts.each {|elt| if !type_is_pod(cx, elt) { result = false; } } } + ty_estr(vstore_fixed(_)) { result = true; } + ty_evec(mt, vstore_fixed(_)) { + result = type_is_pod(cx, mt.ty); + } ty_res(_, inner, tps) { result = type_is_pod(cx, substitute_type_params(cx, tps, inner)); } @@ -1503,6 +1601,7 @@ fn hash_type_structure(st: sty) -> uint { ty_float(t) { alt t { ast::ty_f { 13u } ast::ty_f32 { 14u } ast::ty_f64 { 15u } } } + ty_estr(_) { 16u } ty_str { 17u } ty_enum(did, tys) { let mut h = hash_def(18u, did); @@ -1510,6 +1609,7 @@ fn hash_type_structure(st: sty) -> uint { h } ty_box(mt) { hash_subty(19u, mt.ty) } + ty_evec(mt, _) { hash_subty(20u, mt.ty) } ty_vec(mt) { hash_subty(21u, mt.ty) } ty_rec(fields) { let mut h = 26u; @@ -1849,15 +1949,15 @@ fn set_default_mode(cx: ctxt, m: ast::mode, m_def: ast::rmode) { fn ty_sort_str(cx: ctxt, t: t) -> str { alt get(t).struct { ty_nil | ty_bot | ty_bool | ty_int(_) | - ty_uint(_) | ty_float(_) | ty_str | ty_type | ty_opaque_box | - ty_opaque_closure_ptr(_) { + ty_uint(_) | ty_float(_) | ty_estr(_) | ty_str | + ty_type | ty_opaque_box | ty_opaque_closure_ptr(_) { ty_to_str(cx, t) } ty_enum(_, _) { "enum" } ty_box(_) { "@-ptr" } ty_uniq(_) { "~-ptr" } - ty_vec(_) { "vector" } + ty_evec(_, _) | ty_vec(_) { "vector" } ty_ptr(_) { "*-ptr" } ty_rptr(_, _) { "&-ptr" } ty_rec(_) { "record" } @@ -2312,14 +2412,11 @@ fn is_binopable(_cx: ctxt, ty: t, op: ast::binop) -> bool { fn tycat(ty: t) -> int { alt get(ty).struct { ty_bool { tycat_bool } - ty_int(_) { tycat_int } - ty_uint(_) { tycat_int } + ty_int(_) | ty_uint(_) { tycat_int } ty_float(_) { tycat_float } - ty_str { tycat_str } - ty_vec(_) { tycat_vec } - ty_rec(_) { tycat_struct } - ty_tup(_) { tycat_struct } - ty_enum(_, _) { tycat_struct } + ty_estr(_) | ty_str { tycat_str } + ty_evec(_, _) | ty_vec(_) { tycat_vec } + ty_rec(_) | ty_tup(_) | ty_enum(_, _) { tycat_struct } ty_bot { tycat_bot } _ { tycat_other } } diff --git a/src/rustc/middle/typeck.rs b/src/rustc/middle/typeck.rs index f89a34e668f..46e8a2ad096 100644 --- a/src/rustc/middle/typeck.rs +++ b/src/rustc/middle/typeck.rs @@ -276,6 +276,53 @@ fn type_is_c_like_enum(fcx: @fn_ctxt, sp: span, typ: ty::t) -> bool { enum mode { m_collect, m_check, m_check_tyvar(@fn_ctxt), } +fn ast_region_to_region(tcx: ty::ctxt, + region: ast::region) -> ty::region { + alt region.node { + ast::re_inferred { + // this must be replaced later by a fixup_regions() pass + ty::re_default + } + ast::re_self | ast::re_named(_) { + tcx.region_map.ast_type_to_region.get(region.id) + } + ast::re_static { + ty::re_static + } + } +} + +fn ast_vstore_to_vstore(tcx: ty::ctxt, span: span, n: option<uint>, + v: ast::vstore) -> ty::vstore { + alt v { + ast::vstore_fixed(none) { + alt n { + some(n) { ty::vstore_fixed(n) } + none { + tcx.sess.bug("implied fixed length in ast_vstore_to_vstore with \ + no default length") + } + } + } + ast::vstore_fixed(some(u)) { + alt n { + some(n) if n != u { + tcx.sess.span_err(span, + #fmt("fixed-size sequence mismatch: %u vs. %u", + u, n)); + } + _ { } + } + ty::vstore_fixed(u) + } + ast::vstore_uniq { ty::vstore_uniq } + ast::vstore_box { ty::vstore_box } + ast::vstore_slice(region) { + ty::vstore_slice(ast_region_to_region(tcx, region)) + } + } +} + // Parses the programmer's textual representation of a type into our // internal notion of a type. `getter` is a function that returns the type // corresponding to a definition ID: @@ -361,19 +408,8 @@ fn ast_ty_to_ty(tcx: ty::ctxt, mode: mode, &&ast_ty: @ast::ty) -> ty::t { ty::mk_ptr(tcx, ast_mt_to_mt(tcx, mode, mt)) } ast::ty_rptr(region, mt) { - let r = alt region.node { - ast::re_inferred { - // this must be replaced later by a fixup_regions() pass - ty::re_default - } - ast::re_self | ast::re_named(_) { - tcx.region_map.ast_type_to_region.get(region.id) - } - ast::re_static { - ty::re_static - } - }; - ty::mk_rptr(tcx, r, ast_mt_to_mt(tcx, mode, mt)) + let region = ast_region_to_region(tcx, region); + ty::mk_rptr(tcx, region, ast_mt_to_mt(tcx, mode, mt)) } ast::ty_tup(fields) { let flds = vec::map(fields, bind do_ast_ty_to_ty(tcx, mode, _)); @@ -436,6 +472,18 @@ fn ast_ty_to_ty(tcx: ty::ctxt, mode: mode, &&ast_ty: @ast::ty) -> ty::t { } } } + ast::ty_vstore(t, vst) { + let vst = ast_vstore_to_vstore(tcx, ast_ty.span, none, vst); + alt ty::get(do_ast_ty_to_ty(tcx, mode, t)).struct { + ty::ty_vec(mt) { ty::mk_evec(tcx, mt, vst) } + ty::ty_str { ty::mk_estr(tcx, vst) } + _ { + tcx.sess.span_fatal(ast_ty.span, + "found sequence storage modifier \ + on non-sequence type"); + } + } + } ast::ty_constr(t, cs) { let mut out_cs = []; for cs.each {|constr| @@ -2799,6 +2847,31 @@ fn check_expr_with_unifier(fcx: @fn_ctxt, expr: @ast::expr, unify: unifier, let id = expr.id; let mut bot = false; alt expr.node { + + ast::expr_vstore(ev, vst) { + alt ev.node { + ast::expr_lit(@{node: ast::lit_str(s), span:_}) { + let tt = ast_vstore_to_vstore(tcx, expr.span, + some(str::len(s)), vst); + let typ = ty::mk_estr(tcx, tt); + fcx.write_ty(ev.id, typ); + fcx.write_ty(id, typ); + } + ast::expr_vec(args, mutbl) { + let tt = ast_vstore_to_vstore(tcx, expr.span, + some(vec::len(args)), vst); + let t: ty::t = next_ty_var(fcx); + for args.each {|e| bot |= check_expr_with(fcx, e, t); } + let typ = ty::mk_evec(tcx, {ty: t, mutbl: mutbl}, tt); + fcx.write_ty(ev.id, typ); + fcx.write_ty(id, typ); + } + _ { + tcx.sess.span_err(expr.span, "vstore modifier on non-sequence"); + } + } + } + ast::expr_lit(lit) { let typ = check_lit(fcx.ccx, lit); fcx.write_ty(id, typ); @@ -3319,10 +3392,12 @@ fn check_expr_with_unifier(fcx: @fn_ctxt, expr: @ast::expr, unify: unifier, bot |= check_expr(fcx, idx); let idx_t = fcx.expr_ty(idx); alt structure_of(fcx, expr.span, base_t) { + ty::ty_evec(mt, _) | ty::ty_vec(mt) { require_integral(fcx, idx.span, idx_t); fcx.write_ty(id, mt.ty); } + ty::ty_estr(_) | ty::ty_str { require_integral(fcx, idx.span, idx_t); let typ = ty::mk_mach_uint(tcx, ast::ty_u8); |
