1
Fork 0

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 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

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 } }
}
@ -78,7 +78,7 @@ fn from_port<A:send>(-port: future_pipe::client::waiting<A>) -> future<A> {
port_ <-> *port;
let port = option::unwrap(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;
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<T>(-x: T) -> T { x }
fn move_it<T>(-x: T) -> T { x }
enum state {
empty,
@ -228,7 +228,7 @@ class buffer_resource<T: send> {
}
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<T: send> of recv<T> for port<T> {
fn try_recv() -> option<T> {
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<T: send> : recv<T> {
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.

View file

@ -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),

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_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))
}

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_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") {

View file

@ -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",

View file

@ -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);

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_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) {

View file

@ -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);
}
}

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_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);

View file

@ -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);
}

View file

@ -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, _) {

View file

@ -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));
}

View file

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