Remove <- operator from the compiler

Yield an obsolete syntax error on things like "let foo <- bar;"
and "foo <- bar;" r=brson

Progress on #3466
This commit is contained in:
Tim Chevalier 2012-10-23 11:28:20 -07:00
parent 48c8d1fecd
commit 087cbb55d0
19 changed files with 53 additions and 132 deletions

View File

@ -640,40 +640,12 @@ enum stmt_ {
stmt_semi(@expr, node_id),
}
#[auto_serialize]
#[auto_deserialize]
enum init_op { init_assign, init_move, }
impl init_op : cmp::Eq {
pure fn eq(other: &init_op) -> bool {
match self {
init_assign => {
match (*other) {
init_assign => true,
_ => false
}
}
init_move => {
match (*other) {
init_move => true,
_ => false
}
}
}
}
pure fn ne(other: &init_op) -> bool { !self.eq(other) }
}
#[auto_serialize]
#[auto_deserialize]
type initializer = {op: init_op, expr: @expr};
// FIXME (pending discussion of #1697, #2178...): local should really be
// a refinement on pat.
#[auto_serialize]
#[auto_deserialize]
type local_ = {is_mutbl: bool, ty: @Ty, pat: @pat,
init: Option<initializer>, id: node_id};
init: Option<@expr>, id: node_id};
type local = spanned<local_>;
@ -749,7 +721,6 @@ enum expr_ {
expr_block(blk),
expr_copy(@expr),
expr_move(@expr, @expr),
expr_unary_move(@expr),
expr_assign(@expr, @expr),
expr_swap(@expr, @expr),

View File

@ -460,9 +460,6 @@ fn noop_fold_expr(e: expr_, fld: ast_fold) -> expr_ {
..**cap_item})})))
}
expr_block(blk) => expr_block(fld.fold_block(blk)),
expr_move(el, er) => {
expr_move(fld.fold_expr(el), fld.fold_expr(er))
}
expr_copy(e) => expr_copy(fld.fold_expr(e)),
expr_unary_move(e) => expr_unary_move(fld.fold_expr(e)),
expr_assign(el, er) => {
@ -610,14 +607,7 @@ fn noop_fold_local(l: local_, fld: ast_fold) -> local_ {
return {is_mutbl: l.is_mutbl,
ty: fld.fold_ty(l.ty),
pat: fld.fold_pat(l.pat),
init:
match l.init {
option::None::<initializer> => l.init,
option::Some::<initializer>(init) => {
option::Some::<initializer>({op: init.op,
expr: fld.fold_expr(init.expr)})
}
},
init: l.init.map(|e| fld.fold_expr(*e)),
id: fld.new_id(l.id)};
}

View File

@ -43,7 +43,6 @@ fn need_parens(expr: @ast::expr, outer_prec: uint) -> bool {
ast::expr_cast(_, _) => parse::prec::as_prec < outer_prec,
// This may be too conservative in some cases
ast::expr_assign(_, _) => true,
ast::expr_move(_, _) => true,
ast::expr_swap(_, _) => true,
ast::expr_assign_op(_, _, _) => true,
ast::expr_ret(_) => true,
@ -61,8 +60,7 @@ fn ends_in_lit_int(ex: @ast::expr) -> bool {
_ => false
},
ast::expr_binary(_, _, sub) | ast::expr_unary(_, sub) |
ast::expr_move(_, sub) | ast::expr_copy(sub) |
ast::expr_assign(_, sub) |
ast::expr_copy(sub) | ast::expr_assign(_, sub) |
ast::expr_assign_op(_, _, sub) | ast::expr_swap(_, sub) |
ast::expr_log(_, _, sub) | ast::expr_assert(sub) => {
ends_in_lit_int(sub)

View File

@ -25,6 +25,8 @@ pub enum ObsoleteSyntax {
ObsoleteModeInFnType,
ObsoleteByMutRefMode,
ObsoleteFixedLengthVec,
ObsoleteMoveInit,
ObsoleteBinaryMove
}
impl ObsoleteSyntax : cmp::Eq {
@ -104,6 +106,14 @@ impl Parser : ObsoleteReporter {
"fixed-length vector",
"Fixed-length types are now written `[T * N]`, and instances \
are type-inferred"
),
ObsoleteMoveInit => (
"initializer-by-move",
"Write `let foo = move bar` instead"
),
ObsoleteBinaryMove => (
"binary move",
"Write `foo = move bar` instead"
)
};

View File

@ -20,7 +20,8 @@ use obsolete::{
ObsoleteLowerCaseKindBounds, ObsoleteLet,
ObsoleteFieldTerminator, ObsoleteStructCtor,
ObsoleteWith, ObsoleteClassMethod, ObsoleteClassTraits,
ObsoleteModeInFnType, ObsoleteByMutRefMode
ObsoleteModeInFnType, ObsoleteByMutRefMode,
ObsoleteMoveInit, ObsoleteBinaryMove,
};
use ast::{_mod, add, arg, arm, attribute,
bind_by_ref, bind_by_implicit_ref, bind_by_value, bind_by_move,
@ -35,11 +36,11 @@ use ast::{_mod, add, arg, arm, attribute,
expr_call, expr_cast, expr_copy, expr_do_body, expr_fail,
expr_field, expr_fn, expr_fn_block, expr_if, expr_index,
expr_lit, expr_log, expr_loop, expr_loop_body, expr_mac,
expr_move, expr_path, expr_rec, expr_repeat, expr_ret, expr_swap,
expr_path, expr_rec, expr_repeat, expr_ret, expr_swap,
expr_struct, expr_tup, expr_unary, expr_unary_move, expr_vec,
expr_vstore, expr_while, extern_fn, field, fn_decl, foreign_item,
foreign_item_const, foreign_item_fn, foreign_mod, ident,
impure_fn, infer, inherited, init_assign, init_move, initializer,
impure_fn, infer, inherited,
item, item_, item_class, item_const, item_enum, item_fn,
item_foreign_mod, item_impl, item_mac, item_mod, item_trait,
item_ty, lit, lit_, lit_bool, lit_float, lit_int,
@ -1473,9 +1474,13 @@ impl Parser {
expr_assign_op(aop, lhs, rhs));
}
token::LARROW => {
self.bump();
let rhs = self.parse_expr();
return self.mk_expr(lo, rhs.span.hi, expr_move(lhs, rhs));
self.obsolete(copy self.span, ObsoleteBinaryMove);
// Bogus value (but it's an error)
self.bump(); // <-
self.bump(); // rhs
self.bump(); // ;
return self.mk_expr(lo, self.span.hi,
expr_break(None));
}
token::DARROW => {
self.bump();
@ -1745,23 +1750,18 @@ impl Parser {
return e;
}
fn parse_initializer() -> Option<initializer> {
fn parse_initializer() -> Option<@expr> {
match self.token {
token::EQ => {
self.bump();
return Some({op: init_assign, expr: self.parse_expr()});
return Some(self.parse_expr());
}
token::LARROW => {
self.bump();
return Some({op: init_move, expr: self.parse_expr()});
self.obsolete(copy self.span, ObsoleteMoveInit);
self.bump();
self.bump();
return None;
}
// Now that the the channel is the first argument to receive,
// combining it with an initializer doesn't really make sense.
// case (token::RECV) {
// self.bump();
// return Some(rec(op = init_recv,
// expr = self.parse_expr()));
// }
_ => {
return None;
}

View File

@ -1310,18 +1310,13 @@ fn print_expr(s: ps, &&expr: @ast::expr) {
print_block(s, blk);
}
ast::expr_copy(e) => { word_space(s, ~"copy"); print_expr(s, e); }
// shouldn't parenthesize unless it's needed
ast::expr_unary_move(e) => {
popen(s);
word_space(s, ~"move");
print_expr(s, e);
pclose(s);
}
ast::expr_move(lhs, rhs) => {
print_expr(s, lhs);
space(s.s);
word_space(s, ~"<-");
print_expr(s, rhs);
}
ast::expr_assign(lhs, rhs) => {
print_expr(s, lhs);
space(s.s);
@ -1416,8 +1411,7 @@ fn print_expr_parens_if_not_bot(s: ps, ex: @ast::expr) {
let parens = match ex.node {
ast::expr_fail(_) | ast::expr_ret(_) |
ast::expr_binary(_, _, _) | ast::expr_unary(_, _) |
ast::expr_move(_, _) | ast::expr_copy(_) |
ast::expr_assign(_, _) |
ast::expr_copy(_) | ast::expr_assign(_, _) |
ast::expr_assign_op(_, _, _) | ast::expr_swap(_, _) |
ast::expr_log(_, _, _) | ast::expr_assert(_) |
ast::expr_call(_, _, true) |
@ -1458,11 +1452,8 @@ fn print_decl(s: ps, decl: @ast::decl) {
match loc.node.init {
Some(init) => {
nbsp(s);
match init.op {
ast::init_assign => word_space(s, ~"="),
ast::init_move => word_space(s, ~"<-")
}
print_expr(s, init.expr);
word_space(s, ~"=");
print_expr(s, init);
}
_ => ()
}

View File

@ -116,7 +116,7 @@ fn visit_local<E>(loc: @local, e: E, v: vt<E>) {
v.visit_ty(loc.node.ty, e, v);
match loc.node.init {
None => (),
Some(i) => v.visit_expr(i.expr, e, v)
Some(ex) => v.visit_expr(ex, e, v)
}
}
@ -442,7 +442,6 @@ fn visit_expr<E>(ex: @expr, e: E, v: vt<E>) {
expr_assign(a, b) => { v.visit_expr(b, e, v); v.visit_expr(a, e, v); }
expr_copy(a) => v.visit_expr(a, e, v),
expr_unary_move(a) => v.visit_expr(a, e, v),
expr_move(a, b) => { v.visit_expr(b, e, v); v.visit_expr(a, e, v); }
expr_swap(a, b) => { v.visit_expr(a, e, v); v.visit_expr(b, e, v); }
expr_assign_op(_, a, b) => {
v.visit_expr(b, e, v);

View File

@ -583,12 +583,6 @@ fn check_loans_in_fn(fk: visit::fn_kind, decl: ast::fn_decl, body: ast::blk,
fn check_loans_in_local(local: @ast::local,
&&self: check_loan_ctxt,
vt: visit::vt<check_loan_ctxt>) {
match local.node.init {
Some({op: ast::init_move, expr: expr}) => {
self.check_move_out(expr);
}
Some({op: ast::init_assign, _}) | None => {}
}
visit::visit_local(local, self, vt);
}
@ -609,10 +603,6 @@ fn check_loans_in_expr(expr: @ast::expr,
self.check_assignment(at_swap, l);
self.check_assignment(at_swap, r);
}
ast::expr_move(dest, src) => {
self.check_assignment(at_straight_up, dest);
self.check_move_out(src);
}
ast::expr_unary_move(src) => {
self.check_move_out(src);
}

View File

@ -374,7 +374,7 @@ fn check_stmt(stmt: @stmt, cx: ctx, v: visit::vt<ctx>) {
stmt_decl(@{node: decl_local(locals), _}, _) => {
for locals.each |local| {
match local.node.init {
Some({op: init_assign, expr}) =>
Some(expr) =>
maybe_copy(cx, expr, Some(("initializer statement \
takes its right-hand side by copy", ""))),
_ => {}

View File

@ -552,7 +552,7 @@ fn visit_expr(expr: @expr, &&self: @IrMaps, vt: vt<@IrMaps>) {
expr_loop_body(*) | expr_do_body(*) | expr_cast(*) |
expr_unary(*) | expr_fail(*) |
expr_break(_) | expr_again(_) | expr_lit(_) | expr_ret(*) |
expr_block(*) | expr_move(*) | expr_unary_move(*) | expr_assign(*) |
expr_block(*) | expr_unary_move(*) | expr_assign(*) |
expr_swap(*) | expr_assign_op(*) | expr_mac(*) | expr_struct(*) |
expr_repeat(*) => {
visit::visit_expr(expr, self, vt);
@ -1004,8 +1004,7 @@ impl Liveness {
// initialization, which is mildly more complex than checking
// once at the func header but otherwise equivalent.
let opt_init = local.node.init.map(|i| i.expr );
let succ = self.propagate_through_opt_expr(opt_init, succ);
let succ = self.propagate_through_opt_expr(local.node.init, succ);
self.define_bindings_in_pat(local.node.pat, succ)
}
@ -1157,7 +1156,7 @@ impl Liveness {
}
}
expr_move(l, r) | expr_assign(l, r) => {
expr_assign(l, r) => {
// see comment on lvalues in
// propagate_through_lvalue_components()
let succ = self.write_lvalue(l, succ, ACC_WRITE);
@ -1436,14 +1435,9 @@ impl Liveness {
fn check_local(local: @local, &&self: @Liveness, vt: vt<@Liveness>) {
match local.node.init {
Some({op: op, expr: expr}) => {
Some(_) => {
// Initializer:
match op {
init_move => self.check_move_from_expr(expr, vt),
init_assign => ()
}
self.warn_about_unused_or_dead_vars_in_pat(local.node.pat);
if !local.node.is_mutbl {
self.check_for_reassignments_in_pat(local.node.pat);
@ -1511,13 +1505,6 @@ fn check_expr(expr: @expr, &&self: @Liveness, vt: vt<@Liveness>) {
visit::visit_expr(expr, self, vt);
}
expr_move(l, r) => {
self.check_lvalue(l, vt);
self.check_move_from_expr(r, vt);
visit::visit_expr(expr, self, vt);
}
expr_unary_move(r) => {
self.check_move_from_expr(r, vt);

View File

@ -482,7 +482,7 @@ impl &mem_categorization_ctxt {
}
ast::expr_addr_of(*) | ast::expr_call(*) |
ast::expr_swap(*) | ast::expr_move(*) | ast::expr_assign(*) |
ast::expr_swap(*) | ast::expr_assign(*) |
ast::expr_assign_op(*) | ast::expr_fn(*) | ast::expr_fn_block(*) |
ast::expr_assert(*) | ast::expr_ret(*) |
ast::expr_loop_body(*) | ast::expr_do_body(*) | ast::expr_unary(*) |

View File

@ -3982,7 +3982,7 @@ impl Resolver {
// Nothing to do.
}
Some(initializer) => {
self.resolve_expr(initializer.expr, visitor);
self.resolve_expr(initializer, visitor);
}
}

View File

@ -960,7 +960,7 @@ fn init_local(bcx: block, local: @ast::local) -> block {
// Handle let _ = e; just like e;
match local.node.init {
Some(init) => {
return expr::trans_into(bcx, init.expr, expr::Ignore);
return expr::trans_into(bcx, init, expr::Ignore);
}
None => { return bcx; }
}
@ -977,12 +977,7 @@ fn init_local(bcx: block, local: @ast::local) -> block {
let mut bcx = bcx;
match local.node.init {
Some(init) => {
if init.op == ast::init_assign || !bcx.expr_is_lval(init.expr) {
bcx = expr::trans_into(bcx, init.expr, expr::SaveIn(llptr));
} else { // This is a move from an lval, perform an actual move
let init_datumblock = expr::trans_to_datum(bcx, init.expr);
bcx = init_datumblock.move_to(datum::INIT, llptr);
}
bcx = expr::trans_into(bcx, init, expr::SaveIn(llptr));
}
_ => {
zero_mem(bcx, llptr, ty);

View File

@ -438,11 +438,6 @@ fn trans_rvalue_stmt_unadjusted(bcx: block, expr: @ast::expr) -> block {
let dst_datum = unpack_datum!(bcx, trans_lvalue(bcx, dst));
return src_datum.store_to_datum(bcx, DROP_EXISTING, dst_datum);
}
ast::expr_move(dst, src) => {
let src_datum = unpack_datum!(bcx, trans_to_datum(bcx, src));
let dst_datum = unpack_datum!(bcx, trans_lvalue(bcx, dst));
return src_datum.move_to_datum(bcx, DROP_EXISTING, dst_datum);
}
ast::expr_swap(dst, src) => {
let dst_datum = unpack_datum!(bcx, trans_lvalue(bcx, dst));
let src_datum = unpack_datum!(bcx, trans_lvalue(bcx, src));

View File

@ -180,8 +180,7 @@ fn mark_for_expr(cx: ctx, e: @expr) {
expr_rec(_, _) | expr_struct(*) | expr_tup(_) |
expr_unary(box(_), _) | expr_unary(uniq(_), _) |
expr_binary(add, _, _) |
expr_copy(_) | expr_move(_, _) | expr_unary_move(_) |
expr_repeat(*) => {
expr_copy(_) | expr_unary_move(_) | expr_repeat(*) => {
node_type_needs(cx, use_repr, e.id);
}
expr_cast(base, _) => {

View File

@ -3018,7 +3018,6 @@ fn expr_kind(tcx: ctxt,
ast::expr_while(*) |
ast::expr_loop(*) |
ast::expr_assign(*) |
ast::expr_move(*) |
ast::expr_swap(*) |
ast::expr_assign_op(*) => {
RvalueStmtExpr

View File

@ -755,7 +755,7 @@ impl @fn_ctxt {
fn with_region_lb<R>(lb: ast::node_id, f: fn() -> R) -> R {
let old_region_lb = self.region_lb;
self.region_lb = lb;
let v <- f();
let v = f();
self.region_lb = old_region_lb;
move v
}
@ -1776,9 +1776,6 @@ fn check_expr_with_unifier(fcx: @fn_ctxt,
bot = check_expr(fcx, a, expected);
fcx.write_ty(id, fcx.expr_ty(a));
}
ast::expr_move(lhs, rhs) => {
bot = check_assignment(fcx, expr.span, lhs, rhs, id);
}
ast::expr_assign(lhs, rhs) => {
bot = check_assignment(fcx, expr.span, lhs, rhs, id);
}
@ -2112,9 +2109,9 @@ fn require_integral(fcx: @fn_ctxt, sp: span, t: ty::t) {
}
fn check_decl_initializer(fcx: @fn_ctxt, nid: ast::node_id,
init: ast::initializer) -> bool {
let lty = ty::mk_var(fcx.ccx.tcx, lookup_local(fcx, init.expr.span, nid));
return check_expr_with(fcx, init.expr, lty);
init: @ast::expr) -> bool {
let lty = ty::mk_var(fcx.ccx.tcx, lookup_local(fcx, init.span, nid));
return check_expr_with(fcx, init, lty);
}
fn check_decl_local(fcx: @fn_ctxt, local: @ast::local) -> bool {
@ -2128,7 +2125,7 @@ fn check_decl_local(fcx: @fn_ctxt, local: @ast::local) -> bool {
match local.node.init {
Some(init) => {
bot = check_decl_initializer(fcx, local.node.id, init);
is_lvalue = ty::expr_is_lval(tcx, fcx.ccx.method_map, init.expr);
is_lvalue = ty::expr_is_lval(tcx, fcx.ccx.method_map, init);
}
_ => {
is_lvalue = true;

View File

@ -147,7 +147,7 @@ fn visit_local(l: @ast::local, &&rcx: @rcx, v: rvt) {
v.visit_ty(l.node.ty, rcx, v);
for l.node.init.each |i| {
v.visit_expr(i.expr, rcx, v);
v.visit_expr(*i, rcx, v);
}
}

View File

@ -8,7 +8,7 @@ fn indent<R>(op: fn() -> R) -> R {
// Use in conjunction with the log post-processor like `src/etc/indenter`
// to make debug output more readable.
debug!(">>");
let r <- op();
let r = op();
debug!("<< (Result = %?)", r);
move r
}
@ -75,7 +75,7 @@ fn block_query(b: ast::blk, p: fn@(@ast::expr) -> bool) -> bool {
fn local_rhs_span(l: @ast::local, def: span) -> span {
match l.node.init {
Some(i) => return i.expr.span,
Some(i) => return i.span,
_ => return def
}
}