Add vstore/evec/estr to compiler.
This commit is contained in:
parent
0c94cd5d43
commit
7a3b290245
19 changed files with 605 additions and 107 deletions
|
@ -169,6 +169,14 @@ enum proto {
|
|||
proto_block, // fn&
|
||||
}
|
||||
|
||||
#[auto_serialize]
|
||||
enum vstore {
|
||||
vstore_fixed(option<uint>), // [1,2,3,4]/_ or 4 FIXME: uint -> @expr
|
||||
vstore_uniq, // [1,2,3,4]/~
|
||||
vstore_box, // [1,2,3,4]/@
|
||||
vstore_slice(region) // [1,2,3,4]/&(foo)?
|
||||
}
|
||||
|
||||
pure fn is_blockish(p: ast::proto) -> bool {
|
||||
alt p {
|
||||
proto_any | proto_block { true }
|
||||
|
@ -278,6 +286,7 @@ enum alt_mode { alt_check, alt_exhaustive, }
|
|||
|
||||
#[auto_serialize]
|
||||
enum expr_ {
|
||||
expr_vstore(@expr, vstore),
|
||||
expr_vec([@expr], mutability),
|
||||
expr_rec([field], option<@expr>),
|
||||
expr_call(@expr, [@expr], bool),
|
||||
|
@ -459,6 +468,7 @@ enum ty_ {
|
|||
ty_tup([@ty]),
|
||||
ty_path(@path, node_id),
|
||||
ty_constr(@ty, [@ty_constr]),
|
||||
ty_vstore(@ty, vstore),
|
||||
ty_mac(mac),
|
||||
// ty_infer means the type should be inferred instead of it having been
|
||||
// specified. This should only appear at the "top level" of a type and not
|
||||
|
|
|
@ -367,8 +367,7 @@ fn ser_ty(cx: ext_ctxt, tps: ser_tps_map,
|
|||
}
|
||||
|
||||
ast::ty_ptr(_) | ast::ty_rptr(_, _) {
|
||||
cx.span_err(
|
||||
ty.span, #fmt["Cannot serialize pointer types"]);
|
||||
cx.span_err(ty.span, "cannot serialize pointer types");
|
||||
[]
|
||||
}
|
||||
|
||||
|
@ -390,8 +389,7 @@ fn ser_ty(cx: ext_ctxt, tps: ser_tps_map,
|
|||
}
|
||||
|
||||
ast::ty_fn(_, _) {
|
||||
cx.span_err(
|
||||
ty.span, #fmt["Cannot serialize function types"]);
|
||||
cx.span_err(ty.span, "cannot serialize function types");
|
||||
[]
|
||||
}
|
||||
|
||||
|
@ -448,17 +446,19 @@ fn ser_ty(cx: ext_ctxt, tps: ser_tps_map,
|
|||
}
|
||||
|
||||
ast::ty_mac(_) {
|
||||
cx.span_err(
|
||||
ty.span, #fmt["Cannot serialize macro types"]);
|
||||
cx.span_err(ty.span, "cannot serialize macro types");
|
||||
[]
|
||||
}
|
||||
|
||||
ast::ty_infer {
|
||||
cx.span_err(
|
||||
ty.span, #fmt["Cannot serialize inferred types"]);
|
||||
cx.span_err(ty.span, "cannot serialize inferred types");
|
||||
[]
|
||||
}
|
||||
|
||||
ast::ty_vstore(_, _) {
|
||||
cx.span_unimpl(ty.span, "serialization for vstore types");
|
||||
}
|
||||
|
||||
ast::ty_vec(mt) {
|
||||
let ser_e =
|
||||
cx.expr(
|
||||
|
@ -675,6 +675,10 @@ fn deser_ty(cx: ext_ctxt, tps: deser_tps_map,
|
|||
#ast{ fail }
|
||||
}
|
||||
|
||||
ast::ty_vstore(_, _) {
|
||||
cx.span_unimpl(ty.span, "deserialization for vstore types");
|
||||
}
|
||||
|
||||
ast::ty_vec(mt) {
|
||||
let l = deser_lambda(cx, tps, mt.ty, cx.clone(d));
|
||||
#ast{ std::serialization::read_to_vec($(d), $(l)) }
|
||||
|
|
|
@ -389,6 +389,9 @@ fn noop_fold_expr(e: expr_, fld: ast_fold) -> expr_ {
|
|||
fld.new_id(i),
|
||||
fld.fold_expr(v))
|
||||
}
|
||||
expr_vstore(e, v) {
|
||||
expr_vstore(fld.fold_expr(e), v)
|
||||
}
|
||||
expr_vec(exprs, mutt) {
|
||||
expr_vec(fld.map_exprs(fld.fold_expr, exprs), mutt)
|
||||
}
|
||||
|
@ -497,6 +500,7 @@ fn noop_fold_ty(t: ty_, fld: ast_fold) -> ty_ {
|
|||
ty_path(path, id) {ty_path(fld.fold_path(path), fld.new_id(id))}
|
||||
// FIXME: constrs likely needs to be folded...
|
||||
ty_constr(ty, constrs) {ty_constr(fld.fold_ty(ty), constrs)}
|
||||
ty_vstore(t, vs) {ty_vstore(fld.fold_ty(t), vs)}
|
||||
ty_mac(mac) {ty_mac(fold_mac(mac))}
|
||||
ty_infer {t}
|
||||
}
|
||||
|
|
|
@ -382,15 +382,32 @@ fn parse_type_constraints(p: parser) -> [@ast::ty_constr] {
|
|||
|
||||
fn parse_ty_postfix(orig_t: ast::ty_, p: parser, colons_before_params: bool,
|
||||
lo: uint) -> @ast::ty {
|
||||
|
||||
|
||||
fn mk_ty(p: parser, t: ast::ty_, lo: uint, hi: uint) -> @ast::ty {
|
||||
@{id: p.get_id(),
|
||||
node: t,
|
||||
span: ast_util::mk_sp(lo, hi)}
|
||||
}
|
||||
|
||||
if p.token == token::BINOP(token::SLASH) {
|
||||
let orig_hi = p.last_span.hi;
|
||||
alt parse_maybe_vstore(p) {
|
||||
none { }
|
||||
some(v) {
|
||||
let t = ast::ty_vstore(mk_ty(p, orig_t, lo, orig_hi), v);
|
||||
ret mk_ty(p, t, lo, p.last_span.hi);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if colons_before_params && p.token == token::MOD_SEP {
|
||||
p.bump();
|
||||
expect(p, token::LT);
|
||||
} else if !colons_before_params && p.token == token::LT {
|
||||
p.bump();
|
||||
} else {
|
||||
ret @{id: p.get_id(),
|
||||
node: orig_t,
|
||||
span: ast_util::mk_sp(lo, p.last_span.hi)};
|
||||
ret mk_ty(p, orig_t, lo, p.last_span.hi);
|
||||
}
|
||||
|
||||
// If we're here, we have explicit type parameter instantiation.
|
||||
|
@ -399,12 +416,11 @@ fn parse_ty_postfix(orig_t: ast::ty_, p: parser, colons_before_params: bool,
|
|||
|
||||
alt orig_t {
|
||||
ast::ty_path(pth, ann) {
|
||||
ret @{id: p.get_id(),
|
||||
node: ast::ty_path(@spanned(lo, p.last_span.hi,
|
||||
{global: pth.node.global,
|
||||
idents: pth.node.idents,
|
||||
types: seq}), ann),
|
||||
span: ast_util::mk_sp(lo, p.last_span.hi)};
|
||||
ret mk_ty(p, ast::ty_path(@spanned(lo, p.last_span.hi,
|
||||
{global: pth.node.global,
|
||||
idents: pth.node.idents,
|
||||
types: seq}), ann),
|
||||
lo, p.last_span.hi);
|
||||
}
|
||||
_ { p.fatal("type parameter instantiation only allowed for paths"); }
|
||||
}
|
||||
|
@ -428,22 +444,33 @@ fn parse_ret_ty(p: parser) -> (ast::ret_style, @ast::ty) {
|
|||
}
|
||||
}
|
||||
|
||||
fn parse_region(p: parser) -> ast::region {
|
||||
let region_ = alt p.token {
|
||||
token::IDENT(sid, _) if p.look_ahead(1u) == token::DOT {
|
||||
let string = p.get_str(sid);
|
||||
p.bump(); p.bump();
|
||||
if string == "self" {
|
||||
ast::re_self
|
||||
} else if string == "static" {
|
||||
ast::re_static
|
||||
} else {
|
||||
ast::re_named(string)
|
||||
}
|
||||
fn region_from_name(p: parser, s: option<str>) -> ast::region {
|
||||
let r = alt s {
|
||||
some (string) {
|
||||
if string == "self" {
|
||||
ast::re_self
|
||||
} else if string == "static" {
|
||||
ast::re_static
|
||||
} else {
|
||||
ast::re_named(string)
|
||||
}
|
||||
_ { ast::re_inferred }
|
||||
}
|
||||
none { ast::re_inferred }
|
||||
};
|
||||
ret {id: p.get_id(), node: region_};
|
||||
|
||||
{id: p.get_id(), node: r}
|
||||
}
|
||||
|
||||
fn parse_region(p: parser) -> ast::region {
|
||||
let name =
|
||||
alt p.token {
|
||||
token::IDENT(sid, _) if p.look_ahead(1u) == token::DOT {
|
||||
p.bump(); p.bump();
|
||||
some(p.get_str(sid))
|
||||
}
|
||||
_ { none }
|
||||
};
|
||||
region_from_name(p, name)
|
||||
}
|
||||
|
||||
fn parse_ty(p: parser, colons_before_params: bool) -> @ast::ty {
|
||||
|
@ -666,6 +693,44 @@ fn have_dollar(p: parser) -> option<ast::mac_> {
|
|||
}
|
||||
}
|
||||
|
||||
fn parse_maybe_vstore(p: parser) -> option<ast::vstore> {
|
||||
if p.token == token::BINOP(token::SLASH) {
|
||||
p.bump();
|
||||
alt p.token {
|
||||
token::AT {
|
||||
p.bump(); some(ast::vstore_box)
|
||||
}
|
||||
token::TILDE {
|
||||
p.bump(); some(ast::vstore_uniq)
|
||||
}
|
||||
token::UNDERSCORE {
|
||||
p.bump(); some(ast::vstore_fixed(none))
|
||||
}
|
||||
token::LIT_INT(i, ast::ty_i) if i >= 0 {
|
||||
p.bump(); some(ast::vstore_fixed(some(i as uint)))
|
||||
}
|
||||
token::BINOP(token::AND) {
|
||||
p.bump();
|
||||
alt p.token {
|
||||
token::IDENT(sid, _) {
|
||||
p.bump();
|
||||
let n = p.get_str(sid);
|
||||
some(ast::vstore_slice(region_from_name(p, some(n))))
|
||||
}
|
||||
_ {
|
||||
some(ast::vstore_slice(region_from_name(p, none)))
|
||||
}
|
||||
}
|
||||
}
|
||||
_ {
|
||||
none
|
||||
}
|
||||
}
|
||||
} else {
|
||||
none
|
||||
}
|
||||
}
|
||||
|
||||
fn lit_from_token(p: parser, tok: token::token) -> ast::lit_ {
|
||||
alt tok {
|
||||
token::LIT_INT(i, it) { ast::lit_int(i, it) }
|
||||
|
@ -678,7 +743,7 @@ fn lit_from_token(p: parser, tok: token::token) -> ast::lit_ {
|
|||
}
|
||||
|
||||
fn parse_lit(p: parser) -> ast::lit {
|
||||
let sp = p.span;
|
||||
let lo = p.span.lo;
|
||||
let lit = if eat_word(p, "true") {
|
||||
ast::lit_bool(true)
|
||||
} else if eat_word(p, "false") {
|
||||
|
@ -688,7 +753,7 @@ fn parse_lit(p: parser) -> ast::lit {
|
|||
p.bump();
|
||||
lit_from_token(p, tok)
|
||||
};
|
||||
ret {node: lit, span: sp};
|
||||
ret {node: lit, span: ast_util::mk_sp(lo, p.last_span.hi)};
|
||||
}
|
||||
|
||||
fn is_ident(t: token::token) -> bool {
|
||||
|
@ -891,6 +956,7 @@ fn parse_bottom_expr(p: parser) -> pexpr {
|
|||
let es =
|
||||
parse_seq_to_end(token::RBRACKET, seq_sep(token::COMMA),
|
||||
parse_expr, p);
|
||||
hi = p.span.hi;
|
||||
ex = ast::expr_vec(es, mutbl);
|
||||
} else if p.token == token::POUND_LT {
|
||||
p.bump();
|
||||
|
@ -988,6 +1054,23 @@ fn parse_bottom_expr(p: parser) -> pexpr {
|
|||
hi = lit.span.hi;
|
||||
ex = ast::expr_lit(@lit);
|
||||
}
|
||||
|
||||
// Vstore is legal following expr_lit(lit_str(...)) and expr_vec(...)
|
||||
// only.
|
||||
alt ex {
|
||||
ast::expr_lit(@{node: ast::lit_str(_), span: _}) |
|
||||
ast::expr_vec(_, _) {
|
||||
alt parse_maybe_vstore(p) {
|
||||
none { }
|
||||
some(v) {
|
||||
hi = p.span.hi;
|
||||
ex = ast::expr_vstore(mk_expr(p, lo, hi, ex), v);
|
||||
}
|
||||
}
|
||||
}
|
||||
_ { }
|
||||
}
|
||||
|
||||
ret mk_pexpr(p, lo, hi, ex);
|
||||
}
|
||||
|
||||
|
@ -1194,10 +1277,10 @@ type op_spec = {tok: token::token, op: ast::binop, prec: int};
|
|||
|
||||
// FIXME make this a const, don't store it in parser state
|
||||
fn prec_table() -> @[op_spec] {
|
||||
ret @[// 'as' sits between here with 12
|
||||
{tok: token::BINOP(token::STAR), op: ast::mul, prec: 11},
|
||||
{tok: token::BINOP(token::SLASH), op: ast::div, prec: 11},
|
||||
{tok: token::BINOP(token::PERCENT), op: ast::rem, prec: 11},
|
||||
ret @[{tok: token::BINOP(token::STAR), op: ast::mul, prec: 12},
|
||||
{tok: token::BINOP(token::SLASH), op: ast::div, prec: 12},
|
||||
{tok: token::BINOP(token::PERCENT), op: ast::rem, prec: 12},
|
||||
// 'as' sits between here with 11
|
||||
{tok: token::BINOP(token::PLUS), op: ast::add, prec: 10},
|
||||
{tok: token::BINOP(token::MINUS), op: ast::subtract, prec: 10},
|
||||
{tok: token::BINOP(token::LSL), op: ast::lsl, prec: 9},
|
||||
|
@ -1222,7 +1305,7 @@ fn parse_binops(p: parser) -> @ast::expr {
|
|||
|
||||
const unop_prec: int = 100;
|
||||
|
||||
const as_prec: int = 12;
|
||||
const as_prec: int = 11;
|
||||
|
||||
fn parse_more_binops(p: parser, plhs: pexpr, min_prec: int) ->
|
||||
@ast::expr {
|
||||
|
|
|
@ -378,6 +378,10 @@ fn print_type(s: ps, &&ty: @ast::ty) {
|
|||
space(s.s);
|
||||
word(s.s, constrs_str(cs, ty_constr_to_str));
|
||||
}
|
||||
ast::ty_vstore(t, v) {
|
||||
print_type(s, t);
|
||||
print_vstore(s, v);
|
||||
}
|
||||
ast::ty_mac(_) {
|
||||
fail "print_type doesn't know how to print a ty_mac";
|
||||
}
|
||||
|
@ -810,12 +814,36 @@ fn print_mac(s: ps, m: ast::mac) {
|
|||
}
|
||||
}
|
||||
|
||||
fn print_vstore(s: ps, t: ast::vstore) {
|
||||
alt t {
|
||||
ast::vstore_fixed(some(i)) { word_space(s, #fmt("/%u", i)); }
|
||||
ast::vstore_fixed(none) { word_space(s, "/_"); }
|
||||
ast::vstore_uniq { word_space(s, "/~"); }
|
||||
ast::vstore_box { word_space(s, "/@"); }
|
||||
ast::vstore_slice(r) {
|
||||
alt r.node {
|
||||
ast::re_inferred { word_space(s, "/&"); }
|
||||
ast::re_self { word_space(s, "/&self"); }
|
||||
ast::re_static { word_space(s, "/&static"); }
|
||||
ast::re_named(name) {
|
||||
word(s.s, "/&");
|
||||
word_space(s, name);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn print_expr(s: ps, &&expr: @ast::expr) {
|
||||
maybe_print_comment(s, expr.span.lo);
|
||||
ibox(s, indent_unit);
|
||||
let ann_node = node_expr(s, expr);
|
||||
s.ann.pre(ann_node);
|
||||
alt expr.node {
|
||||
ast::expr_vstore(e, v) {
|
||||
print_expr(s, e);
|
||||
print_vstore(s, v);
|
||||
}
|
||||
ast::expr_vec(exprs, mutbl) {
|
||||
ibox(s, indent_unit);
|
||||
word(s.s, "[");
|
||||
|
|
|
@ -170,11 +170,10 @@ fn skip_ty<E>(_t: @ty, _e: E, _v: vt<E>) {}
|
|||
|
||||
fn visit_ty<E>(t: @ty, e: E, v: vt<E>) {
|
||||
alt t.node {
|
||||
ty_box(mt) { v.visit_ty(mt.ty, e, v); }
|
||||
ty_uniq(mt) { v.visit_ty(mt.ty, e, v); }
|
||||
ty_vec(mt) { v.visit_ty(mt.ty, e, v); }
|
||||
ty_ptr(mt) { v.visit_ty(mt.ty, e, v); }
|
||||
ty_rptr(_, mt) { v.visit_ty(mt.ty, e, v); }
|
||||
ty_box(mt) | ty_uniq(mt) |
|
||||
ty_vec(mt) | ty_ptr(mt) | ty_rptr(_, mt) {
|
||||
v.visit_ty(mt.ty, e, v);
|
||||
}
|
||||
ty_rec(flds) {
|
||||
for flds.each {|f| v.visit_ty(f.node.mt.ty, e, v); }
|
||||
}
|
||||
|
@ -187,6 +186,9 @@ fn visit_ty<E>(t: @ty, e: E, v: vt<E>) {
|
|||
v.visit_ty(decl.output, e, v);
|
||||
}
|
||||
ty_path(p, _) { visit_path(p, e, v); }
|
||||
ty_vstore(t, _) {
|
||||
v.visit_ty(t, e, v);
|
||||
}
|
||||
ty_constr(t, cs) {
|
||||
v.visit_ty(t, e, v);
|
||||
for cs.each {|tc|
|
||||
|
@ -335,6 +337,7 @@ fn visit_expr<E>(ex: @expr, e: E, v: vt<E>) {
|
|||
v.visit_expr(pool, e, v);
|
||||
v.visit_expr(val, e, v);
|
||||
}
|
||||
expr_vstore(x, _) { v.visit_expr(x, e, v); }
|
||||
expr_vec(es, _) { visit_exprs(es, e, v); }
|
||||
expr_rec(flds, base) {
|
||||
for flds.each {|f| v.visit_expr(f.node.expr, e, v); }
|
||||
|
|
|
@ -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[");
|
||||
|
|
|
@ -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}];
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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) {
|
||||
|
|
|
@ -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 }
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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();
|
||||
|
|
|
@ -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|
|
||||
|
|
|
@ -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(_, _) {
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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),
|
||||
|
|
|
@ -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 }
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -1,9 +1,8 @@
|
|||
// xfail-test
|
||||
fn main() {
|
||||
let x : str/5 = "hello"/5;
|
||||
let y : str/5 = "there"/_;
|
||||
let _y : str/5 = "there"/_;
|
||||
let mut z = "thing"/_;
|
||||
z = x;
|
||||
assert z[1] == 'h' as u8;
|
||||
assert z[4] == 'g' as u8;
|
||||
assert z[0] == ('h' as u8);
|
||||
assert z[4] == ('o' as u8);
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue