rustc: Implement unary move. Closes #917.

This commit is contained in:
Patrick Walton
2012-07-31 17:31:24 -07:00
parent c4bb8f8aaf
commit c88933d714
15 changed files with 48 additions and 24 deletions

View File

@@ -15,7 +15,7 @@ syn match rustAssert "assert\(\w\)*"
syn keyword rustKeyword alt again as break syn keyword rustKeyword alt again as break
syn keyword rustKeyword check claim const copy do drop else export extern fail 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 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 keyword rustKeyword ret self to unchecked
syn match rustKeyword "unsafe" " Allows also matching unsafe::foo() syn match rustKeyword "unsafe" " Allows also matching unsafe::foo()
syn keyword rustKeyword use while with syn keyword rustKeyword use while with

View File

@@ -60,7 +60,7 @@ fn from_value<A>(+val: A) -> future<A> {
}) })
} }
macro_rules! move{ macro_rules! move_it {
{$x:expr} => { unsafe { let y <- *ptr::addr_of($x); y } } {$x:expr} => { unsafe { let y <- *ptr::addr_of($x); y } }
} }
@@ -78,7 +78,7 @@ fn from_port<A:send>(-port: future_pipe::client::waiting<A>) -> future<A> {
port_ <-> *port; port_ <-> *port;
let port = option::unwrap(port_); let port = option::unwrap(port_);
alt recv(port) { alt recv(port) {
future_pipe::completed(data) { move!{data} } future_pipe::completed(data) { move_it!{data} }
} }
} }
} }

View File

