diff --git a/src/etc/vim/syntax/rust.vim b/src/etc/vim/syntax/rust.vim index b9fae0697088..172de551ad0a 100644 --- a/src/etc/vim/syntax/rust.vim +++ b/src/etc/vim/syntax/rust.vim @@ -15,7 +15,7 @@ syn match rustAssert "assert\(\w\)*" syn keyword rustKeyword alt again as break syn keyword rustKeyword check claim const copy do drop else export extern fail syn keyword rustKeyword for if impl import in let log -syn keyword rustKeyword loop mod mut new of owned pure +syn keyword rustKeyword loop mod move mut new of owned pure syn keyword rustKeyword ret self to unchecked syn match rustKeyword "unsafe" " Allows also matching unsafe::foo() syn keyword rustKeyword use while with diff --git a/src/libcore/future.rs b/src/libcore/future.rs index 7dfafd499a4b..43b0a4047b61 100644 --- a/src/libcore/future.rs +++ b/src/libcore/future.rs @@ -60,7 +60,7 @@ fn from_value(+val: A) -> future { }) } -macro_rules! move{ +macro_rules! move_it { {$x:expr} => { unsafe { let y <- *ptr::addr_of($x); y } } } @@ -78,7 +78,7 @@ fn from_port(-port: future_pipe::client::waiting) -> future { port_ <-> *port; let port = option::unwrap(port_); alt recv(port) { - future_pipe::completed(data) { move!{data} } + future_pipe::completed(data) { move_it!{data} } } } } diff --git a/src/libcore/pipes.rs b/src/libcore/pipes.rs index 873ffd05aa57..3d115463844c 100644 --- a/src/libcore/pipes.rs +++ b/src/libcore/pipes.rs @@ -22,13 +22,13 @@ export stream, port, chan, shared_chan, port_set, channel; const SPIN_COUNT: uint = 0; -macro_rules! move { +macro_rules! move_it { { $x:expr } => { unsafe { let y <- *ptr::addr_of($x); y } } } // This is to help make sure we only move out of enums in safe // places. Once there is unary move, it can be removed. -fn move(-x: T) -> T { x } +fn move_it(-x: T) -> T { x } enum state { empty, @@ -228,7 +228,7 @@ class buffer_resource { } drop unsafe { - let b = move!{self.buffer}; + let b = move_it!{self.buffer}; //let p = ptr::addr_of(*b); //error!{"drop %?", p}; let old_count = atomic_sub_rel(b.header.ref_count, 1); @@ -725,10 +725,10 @@ impl port of recv for port { fn try_recv() -> option { let mut endp = none; endp <-> self.endp; - alt move(pipes::try_recv(unwrap(endp))) { + alt move_it(pipes::try_recv(unwrap(endp))) { some(streamp::data(x, endp)) { - self.endp = some(move!{endp}); - some(move!{x}) + self.endp = some(move_it!{endp}); + some(move_it!{x}) } none { none } } @@ -770,9 +770,9 @@ class port_set : recv { let i = wait_many(self.ports.map(|p| p.header())); // dereferencing an unsafe pointer nonsense to appease the // borrowchecker. - alt move(unsafe {(*ptr::addr_of(self.ports[i])).try_recv()}) { + alt move_it(unsafe {(*ptr::addr_of(self.ports[i])).try_recv()}) { some(m) { - result = some(move!{m}); + result = some(move_it!{m}); } none { // Remove this port. diff --git a/src/libsyntax/ast.rs b/src/libsyntax/ast.rs index 6e56e5ca65a4..8c2b6dc3490c 100644 --- a/src/libsyntax/ast.rs +++ b/src/libsyntax/ast.rs @@ -322,6 +322,7 @@ enum expr_ { expr_copy(@expr), expr_move(@expr, @expr), + expr_unary_move(@expr), expr_assign(@expr, @expr), expr_swap(@expr, @expr), expr_assign_op(binop, @expr, @expr), diff --git a/src/libsyntax/fold.rs b/src/libsyntax/fold.rs index dd051564cf4a..5e533f3f4942 100644 --- a/src/libsyntax/fold.rs +++ b/src/libsyntax/fold.rs @@ -454,6 +454,7 @@ fn noop_fold_expr(e: expr_, fld: ast_fold) -> expr_ { 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) { expr_assign(fld.fold_expr(el), fld.fold_expr(er)) } diff --git a/src/libsyntax/parse/parser.rs b/src/libsyntax/parse/parser.rs index 28ad7173be87..aaafbf0ef243 100644 --- a/src/libsyntax/parse/parser.rs +++ b/src/libsyntax/parse/parser.rs @@ -31,12 +31,12 @@ import ast::{_mod, add, alt_check, alt_exhaustive, arg, arm, attribute, expr_index, expr_lit, expr_log, expr_loop, expr_loop_body, expr_mac, expr_move, expr_new, expr_path, expr_rec, expr_ret, expr_swap, expr_struct, expr_tup, expr_unary, - expr_vec, expr_vstore, expr_while, extern_fn, field, fn_decl, - foreign_item, foreign_item_fn, foreign_mod, ident, impure_fn, - infer, init_assign, init_move, initializer, instance_var, 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, + expr_unary_move, expr_vec, expr_vstore, expr_while, extern_fn, + field, fn_decl, foreign_item, foreign_item_fn, foreign_mod, + ident, impure_fn, infer, init_assign, init_move, initializer, + instance_var, 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, lit_int_unsuffixed, lit_nil, lit_str, lit_uint, local, m_const, m_imm, m_mutbl, mac_, mac_aq, mac_ellipsis, mac_invoc, mac_invoc_tt, mac_var, matcher, match_nonterminal, @@ -854,6 +854,10 @@ class parser { let e = self.parse_expr(); ex = expr_copy(e); hi = e.span.hi; + } else if self.eat_keyword(~"move") { + let e = self.parse_expr(); + ex = expr_unary_move(e); + hi = e.span.hi; } else if self.token == token::MOD_SEP || is_ident(self.token) && !self.is_keyword(~"true") && !self.is_keyword(~"false") { diff --git a/src/libsyntax/parse/token.rs b/src/libsyntax/parse/token.rs index e4386ab140ff..1d4e67c5d14d 100644 --- a/src/libsyntax/parse/token.rs +++ b/src/libsyntax/parse/token.rs @@ -327,7 +327,7 @@ fn restricted_keyword_table() -> hashmap<~str, ()> { ~"fail", ~"false", ~"fn", ~"for", ~"if", ~"iface", ~"impl", ~"import", ~"let", ~"log", ~"loop", - ~"match", ~"mod", ~"module", ~"mut", + ~"match", ~"mod", ~"module", ~"move", ~"mut", ~"new", ~"owned", ~"pure", diff --git a/src/libsyntax/print/pprust.rs b/src/libsyntax/print/pprust.rs index 3292831c32f2..41e795fd4368 100644 --- a/src/libsyntax/print/pprust.rs +++ b/src/libsyntax/print/pprust.rs @@ -1100,6 +1100,7 @@ fn print_expr(s: ps, &&expr: @ast::expr) { print_block(s, blk); } ast::expr_copy(e) { word_space(s, ~"copy"); print_expr(s, e); } + ast::expr_unary_move(e) { word_space(s, ~"move"); print_expr(s, e); } ast::expr_move(lhs, rhs) { print_expr(s, lhs); space(s.s); diff --git a/src/libsyntax/visit.rs b/src/libsyntax/visit.rs index a542ca574ace..050d7e581207 100644 --- a/src/libsyntax/visit.rs +++ b/src/libsyntax/visit.rs @@ -408,6 +408,7 @@ fn visit_expr(ex: @expr, e: E, v: vt) { expr_block(b) { v.visit_block(b, e, v); } 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) { diff --git a/src/rustc/middle/borrowck/categorization.rs b/src/rustc/middle/borrowck/categorization.rs index 6f5b5d139d30..36b35dbbdbcf 100644 --- a/src/rustc/middle/borrowck/categorization.rs +++ b/src/rustc/middle/borrowck/categorization.rs @@ -181,7 +181,8 @@ impl public_methods for borrowck_ctxt { ast::expr_new(*) | ast::expr_binary(*) | ast::expr_while(*) | ast::expr_block(*) | ast::expr_loop(*) | ast::expr_alt(*) | ast::expr_lit(*) | ast::expr_break | ast::expr_mac(*) | - ast::expr_again | ast::expr_rec(*) | ast::expr_struct(*) { + ast::expr_again | ast::expr_rec(*) | ast::expr_struct(*) | + ast::expr_unary_move(*) { ret self.cat_rvalue(expr, expr_ty); } } diff --git a/src/rustc/middle/liveness.rs b/src/rustc/middle/liveness.rs index e7d88b9b2b85..8a65a1b05678 100644 --- a/src/rustc/middle/liveness.rs +++ b/src/rustc/middle/liveness.rs @@ -470,8 +470,8 @@ fn visit_expr(expr: @expr, &&self: @ir_maps, vt: vt<@ir_maps>) { 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_assign(*) | expr_swap(*) | - expr_assign_op(*) | expr_mac(*) | expr_struct(*) { + expr_block(*) | expr_move(*) | expr_unary_move(*) | expr_assign(*) | + expr_swap(*) | expr_assign_op(*) | expr_mac(*) | expr_struct(*) => { visit::visit_expr(expr, self, vt); } } @@ -1104,6 +1104,7 @@ class liveness { expr_assert(e) | expr_addr_of(_, e) | expr_copy(e) | + expr_unary_move(e) | expr_loop_body(e) | expr_do_body(e) | expr_cast(e, _) | @@ -1430,6 +1431,12 @@ fn check_expr(expr: @expr, &&self: @liveness, vt: vt<@liveness>) { visit::visit_expr(expr, self, vt); } + expr_unary_move(r) { + self.check_move_from_expr(r, vt); + + visit::visit_expr(expr, self, vt); + } + expr_assign_op(_, l, _) { self.check_lvalue(l, vt); diff --git a/src/rustc/middle/trans/base.rs b/src/rustc/middle/trans/base.rs index 2e5d5051a79f..96e7c74f25dc 100644 --- a/src/rustc/middle/trans/base.rs +++ b/src/rustc/middle/trans/base.rs @@ -3682,7 +3682,7 @@ fn trans_expr(bcx: block, e: @ast::expr, dest: dest) -> block { ast::expr_do_body(blk) { ret trans_expr(bcx, blk, dest); } - ast::expr_copy(a) { + ast::expr_copy(a) | ast::expr_unary_move(a) { if !expr_is_lval(bcx, a) { ret trans_expr(bcx, a, dest); } diff --git a/src/rustc/middle/trans/type_use.rs b/src/rustc/middle/trans/type_use.rs index 6bb19724afe4..8ab6fbfc6eba 100644 --- a/src/rustc/middle/trans/type_use.rs +++ b/src/rustc/middle/trans/type_use.rs @@ -158,7 +158,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_copy(_) | expr_move(_, _) | expr_unary_move(_) { node_type_needs(cx, use_repr, e.id); } expr_cast(base, _) { diff --git a/src/rustc/middle/typeck/check.rs b/src/rustc/middle/typeck/check.rs index 1f589a1b9608..db9084cbad16 100644 --- a/src/rustc/middle/typeck/check.rs +++ b/src/rustc/middle/typeck/check.rs @@ -1416,7 +1416,7 @@ fn check_expr_with_unifier(fcx: @fn_ctxt, bot = check_expr_with(fcx, e, ty::mk_bool(tcx)); fcx.write_nil(id); } - ast::expr_copy(a) { + ast::expr_copy(a) | ast::expr_unary_move(a) { bot = check_expr(fcx, a, expected); fcx.write_ty(id, fcx.expr_ty(a)); } diff --git a/src/test/compile-fail/unary-move.rs b/src/test/compile-fail/unary-move.rs new file mode 100644 index 000000000000..5178d5a1e9b0 --- /dev/null +++ b/src/test/compile-fail/unary-move.rs @@ -0,0 +1,8 @@ +// error-pattern: use of moved variable + +fn main() { + let x = 3; + let y = move x; + debug!("%d", x); +} +