Implement mutable/immutable alias distinction.
Before, all aliases were implicitly mutable, and writing &mutable was the same as writing &. Now, the two are distinguished, and assignments to regular aliases are no longer allowed.
This commit is contained in:
parent
798bbd2e22
commit
fccf065266
11 changed files with 108 additions and 64 deletions
|
@ -203,7 +203,7 @@ fn unop_to_str(unop op) -> str {
|
||||||
|
|
||||||
tag mode {
|
tag mode {
|
||||||
val;
|
val;
|
||||||
alias;
|
alias(bool);
|
||||||
}
|
}
|
||||||
|
|
||||||
type stmt = spanned[stmt_];
|
type stmt = spanned[stmt_];
|
||||||
|
|
|
@ -328,8 +328,12 @@ fn parse_ty_fn(@pstate st, str_def sd) -> tup(vec[ty::arg], ty::t,
|
||||||
while (peek(st) as char != ']') {
|
while (peek(st) as char != ']') {
|
||||||
auto mode = ty::mo_val;
|
auto mode = ty::mo_val;
|
||||||
if (peek(st) as char == '&') {
|
if (peek(st) as char == '&') {
|
||||||
mode = ty::mo_alias;
|
mode = ty::mo_alias(false);
|
||||||
st.pos = st.pos + 1u;
|
st.pos += 1u;
|
||||||
|
if (peek(st) as char == 'm') {
|
||||||
|
mode = ty::mo_alias(true);
|
||||||
|
st.pos += 1u;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
inputs += [rec(mode=mode, ty=parse_ty(st, sd))];
|
inputs += [rec(mode=mode, ty=parse_ty(st, sd))];
|
||||||
}
|
}
|
||||||
|
|
|
@ -319,16 +319,10 @@ fn parse_ty_fn(ast::proto proto, &parser p, uint lo)
|
||||||
-> ast::ty_ {
|
-> ast::ty_ {
|
||||||
fn parse_fn_input_ty(&parser p) -> ast::ty_arg {
|
fn parse_fn_input_ty(&parser p) -> ast::ty_arg {
|
||||||
auto lo = p.get_lo_pos();
|
auto lo = p.get_lo_pos();
|
||||||
auto mode;
|
auto mode = ast::val;
|
||||||
if (p.peek() == token::BINOP(token::AND)) {
|
if (p.peek() == token::BINOP(token::AND)) {
|
||||||
p.bump();
|
p.bump();
|
||||||
mode = ast::alias;
|
mode = ast::alias(eat_word(p, "mutable"));
|
||||||
|
|
||||||
if (eat_word(p, "mutable")) {
|
|
||||||
// TODO: handle mutable alias args
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
mode = ast::val;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
auto t = parse_ty(p);
|
auto t = parse_ty(p);
|
||||||
|
@ -598,11 +592,8 @@ fn parse_ty(&parser p) -> @ast::ty {
|
||||||
fn parse_arg(&parser p) -> ast::arg {
|
fn parse_arg(&parser p) -> ast::arg {
|
||||||
let ast::mode m = ast::val;
|
let ast::mode m = ast::val;
|
||||||
if (p.peek() == token::BINOP(token::AND)) {
|
if (p.peek() == token::BINOP(token::AND)) {
|
||||||
m = ast::alias;
|
|
||||||
p.bump();
|
p.bump();
|
||||||
|
m = ast::alias(eat_word(p, "mutable"));
|
||||||
// TODO: handle mutable alias args
|
|
||||||
eat_word(p, "mutable");
|
|
||||||
}
|
}
|
||||||
let @ast::ty t = parse_ty(p);
|
let @ast::ty t = parse_ty(p);
|
||||||
let ast::ident i = parse_value_ident(p);
|
let ast::ident i = parse_value_ident(p);
|
||||||
|
|
|
@ -23,7 +23,12 @@ type restrict = @rec(vec[def_num] root_vars,
|
||||||
vec[uint] depends_on,
|
vec[uint] depends_on,
|
||||||
mutable valid ok);
|
mutable valid ok);
|
||||||
|
|
||||||
type scope = vec[restrict];
|
type scope = rec(vec[tup(def_num, ast::mode)] args,
|
||||||
|
vec[restrict] rs);
|
||||||
|
fn scope(&scope sc, vec[restrict] add) -> scope {
|
||||||
|
ret rec(args=sc.args, rs=sc.rs + add);
|
||||||
|
}
|
||||||
|
|
||||||
type ctx = rec(@ty::ctxt tcx,
|
type ctx = rec(@ty::ctxt tcx,
|
||||||
resolve::def_map dm);
|
resolve::def_map dm);
|
||||||
|
|
||||||
|
@ -32,13 +37,17 @@ fn check_crate(@ty::ctxt tcx, resolve::def_map dm, &@ast::crate crate) {
|
||||||
auto v = @rec(visit_fn = visit_fn,
|
auto v = @rec(visit_fn = visit_fn,
|
||||||
visit_expr = bind visit_expr(cx, _, _, _)
|
visit_expr = bind visit_expr(cx, _, _, _)
|
||||||
with *visit::default_visitor[scope]());
|
with *visit::default_visitor[scope]());
|
||||||
visit::visit_crate(*crate, [], visit::vtor(v));
|
visit::visit_crate(*crate, rec(args=[], rs=[]), visit::vtor(v));
|
||||||
}
|
}
|
||||||
|
|
||||||
fn visit_fn(&ast::_fn f, &vec[ast::ty_param] tp, &span sp, &ident name,
|
fn visit_fn(&ast::_fn f, &vec[ast::ty_param] tp, &span sp, &ident name,
|
||||||
&ast::def_id d_id, &ast::ann a, &scope sc, &vt[scope] v) {
|
&ast::def_id d_id, &ast::ann a, &scope sc, &vt[scope] v) {
|
||||||
visit::visit_fn_decl(f.decl, sc, v);
|
visit::visit_fn_decl(f.decl, sc, v);
|
||||||
vt(v).visit_block(f.body, [], v);
|
auto args = [];
|
||||||
|
for (ast::arg arg in f.decl.inputs) {
|
||||||
|
vec::push(args, tup(arg.id._1, arg.mode));
|
||||||
|
}
|
||||||
|
vt(v).visit_block(f.body, rec(args=args, rs=[]), v);
|
||||||
}
|
}
|
||||||
|
|
||||||
fn visit_expr(&@ctx cx, &@ast::expr ex, &scope sc, &vt[scope] v) {
|
fn visit_expr(&@ctx cx, &@ast::expr ex, &scope sc, &vt[scope] v) {
|
||||||
|
@ -179,12 +188,12 @@ fn check_alt(&ctx cx, &@ast::expr input, &vec[ast::arm] arms,
|
||||||
auto dnums = arm_defnums(a);
|
auto dnums = arm_defnums(a);
|
||||||
auto new_sc = sc;
|
auto new_sc = sc;
|
||||||
if (vec::len(dnums) > 0u) {
|
if (vec::len(dnums) > 0u) {
|
||||||
vec::push(new_sc, @rec(root_vars=roots,
|
new_sc = scope(sc, [@rec(root_vars=roots,
|
||||||
block_defnum=dnums.(0),
|
block_defnum=dnums.(0),
|
||||||
bindings=dnums,
|
bindings=dnums,
|
||||||
tys=forbidden_tp,
|
tys=forbidden_tp,
|
||||||
depends_on=deps(sc, roots),
|
depends_on=deps(sc, roots),
|
||||||
mutable ok=valid));
|
mutable ok=valid)]);
|
||||||
}
|
}
|
||||||
visit::visit_arm(a, new_sc, v);
|
visit::visit_arm(a, new_sc, v);
|
||||||
}
|
}
|
||||||
|
@ -225,7 +234,7 @@ fn check_for_each(&ctx cx, &@ast::decl decl, &@ast::expr call,
|
||||||
tys=data.unsafe_ts,
|
tys=data.unsafe_ts,
|
||||||
depends_on=deps(sc, data.root_vars),
|
depends_on=deps(sc, data.root_vars),
|
||||||
mutable ok=valid);
|
mutable ok=valid);
|
||||||
visit::visit_block(block, sc + [new_sc], v);
|
visit::visit_block(block, scope(sc, [new_sc]), v);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -261,7 +270,7 @@ fn check_for(&ctx cx, &@ast::decl decl, &@ast::expr seq,
|
||||||
tys=unsafe,
|
tys=unsafe,
|
||||||
depends_on=deps(sc, root_def),
|
depends_on=deps(sc, root_def),
|
||||||
mutable ok=valid);
|
mutable ok=valid);
|
||||||
visit::visit_block(block, sc + [new_sc], v);
|
visit::visit_block(block, scope(sc, [new_sc]), v);
|
||||||
}
|
}
|
||||||
|
|
||||||
fn check_var(&ctx cx, &@ast::expr ex, &ast::path p, ast::ann ann, bool assign,
|
fn check_var(&ctx cx, &@ast::expr ex, &ast::path p, ast::ann ann, bool assign,
|
||||||
|
@ -270,7 +279,7 @@ fn check_var(&ctx cx, &@ast::expr ex, &ast::path p, ast::ann ann, bool assign,
|
||||||
if (!def_is_local(def)) { ret; }
|
if (!def_is_local(def)) { ret; }
|
||||||
auto my_defnum = ast::def_id_of_def(def)._1;
|
auto my_defnum = ast::def_id_of_def(def)._1;
|
||||||
auto var_t = ty::expr_ty(*cx.tcx, ex);
|
auto var_t = ty::expr_ty(*cx.tcx, ex);
|
||||||
for (restrict r in sc) {
|
for (restrict r in sc.rs) {
|
||||||
// excludes variables introduced since the alias was made
|
// excludes variables introduced since the alias was made
|
||||||
if (my_defnum < r.block_defnum) {
|
if (my_defnum < r.block_defnum) {
|
||||||
for (ty::t t in r.tys) {
|
for (ty::t t in r.tys) {
|
||||||
|
@ -287,14 +296,29 @@ fn check_var(&ctx cx, &@ast::expr ex, &ast::path p, ast::ann ann, bool assign,
|
||||||
fn check_assign(&@ctx cx, &@ast::expr dest, &@ast::expr src,
|
fn check_assign(&@ctx cx, &@ast::expr dest, &@ast::expr src,
|
||||||
&scope sc, &vt[scope] v) {
|
&scope sc, &vt[scope] v) {
|
||||||
visit_expr(cx, src, sc, v);
|
visit_expr(cx, src, sc, v);
|
||||||
|
|
||||||
alt (dest.node) {
|
alt (dest.node) {
|
||||||
case (ast::expr_path(?p, ?ann)) {
|
case (ast::expr_path(?p, ?ann)) {
|
||||||
auto dnum = ast::def_id_of_def(cx.dm.get(ann.id))._1;
|
auto dnum = ast::def_id_of_def(cx.dm.get(ann.id))._1;
|
||||||
|
|
||||||
|
for (tup(def_num, ast::mode) arg in sc.args) {
|
||||||
|
if (arg._0 == dnum && arg._1 == ast::alias(false)) {
|
||||||
|
cx.tcx.sess.span_err
|
||||||
|
(dest.span, "assigning to immutable alias");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
auto var_t = ty::expr_ty(*cx.tcx, dest);
|
auto var_t = ty::expr_ty(*cx.tcx, dest);
|
||||||
for (restrict r in sc) {
|
for (restrict r in sc.rs) {
|
||||||
if (vec::member(dnum, r.root_vars)) {
|
if (vec::member(dnum, r.root_vars)) {
|
||||||
r.ok = overwritten(dest.span, p);
|
r.ok = overwritten(dest.span, p);
|
||||||
}
|
}
|
||||||
|
for (def_num bnd in r.bindings) {
|
||||||
|
if (dnum == bnd) {
|
||||||
|
cx.tcx.sess.span_err
|
||||||
|
(dest.span, "assigning to immutable alias");
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
check_var(*cx, dest, p, ann, true, sc);
|
check_var(*cx, dest, p, ann, true, sc);
|
||||||
}
|
}
|
||||||
|
@ -308,7 +332,7 @@ fn test_scope(&ctx cx, &scope sc, &restrict r, &ast::path p) {
|
||||||
auto prob = r.ok;
|
auto prob = r.ok;
|
||||||
for (uint dep in r.depends_on) {
|
for (uint dep in r.depends_on) {
|
||||||
if (prob != valid) { break; }
|
if (prob != valid) { break; }
|
||||||
prob = sc.(dep).ok;
|
prob = sc.rs.(dep).ok;
|
||||||
}
|
}
|
||||||
if (prob != valid) {
|
if (prob != valid) {
|
||||||
auto msg = alt (prob) {
|
auto msg = alt (prob) {
|
||||||
|
@ -328,7 +352,7 @@ fn test_scope(&ctx cx, &scope sc, &restrict r, &ast::path p) {
|
||||||
fn deps(&scope sc, vec[def_num] roots) -> vec[uint] {
|
fn deps(&scope sc, vec[def_num] roots) -> vec[uint] {
|
||||||
auto i = 0u;
|
auto i = 0u;
|
||||||
auto result = [];
|
auto result = [];
|
||||||
for (restrict r in sc) {
|
for (restrict r in sc.rs) {
|
||||||
for (def_num dn in roots) {
|
for (def_num dn in roots) {
|
||||||
if (vec::member(dn, r.bindings)) {
|
if (vec::member(dn, r.bindings)) {
|
||||||
vec::push(result, i);
|
vec::push(result, i);
|
||||||
|
|
|
@ -250,7 +250,13 @@ mod Encode {
|
||||||
&ast::controlflow cf, &vec[@ast::constr] constrs) {
|
&ast::controlflow cf, &vec[@ast::constr] constrs) {
|
||||||
w.write_char('[');
|
w.write_char('[');
|
||||||
for (ty::arg arg in args) {
|
for (ty::arg arg in args) {
|
||||||
if (arg.mode == ty::mo_alias) { w.write_char('&'); }
|
alt (arg.mode) {
|
||||||
|
case (ty::mo_alias(?mut)) {
|
||||||
|
w.write_char('&');
|
||||||
|
if (mut) { w.write_char('m'); }
|
||||||
|
}
|
||||||
|
case (ty::mo_val) {}
|
||||||
|
}
|
||||||
enc_ty(w, cx, arg.ty);
|
enc_ty(w, cx, arg.ty);
|
||||||
}
|
}
|
||||||
w.write_char(']');
|
w.write_char(']');
|
||||||
|
|
|
@ -691,12 +691,12 @@ fn type_of_explicit_args(&@crate_ctxt cx, &span sp,
|
||||||
let vec[TypeRef] atys = [];
|
let vec[TypeRef] atys = [];
|
||||||
for (ty::arg arg in inputs) {
|
for (ty::arg arg in inputs) {
|
||||||
if (ty::type_has_dynamic_size(cx.tcx, arg.ty)) {
|
if (ty::type_has_dynamic_size(cx.tcx, arg.ty)) {
|
||||||
assert (arg.mode == ty::mo_alias);
|
assert (arg.mode != ty::mo_val);
|
||||||
atys += [T_typaram_ptr(cx.tn)];
|
atys += [T_typaram_ptr(cx.tn)];
|
||||||
} else {
|
} else {
|
||||||
let TypeRef t;
|
let TypeRef t;
|
||||||
alt (arg.mode) {
|
alt (arg.mode) {
|
||||||
case (ty::mo_alias) {
|
case (ty::mo_alias(_)) {
|
||||||
t = T_ptr(type_of_inner(cx, sp, arg.ty));
|
t = T_ptr(type_of_inner(cx, sp, arg.ty));
|
||||||
}
|
}
|
||||||
case (_) {
|
case (_) {
|
||||||
|
@ -762,7 +762,7 @@ fn type_of_fn_full(&@crate_ctxt cx,
|
||||||
atys +=
|
atys +=
|
||||||
[T_fn_pair(cx.tn,
|
[T_fn_pair(cx.tn,
|
||||||
type_of_fn_full(cx, sp, ast::proto_fn, none[TypeRef],
|
type_of_fn_full(cx, sp, ast::proto_fn, none[TypeRef],
|
||||||
[rec(mode=ty::mo_alias,
|
[rec(mode=ty::mo_alias(false),
|
||||||
ty=output)],
|
ty=output)],
|
||||||
ty::mk_nil(cx.tcx), 0u))];
|
ty::mk_nil(cx.tcx), 0u))];
|
||||||
}
|
}
|
||||||
|
@ -923,7 +923,7 @@ fn type_of_inner(&@crate_ctxt cx, &span sp, &ty::t t) -> TypeRef {
|
||||||
fn type_of_arg(@local_ctxt cx, &span sp, &ty::arg arg) -> TypeRef {
|
fn type_of_arg(@local_ctxt cx, &span sp, &ty::arg arg) -> TypeRef {
|
||||||
alt (ty::struct(cx.ccx.tcx, arg.ty)) {
|
alt (ty::struct(cx.ccx.tcx, arg.ty)) {
|
||||||
case (ty::ty_param(_)) {
|
case (ty::ty_param(_)) {
|
||||||
if (arg.mode == ty::mo_alias) {
|
if (arg.mode != ty::mo_val) {
|
||||||
ret T_typaram_ptr(cx.ccx.tn);
|
ret T_typaram_ptr(cx.ccx.tn);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -933,7 +933,7 @@ fn type_of_arg(@local_ctxt cx, &span sp, &ty::arg arg) -> TypeRef {
|
||||||
}
|
}
|
||||||
|
|
||||||
auto typ;
|
auto typ;
|
||||||
if (arg.mode == ty::mo_alias) {
|
if (arg.mode != ty::mo_val) {
|
||||||
typ = T_ptr(type_of_inner(cx.ccx, sp, arg.ty));
|
typ = T_ptr(type_of_inner(cx.ccx, sp, arg.ty));
|
||||||
} else {
|
} else {
|
||||||
typ = type_of_inner(cx.ccx, sp, arg.ty);
|
typ = type_of_inner(cx.ccx, sp, arg.ty);
|
||||||
|
@ -4063,7 +4063,7 @@ fn trans_for_each(&@block_ctxt cx,
|
||||||
auto iter_body_llty =
|
auto iter_body_llty =
|
||||||
type_of_fn_full(lcx.ccx, cx.sp, ast::proto_fn,
|
type_of_fn_full(lcx.ccx, cx.sp, ast::proto_fn,
|
||||||
none[TypeRef],
|
none[TypeRef],
|
||||||
[rec(mode=ty::mo_alias, ty=decl_ty)],
|
[rec(mode=ty::mo_alias(false), ty=decl_ty)],
|
||||||
ty::mk_nil(lcx.ccx.tcx), 0u);
|
ty::mk_nil(lcx.ccx.tcx), 0u);
|
||||||
|
|
||||||
let ValueRef lliterbody = decl_internal_fastcall_fn(lcx.ccx.llmod,
|
let ValueRef lliterbody = decl_internal_fastcall_fn(lcx.ccx.llmod,
|
||||||
|
@ -4840,7 +4840,7 @@ fn trans_bind_thunk(&@local_ctxt cx,
|
||||||
}
|
}
|
||||||
} else if (ty::type_contains_params(cx.ccx.tcx,
|
} else if (ty::type_contains_params(cx.ccx.tcx,
|
||||||
out_arg.ty)) {
|
out_arg.ty)) {
|
||||||
assert (out_arg.mode == ty::mo_alias);
|
assert (out_arg.mode != ty::mo_val);
|
||||||
val = bcx.build.PointerCast(val, llout_arg_ty);
|
val = bcx.build.PointerCast(val, llout_arg_ty);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -4853,7 +4853,7 @@ fn trans_bind_thunk(&@local_ctxt cx,
|
||||||
let ValueRef passed_arg = llvm::LLVMGetParam(llthunk, a);
|
let ValueRef passed_arg = llvm::LLVMGetParam(llthunk, a);
|
||||||
|
|
||||||
if (ty::type_contains_params(cx.ccx.tcx, out_arg.ty)) {
|
if (ty::type_contains_params(cx.ccx.tcx, out_arg.ty)) {
|
||||||
assert (out_arg.mode == ty::mo_alias);
|
assert (out_arg.mode != ty::mo_val);
|
||||||
passed_arg = bcx.build.PointerCast(passed_arg,
|
passed_arg = bcx.build.PointerCast(passed_arg,
|
||||||
llout_arg_ty);
|
llout_arg_ty);
|
||||||
}
|
}
|
||||||
|
@ -5098,7 +5098,7 @@ fn trans_arg_expr(&@block_ctxt cx,
|
||||||
auto re = trans_expr(bcx, e);
|
auto re = trans_expr(bcx, e);
|
||||||
val = re.val;
|
val = re.val;
|
||||||
bcx = re.bcx;
|
bcx = re.bcx;
|
||||||
} else if (arg.mode == ty::mo_alias) {
|
} else if (arg.mode != ty::mo_val) {
|
||||||
let lval_result lv;
|
let lval_result lv;
|
||||||
if (ty::is_lval(e)) {
|
if (ty::is_lval(e)) {
|
||||||
lv = trans_lval(bcx, e);
|
lv = trans_lval(bcx, e);
|
||||||
|
@ -5125,7 +5125,7 @@ fn trans_arg_expr(&@block_ctxt cx,
|
||||||
bcx = re.bcx;
|
bcx = re.bcx;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (arg.mode != ty::mo_alias) {
|
if (arg.mode == ty::mo_val) {
|
||||||
bcx = take_ty(bcx, val, e_ty).bcx;
|
bcx = take_ty(bcx, val, e_ty).bcx;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -5930,7 +5930,7 @@ fn trans_put(&@block_ctxt cx, &option::t[@ast::expr] e) -> result {
|
||||||
case (none) { }
|
case (none) { }
|
||||||
case (some(?x)) {
|
case (some(?x)) {
|
||||||
auto e_ty = ty::expr_ty(cx.fcx.lcx.ccx.tcx, x);
|
auto e_ty = ty::expr_ty(cx.fcx.lcx.ccx.tcx, x);
|
||||||
auto arg = rec(mode=ty::mo_alias, ty=e_ty);
|
auto arg = rec(mode=ty::mo_alias(false), ty=e_ty);
|
||||||
auto arg_tys = type_of_explicit_args(cx.fcx.lcx.ccx,
|
auto arg_tys = type_of_explicit_args(cx.fcx.lcx.ccx,
|
||||||
x.span, [arg]);
|
x.span, [arg]);
|
||||||
auto r = trans_arg_expr(bcx, arg, arg_tys.(0), x);
|
auto r = trans_arg_expr(bcx, arg, arg_tys.(0), x);
|
||||||
|
@ -6194,7 +6194,7 @@ fn mk_spawn_wrapper(&@block_ctxt cx,
|
||||||
|
|
||||||
let TypeRef wrapper_fn_type =
|
let TypeRef wrapper_fn_type =
|
||||||
type_of_fn(cx.fcx.lcx.ccx, cx.sp, ast::proto_fn,
|
type_of_fn(cx.fcx.lcx.ccx, cx.sp, ast::proto_fn,
|
||||||
[rec(mode = ty::mo_alias, ty = args_ty)],
|
[rec(mode = ty::mo_alias(false), ty = args_ty)],
|
||||||
ty::idx_nil,
|
ty::idx_nil,
|
||||||
0u);
|
0u);
|
||||||
|
|
||||||
|
@ -6401,7 +6401,7 @@ fn trans_anon_obj(@block_ctxt cx, &span sp,
|
||||||
case (some(?fields)) {
|
case (some(?fields)) {
|
||||||
addtl_fields = fields;
|
addtl_fields = fields;
|
||||||
for (ast::obj_field f in fields) {
|
for (ast::obj_field f in fields) {
|
||||||
addtl_fn_args += [rec(mode=ast::alias, ty=f.ty,
|
addtl_fn_args += [rec(mode=ast::alias(false), ty=f.ty,
|
||||||
ident=f.ident, id=f.id)];
|
ident=f.ident, id=f.id)];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -7045,7 +7045,7 @@ fn copy_args_to_allocas(@fn_ctxt fcx,
|
||||||
|
|
||||||
let uint arg_n = 0u;
|
let uint arg_n = 0u;
|
||||||
for (ast::arg aarg in args) {
|
for (ast::arg aarg in args) {
|
||||||
if (aarg.mode != ast::alias) {
|
if (aarg.mode == ast::val) {
|
||||||
auto arg_t = type_of_arg(bcx.fcx.lcx, fcx.sp, arg_tys.(arg_n));
|
auto arg_t = type_of_arg(bcx.fcx.lcx, fcx.sp, arg_tys.(arg_n));
|
||||||
auto a = alloca(bcx, arg_t);
|
auto a = alloca(bcx, arg_t);
|
||||||
auto argval = bcx.fcx.llargs.get(aarg.id);
|
auto argval = bcx.fcx.llargs.get(aarg.id);
|
||||||
|
@ -7063,7 +7063,7 @@ fn add_cleanups_for_args(&@block_ctxt bcx,
|
||||||
vec[ty::arg] arg_tys) {
|
vec[ty::arg] arg_tys) {
|
||||||
let uint arg_n = 0u;
|
let uint arg_n = 0u;
|
||||||
for (ast::arg aarg in args) {
|
for (ast::arg aarg in args) {
|
||||||
if (aarg.mode != ast::alias) {
|
if (aarg.mode == ast::val) {
|
||||||
auto argval = bcx.fcx.llargs.get(aarg.id);
|
auto argval = bcx.fcx.llargs.get(aarg.id);
|
||||||
find_scope_cx(bcx).cleanups +=
|
find_scope_cx(bcx).cleanups +=
|
||||||
[clean(bind drop_slot(_, argval, arg_tys.(arg_n).ty))];
|
[clean(bind drop_slot(_, argval, arg_tys.(arg_n).ty))];
|
||||||
|
@ -7329,7 +7329,8 @@ fn trans_obj(@local_ctxt cx, &span sp, &ast::_obj ob, ast::def_id oid,
|
||||||
// we're creating.
|
// we're creating.
|
||||||
let vec[ast::arg] fn_args = [];
|
let vec[ast::arg] fn_args = [];
|
||||||
for (ast::obj_field f in ob.fields) {
|
for (ast::obj_field f in ob.fields) {
|
||||||
fn_args += [rec(mode=ast::alias, ty=f.ty, ident=f.ident, id=f.id)];
|
fn_args += [rec(mode=ast::alias(false),
|
||||||
|
ty=f.ty, ident=f.ident, id=f.id)];
|
||||||
}
|
}
|
||||||
auto fcx = new_fn_ctxt(cx, sp, llctor_decl);
|
auto fcx = new_fn_ctxt(cx, sp, llctor_decl);
|
||||||
|
|
||||||
|
@ -7522,7 +7523,7 @@ fn trans_tag_variant(@local_ctxt cx, ast::def_id tag_id,
|
||||||
let vec[ast::arg] fn_args = [];
|
let vec[ast::arg] fn_args = [];
|
||||||
auto i = 0u;
|
auto i = 0u;
|
||||||
for (ast::variant_arg varg in variant.node.args) {
|
for (ast::variant_arg varg in variant.node.args) {
|
||||||
fn_args += [rec(mode=ast::alias,
|
fn_args += [rec(mode=ast::alias(false),
|
||||||
ty=varg.ty,
|
ty=varg.ty,
|
||||||
ident="arg" + uint::to_str(i, 10u),
|
ident="arg" + uint::to_str(i, 10u),
|
||||||
id=varg.id)];
|
id=varg.id)];
|
||||||
|
|
|
@ -41,7 +41,7 @@ import util::data::interner;
|
||||||
|
|
||||||
tag mode {
|
tag mode {
|
||||||
mo_val;
|
mo_val;
|
||||||
mo_alias;
|
mo_alias(bool);
|
||||||
}
|
}
|
||||||
|
|
||||||
type arg = rec(mode mode, t ty);
|
type arg = rec(mode mode, t ty);
|
||||||
|
|
|
@ -179,7 +179,7 @@ fn ast_mode_to_mode(ast::mode mode) -> ty::mode {
|
||||||
auto ty_mode;
|
auto ty_mode;
|
||||||
alt (mode) {
|
alt (mode) {
|
||||||
case (ast::val) { ty_mode = mo_val; }
|
case (ast::val) { ty_mode = mo_val; }
|
||||||
case (ast::alias) { ty_mode = mo_alias; }
|
case (ast::alias(?mut)) { ty_mode = mo_alias(mut); }
|
||||||
}
|
}
|
||||||
ret ty_mode;
|
ret ty_mode;
|
||||||
}
|
}
|
||||||
|
@ -548,7 +548,7 @@ mod collect {
|
||||||
for (ast::obj_field f in obj_info.fields) {
|
for (ast::obj_field f in obj_info.fields) {
|
||||||
auto g = bind getter(cx, _);
|
auto g = bind getter(cx, _);
|
||||||
auto t_field = ast_ty_to_ty(cx.tcx, g, f.ty);
|
auto t_field = ast_ty_to_ty(cx.tcx, g, f.ty);
|
||||||
vec::push[arg](t_inputs, rec(mode=ty::mo_alias, ty=t_field));
|
vec::push(t_inputs, rec(mode=ty::mo_alias(false), ty=t_field));
|
||||||
}
|
}
|
||||||
|
|
||||||
let vec[@ast::constr] constrs = [];
|
let vec[@ast::constr] constrs = [];
|
||||||
|
@ -681,7 +681,7 @@ mod collect {
|
||||||
let vec[arg] args = [];
|
let vec[arg] args = [];
|
||||||
for (ast::variant_arg va in variant.node.args) {
|
for (ast::variant_arg va in variant.node.args) {
|
||||||
auto arg_ty = ast_ty_to_ty(cx.tcx, f, va.ty);
|
auto arg_ty = ast_ty_to_ty(cx.tcx, f, va.ty);
|
||||||
args += [rec(mode=ty::mo_alias, ty=arg_ty)];
|
args += [rec(mode=ty::mo_alias(false), ty=arg_ty)];
|
||||||
}
|
}
|
||||||
auto tag_t = ty::mk_tag(cx.tcx, tag_id, ty_param_tys);
|
auto tag_t = ty::mk_tag(cx.tcx, tag_id, ty_param_tys);
|
||||||
// FIXME: this will be different for constrained types
|
// FIXME: this will be different for constrained types
|
||||||
|
|
|
@ -13,11 +13,11 @@ fn ty_to_str(&ctxt cx, &t typ) -> str {
|
||||||
|
|
||||||
fn fn_input_to_str(&ctxt cx,
|
fn fn_input_to_str(&ctxt cx,
|
||||||
&rec(middle::ty::mode mode, t ty) input) -> str {
|
&rec(middle::ty::mode mode, t ty) input) -> str {
|
||||||
auto s;
|
auto s = alt (input.mode) {
|
||||||
alt (input.mode) {
|
case (mo_val) { "" }
|
||||||
case (mo_val) { s = ""; }
|
case (mo_alias(false)) { "&" }
|
||||||
case (mo_alias) { s = "&"; }
|
case (mo_alias(true)) { "&mutable " }
|
||||||
}
|
};
|
||||||
|
|
||||||
ret s + ty_to_str(cx, input.ty);
|
ret s + ty_to_str(cx, input.ty);
|
||||||
}
|
}
|
||||||
|
|
|
@ -960,7 +960,7 @@ fn print_fn(&ps s, ast::fn_decl decl, ast::proto proto, str name,
|
||||||
popen(s);
|
popen(s);
|
||||||
fn print_arg(&ps s, &ast::arg x) {
|
fn print_arg(&ps s, &ast::arg x) {
|
||||||
ibox(s, indent_unit);
|
ibox(s, indent_unit);
|
||||||
if (x.mode == ast::alias) {word(s.s, "&");}
|
print_alias(s, x.mode);
|
||||||
print_type(s, *x.ty);
|
print_type(s, *x.ty);
|
||||||
space(s.s);
|
space(s.s);
|
||||||
word(s.s, x.ident);
|
word(s.s, x.ident);
|
||||||
|
@ -977,6 +977,14 @@ fn print_fn(&ps s, ast::fn_decl decl, ast::proto proto, str name,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn print_alias(&ps s, ast::mode m) {
|
||||||
|
alt (m) {
|
||||||
|
case (ast::alias(true)) { word_space(s, "&mutable"); }
|
||||||
|
case (ast::alias(false)) { word(s.s, "&"); }
|
||||||
|
case (ast::val) {}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
fn print_type_params(&ps s, &vec[ast::ty_param] params) {
|
fn print_type_params(&ps s, &vec[ast::ty_param] params) {
|
||||||
if (vec::len[ast::ty_param](params) > 0u) {
|
if (vec::len[ast::ty_param](params) > 0u) {
|
||||||
word(s.s, "[");
|
word(s.s, "[");
|
||||||
|
@ -1095,7 +1103,7 @@ fn print_ty_fn(&ps s, &ast::proto proto, &option::t[str] id,
|
||||||
zerobreak(s.s);
|
zerobreak(s.s);
|
||||||
popen(s);
|
popen(s);
|
||||||
fn print_arg(&ps s, &ast::ty_arg input) {
|
fn print_arg(&ps s, &ast::ty_arg input) {
|
||||||
if (input.node.mode == ast::alias) {word(s.s, "&");}
|
print_alias(s, input.node.mode);
|
||||||
print_type(s, *input.node.ty);
|
print_type(s, *input.node.ty);
|
||||||
}
|
}
|
||||||
auto f = print_arg;
|
auto f = print_arg;
|
||||||
|
|
10
src/test/compile-fail/assign-alias.rs
Normal file
10
src/test/compile-fail/assign-alias.rs
Normal file
|
@ -0,0 +1,10 @@
|
||||||
|
// xfail-stage1
|
||||||
|
// error-pattern:assigning to immutable alias
|
||||||
|
|
||||||
|
fn f(&int i) {
|
||||||
|
i += 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
fn main() {
|
||||||
|
f(1);
|
||||||
|
}
|
Loading…
Reference in a new issue