rustc: Implement unary move. Closes #917.
This commit is contained in:
@@ -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
|
||||||
|
|||||||
@@ -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} }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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.
|
||||||
|
|||||||
@@ -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),
|
||||||
|
|||||||
@@ -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))
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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") {
|
||||||
|
|||||||
@@ -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",
|
||||||
|
|||||||
@@ -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);
|
||||||
|
|||||||
@@ -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) {
|
||||||
|
|||||||
@@ -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);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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);
|
||||||
|
|
||||||
|
|||||||
@@ -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);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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, _) {
|
||||||
|
|||||||
@@ -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));
|
||||||
}
|
}
|
||||||
|
|||||||
8
src/test/compile-fail/unary-move.rs
Normal file
8
src/test/compile-fail/unary-move.rs
Normal file
@@ -0,0 +1,8 @@
|
|||||||
|
// error-pattern: use of moved variable
|
||||||
|
|
||||||
|
fn main() {
|
||||||
|
let x = 3;
|
||||||
|
let y = move x;
|
||||||
|
debug!("%d", x);
|
||||||
|
}
|
||||||
|
|
||||||
Reference in New Issue
Block a user