@@ -22,13 +22,13 @@ export stream, port, chan, shared_chan, port_set, channel;
const SPIN_COUNT: uint = 0; const SPIN_COUNT: uint = 0;
macro_rules! move { macro_rules! move_it {
{ $x:expr } => { unsafe { let y <- *ptr::addr_of($x); y } } { $x:expr } => { unsafe { let y <- *ptr::addr_of($x); y } }
} }
// This is to help make sure we only move out of enums in safe // This is to help make sure we only move out of enums in safe
// places. Once there is unary move, it can be removed. // places. Once there is unary move, it can be removed.
fn move<T>(-x: T) -> T { x } fn move_it<T>(-x: T) -> T { x }
enum state { enum state {
empty, empty,
@@ -228,7 +228,7 @@ class buffer_resource<T: send> {
} }
drop unsafe { drop unsafe {
let b = move!{self.buffer}; let b = move_it!{self.buffer};
//let p = ptr::addr_of(*b); //let p = ptr::addr_of(*b);
//error!{"drop %?", p}; //error!{"drop %?", p};
let old_count = atomic_sub_rel(b.header.ref_count, 1); let old_count = atomic_sub_rel(b.header.ref_count, 1);
@@ -725,10 +725,10 @@ impl port<T: send> of recv<T> for port<T> {
fn try_recv() -> option<T> { fn try_recv() -> option<T> {
let mut endp = none; let mut endp = none;
endp <-> self.endp; endp <-> self.endp;
alt move(pipes::try_recv(unwrap(endp))) { alt move_it(pipes::try_recv(unwrap(endp))) {
some(streamp::data(x, endp)) { some(streamp::data(x, endp)) {
self.endp = some(move!{endp}); self.endp = some(move_it!{endp});
some(move!{x}) some(move_it!{x})
} }
none { none } none { none }
} }
@@ -770,9 +770,9 @@ class port_set<T: send> : recv<T> {
let i = wait_many(self.ports.map(|p| p.header())); let i = wait_many(self.ports.map(|p| p.header()));
// dereferencing an unsafe pointer nonsense to appease the // dereferencing an unsafe pointer nonsense to appease the
// borrowchecker. // 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) { some(m) {
result = some(move!{m}); result = some(move_it!{m});
} }
none { none {
// Remove this port. // Remove this port.

View File

@@ -322,6 +322,7 @@ enum expr_ {
expr_copy(@expr), expr_copy(@expr),
expr_move(@expr, @expr), expr_move(@expr, @expr),
expr_unary_move(@expr),
expr_assign(@expr, @expr), expr_assign(@expr, @expr),
expr_swap(@expr, @expr), expr_swap(@expr, @expr),
expr_assign_op(binop, @expr, @expr), expr_assign_op(binop, @expr, @expr),

View File

@@ -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_move(fld.fold_expr(el), fld.fold_expr(er))
} }
expr_copy(e) { expr_copy(fld.fold_expr(e)) } 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(el, er) {
expr_assign(fld.fold_expr(el), fld.fold_expr(er)) expr_assign(fld.fold_expr(el), fld.fold_expr(er))
} }

View File

@@ -31,12 +31,12 @@ import ast::{_mod, add, alt_check, alt_exhaustive, arg, arm, attribute,
expr_index, expr_lit, expr_log, expr_loop, expr_index, expr_lit, expr_log, expr_loop,
expr_loop_body, expr_mac, expr_move, expr_new, expr_path, expr_loop_body, expr_mac, expr_move, expr_new, expr_path,
expr_rec, expr_ret, expr_swap, expr_struct, expr_tup, expr_unary, expr_rec, expr_ret, expr_swap, expr_struct, expr_tup, expr_unary,
expr_vec, expr_vstore, expr_while, extern_fn, field, fn_decl, expr_unary_move, expr_vec, expr_vstore, expr_while, extern_fn,
foreign_item, foreign_item_fn, foreign_mod, ident, impure_fn, field, fn_decl, foreign_item, foreign_item_fn, foreign_mod,
infer, init_assign, init_move, initializer, instance_var, item, ident, impure_fn, infer, init_assign, init_move, initializer,
item_, item_class, item_const, item_enum, item_fn, instance_var, item, item_, item_class, item_const, item_enum,
item_foreign_mod, item_impl, item_mac, item_mod, item_trait, item_fn, item_foreign_mod, item_impl, item_mac, item_mod,
item_ty, lit, lit_, lit_bool, lit_float, lit_int, item_trait, item_ty, lit, lit_, lit_bool, lit_float, lit_int,
lit_int_unsuffixed, lit_nil, lit_str, lit_uint, local, m_const, lit_int_unsuffixed, lit_nil, lit_str, lit_uint, local, m_const,
m_imm, m_mutbl, mac_, mac_aq, mac_ellipsis, m_imm, m_mutbl, mac_, mac_aq, mac_ellipsis,
mac_invoc, mac_invoc_tt, mac_var, matcher, match_nonterminal, mac_invoc, mac_invoc_tt, mac_var, matcher, match_nonterminal,
@@ -854,6 +854,10 @@ class parser {
let e = self.parse_expr(); let e = self.parse_expr();
ex = expr_copy(e); ex = expr_copy(e);
hi = e.span.hi; 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 || } else if self.token == token::MOD_SEP ||
is_ident(self.token) && !self.is_keyword(~"true") && is_ident(self.token) && !self.is_keyword(~"true") &&
!self.is_keyword(~"false") { !self.is_keyword(~"false") {

View File

@@ -327,7 +327,7 @@ fn restricted_keyword_table() -> hashmap<~str, ()> {
~"fail", ~"false", ~"fn", ~"for", ~"fail", ~"false", ~"fn", ~"for",
~"if", ~"iface", ~"impl", ~"import", ~"if", ~"iface", ~"impl", ~"import",
~"let", ~"log", ~"loop", ~"let", ~"log", ~"loop",
~"match", ~"mod", ~"module", ~"mut", ~"match", ~"mod", ~"module", ~"move", ~"mut",
~"new", ~"new",
~"owned", ~"owned",
~"pure", ~"pure",

View File

@@ -1100,6 +1100,7 @@ fn print_expr(s: ps, &&expr: @ast::expr) {
print_block(s, blk); print_block(s, blk);
} }
ast::expr_copy(e) { word_space(s, ~"copy"); print_expr(s, e); } 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) { ast::expr_move(lhs, rhs) {
print_expr(s, lhs); print_expr(s, lhs);
space(s.s); space(s.s);

View File

@@ -408,6 +408,7 @@ fn visit_expr<E>(ex: @expr, e: E, v: vt<E>) {
expr_block(b) { v.visit_block(b, e, v); } 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_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_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_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_swap(a, b) { v.visit_expr(a, e, v); v.visit_expr(b, e, v); }
expr_assign_op(_, a, b) { expr_assign_op(_, a, b) {

View File

@@ -181,7 +181,8 @@ impl public_methods for borrowck_ctxt {
ast::expr_new(*) | ast::expr_binary(*) | ast::expr_while(*) | ast::expr_new(*) | ast::expr_binary(*) | ast::expr_while(*) |
ast::expr_block(*) | ast::expr_loop(*) | ast::expr_alt(*) | ast::expr_block(*) | ast::expr_loop(*) | ast::expr_alt(*) |
ast::expr_lit(*) | ast::expr_break | ast::expr_mac(*) | 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); ret self.cat_rvalue(expr, expr_ty);
} }
} }

View File

@@ -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_loop_body(*) | expr_do_body(*) | expr_cast(*) |
expr_unary(*) | expr_fail(*) | expr_unary(*) | expr_fail(*) |
expr_break | expr_again | expr_lit(_) | expr_ret(*) | expr_break | expr_again | expr_lit(_) | expr_ret(*) |
expr_block(*) | expr_move(*) | expr_assign(*) | expr_swap(*) | expr_block(*) | expr_move(*) | expr_unary_move(*) | expr_assign(*) |
expr_assign_op(*) | expr_mac(*) | expr_struct(*) { expr_swap(*) | expr_assign_op(*) | expr_mac(*) | expr_struct(*) => {
visit::visit_expr(expr, self, vt); visit::visit_expr(expr, self, vt);
} }
} }
@@ -1104,6 +1104,7 @@ class liveness {
expr_assert(e) | expr_assert(e) |
expr_addr_of(_, e) | expr_addr_of(_, e) |
expr_copy(e) | expr_copy(e) |
expr_unary_move(e) |
expr_loop_body(e) | expr_loop_body(e) |
expr_do_body(e) | expr_do_body(e) |
expr_cast(e, _) | expr_cast(e, _) |
@@ -1430,6 +1431,12 @@ fn check_expr(expr: @expr, &&self: @liveness, vt: vt<@liveness>) {
visit::visit_expr(expr, self, vt); 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, _) { expr_assign_op(_, l, _) {
self.check_lvalue(l, vt); self.check_lvalue(l, vt);

View File

@@ -3682,7 +3682,7 @@ fn trans_expr(bcx: block, e: @ast::expr, dest: dest) -> block {
ast::expr_do_body(blk) { ast::expr_do_body(blk) {
ret trans_expr(bcx, blk, dest); 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) { if !expr_is_lval(bcx, a) {
ret trans_expr(bcx, a, dest); ret trans_expr(bcx, a, dest);
} }

View File

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

View File

@@ -1416,7 +1416,7 @@ fn check_expr_with_unifier(fcx: @fn_ctxt,
bot = check_expr_with(fcx, e, ty::mk_bool(tcx)); bot = check_expr_with(fcx, e, ty::mk_bool(tcx));
fcx.write_nil(id); fcx.write_nil(id);
} }
ast::expr_copy(a) { ast::expr_copy(a) | ast::expr_unary_move(a) {
bot = check_expr(fcx, a, expected); bot = check_expr(fcx, a, expected);
fcx.write_ty(id, fcx.expr_ty(a)); fcx.write_ty(id, fcx.expr_ty(a));
} }

View File

@@ -0,0 +1,8 @@
// error-pattern: use of moved variable
fn main() {
let x = 3;
let y = move x;
debug!("%d", x);
}