librustc: Implement placement box
for GC and unique pointers.
This commit is contained in:
parent
dd11fe17c7
commit
e12711540a
@ -394,6 +394,10 @@ impl CFGBuilder {
|
||||
self.straightline(expr, pred, [l, r])
|
||||
}
|
||||
|
||||
ast::ExprBox(p, e) => {
|
||||
self.straightline(expr, pred, [p, e])
|
||||
}
|
||||
|
||||
ast::ExprAddrOf(_, e) |
|
||||
ast::ExprDoBody(e) |
|
||||
ast::ExprCast(e, _) |
|
||||
|
@ -721,6 +721,11 @@ impl<'a, O:DataFlowOperator> PropagationContext<'a, O> {
|
||||
self.walk_expr(e, in_out, loop_scopes);
|
||||
}
|
||||
|
||||
ast::ExprBox(s, e) => {
|
||||
self.walk_expr(s, in_out, loop_scopes);
|
||||
self.walk_expr(e, in_out, loop_scopes);
|
||||
}
|
||||
|
||||
ast::ExprInlineAsm(ref inline_asm) => {
|
||||
for &(_, expr) in inline_asm.inputs.iter() {
|
||||
self.walk_expr(expr, in_out, loop_scopes);
|
||||
|
@ -207,7 +207,7 @@ pub fn collect_language_items(crate: &ast::Crate,
|
||||
}
|
||||
|
||||
lets_do_this! {
|
||||
There are 37 lang items.
|
||||
There are 40 lang items.
|
||||
|
||||
// ID, Variant name, Name, Method name;
|
||||
0, FreezeTraitLangItem, "freeze", freeze_trait;
|
||||
@ -256,5 +256,9 @@ lets_do_this! {
|
||||
35, TypeIdLangItem, "type_id", type_id;
|
||||
|
||||
36, EhPersonalityLangItem, "eh_personality", eh_personality_fn;
|
||||
|
||||
37, ManagedHeapLangItem, "managed_heap", managed_heap;
|
||||
38, ExchangeHeapLangItem, "exchange_heap", exchange_heap;
|
||||
39, GcLangItem, "gc", gc;
|
||||
}
|
||||
|
||||
|
@ -556,7 +556,7 @@ fn visit_expr(v: &mut LivenessVisitor, expr: &Expr, this: @IrMaps) {
|
||||
ExprAgain(_) | ExprLit(_) | ExprRet(..) | ExprBlock(..) |
|
||||
ExprAssign(..) | ExprAssignOp(..) | ExprMac(..) |
|
||||
ExprStruct(..) | ExprRepeat(..) | ExprParen(..) |
|
||||
ExprInlineAsm(..) => {
|
||||
ExprInlineAsm(..) | ExprBox(..) => {
|
||||
visit::walk_expr(v, expr, this);
|
||||
}
|
||||
}
|
||||
@ -1252,7 +1252,8 @@ impl Liveness {
|
||||
}
|
||||
|
||||
ExprIndex(_, l, r) |
|
||||
ExprBinary(_, _, l, r) => {
|
||||
ExprBinary(_, _, l, r) |
|
||||
ExprBox(l, r) => {
|
||||
self.propagate_through_exprs([l, r], succ)
|
||||
}
|
||||
|
||||
@ -1546,7 +1547,7 @@ fn check_expr(this: &mut Liveness, expr: &Expr) {
|
||||
ExprAgain(..) | ExprLit(_) | ExprBlock(..) |
|
||||
ExprMac(..) | ExprAddrOf(..) | ExprStruct(..) | ExprRepeat(..) |
|
||||
ExprParen(..) | ExprFnBlock(..) | ExprProc(..) | ExprPath(..) |
|
||||
ExprSelf(..) => {
|
||||
ExprSelf(..) | ExprBox(..) => {
|
||||
visit::walk_expr(this, expr, ());
|
||||
}
|
||||
ExprForLoop(..) => fail!("non-desugared expr_for_loop")
|
||||
|
@ -438,7 +438,7 @@ impl mem_categorization_ctxt {
|
||||
ast::ExprBlock(..) | ast::ExprLoop(..) | ast::ExprMatch(..) |
|
||||
ast::ExprLit(..) | ast::ExprBreak(..) | ast::ExprMac(..) |
|
||||
ast::ExprAgain(..) | ast::ExprStruct(..) | ast::ExprRepeat(..) |
|
||||
ast::ExprInlineAsm(..) => {
|
||||
ast::ExprInlineAsm(..) | ast::ExprBox(..) => {
|
||||
return self.cat_rvalue_node(expr, expr_ty);
|
||||
}
|
||||
|
||||
|
@ -591,6 +591,11 @@ impl VisitContext {
|
||||
self.use_expr(base, comp_mode);
|
||||
}
|
||||
|
||||
ExprBox(place, base) => {
|
||||
self.use_expr(place, comp_mode);
|
||||
self.use_expr(base, comp_mode);
|
||||
}
|
||||
|
||||
ExprMac(..) => {
|
||||
self.tcx.sess.span_bug(
|
||||
expr.span,
|
||||
|
@ -2616,6 +2616,11 @@ fn populate_scope_map(cx: &CrateContext,
|
||||
ast::ExprField(@ref sub_exp, _, _) |
|
||||
ast::ExprParen(@ref sub_exp) => walk_expr(cx, sub_exp, scope_stack, scope_map),
|
||||
|
||||
ast::ExprBox(@ref place, @ref sub_expr) => {
|
||||
walk_expr(cx, place, scope_stack, scope_map);
|
||||
walk_expr(cx, sub_expr, scope_stack, scope_map);
|
||||
}
|
||||
|
||||
ast::ExprRet(exp_opt) => match exp_opt {
|
||||
Some(@ref sub_exp) => walk_expr(cx, sub_exp, scope_stack, scope_map),
|
||||
None => ()
|
||||
|
@ -619,6 +619,14 @@ fn trans_rvalue_datum_unadjusted<'a>(bcx: &'a Block<'a>, expr: &ast::Expr)
|
||||
return tvec::trans_uniq_or_managed_vstore(bcx, heap,
|
||||
expr, contents);
|
||||
}
|
||||
ast::ExprBox(_, contents) => {
|
||||
// Special case for `~T`. (The other case, for GC, is handled in
|
||||
// `trans_rvalue_dps_unadjusted`.)
|
||||
let box_ty = expr_ty(bcx, expr);
|
||||
let contents_ty = expr_ty(bcx, contents);
|
||||
let heap = heap_for_unique(bcx, contents_ty);
|
||||
return trans_boxed_expr(bcx, box_ty, contents, contents_ty, heap)
|
||||
}
|
||||
ast::ExprLit(lit) => {
|
||||
return trans_immediate_lit(bcx, expr, *lit);
|
||||
}
|
||||
@ -828,6 +836,11 @@ fn trans_rvalue_dps_unadjusted<'a>(
|
||||
ast::ExprAssignOp(callee_id, op, dst, src) => {
|
||||
return trans_assign_op(bcx, expr, callee_id, op, dst, src);
|
||||
}
|
||||
ast::ExprBox(_, contents) => {
|
||||
// Special case for `Gc<T>` for now. The other case, for unique
|
||||
// pointers, is handled in `trans_rvalue_datum_unadjusted`.
|
||||
return trans_gc(bcx, expr, contents, dest)
|
||||
}
|
||||
_ => {
|
||||
bcx.tcx().sess.span_bug(
|
||||
expr.span,
|
||||
@ -1463,35 +1476,35 @@ fn trans_unary_datum<'a>(
|
||||
trans_unary_datum()")
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
fn trans_boxed_expr<'a>(
|
||||
bcx: &'a Block<'a>,
|
||||
box_ty: ty::t,
|
||||
contents: &ast::Expr,
|
||||
contents_ty: ty::t,
|
||||
heap: heap)
|
||||
-> DatumBlock<'a> {
|
||||
let _icx = push_ctxt("trans_boxed_expr");
|
||||
if heap == heap_exchange {
|
||||
let llty = type_of::type_of(bcx.ccx(), contents_ty);
|
||||
let size = llsize_of(bcx.ccx(), llty);
|
||||
let Result { bcx: bcx, val: val } = malloc_raw_dyn(bcx, contents_ty,
|
||||
heap_exchange, size);
|
||||
add_clean_free(bcx, val, heap_exchange);
|
||||
let bcx = trans_into(bcx, contents, SaveIn(val));
|
||||
revoke_clean(bcx, val);
|
||||
return immediate_rvalue_bcx(bcx, val, box_ty);
|
||||
} else {
|
||||
let base::MallocResult {
|
||||
bcx,
|
||||
smart_ptr: bx,
|
||||
body
|
||||
} = base::malloc_general(bcx, contents_ty, heap);
|
||||
add_clean_free(bcx, bx, heap);
|
||||
let bcx = trans_into(bcx, contents, SaveIn(body));
|
||||
revoke_clean(bcx, bx);
|
||||
return immediate_rvalue_bcx(bcx, bx, box_ty);
|
||||
}
|
||||
fn trans_boxed_expr<'a>(
|
||||
bcx: &'a Block<'a>,
|
||||
box_ty: ty::t,
|
||||
contents: &ast::Expr,
|
||||
contents_ty: ty::t,
|
||||
heap: heap)
|
||||
-> DatumBlock<'a> {
|
||||
let _icx = push_ctxt("trans_boxed_expr");
|
||||
if heap == heap_exchange {
|
||||
let llty = type_of::type_of(bcx.ccx(), contents_ty);
|
||||
let size = llsize_of(bcx.ccx(), llty);
|
||||
let Result { bcx: bcx, val: val } = malloc_raw_dyn(bcx, contents_ty,
|
||||
heap_exchange, size);
|
||||
add_clean_free(bcx, val, heap_exchange);
|
||||
let bcx = trans_into(bcx, contents, SaveIn(val));
|
||||
revoke_clean(bcx, val);
|
||||
return immediate_rvalue_bcx(bcx, val, box_ty);
|
||||
} else {
|
||||
let base::MallocResult {
|
||||
bcx,
|
||||
smart_ptr: bx,
|
||||
body
|
||||
} = base::malloc_general(bcx, contents_ty, heap);
|
||||
add_clean_free(bcx, bx, heap);
|
||||
let bcx = trans_into(bcx, contents, SaveIn(body));
|
||||
revoke_clean(bcx, bx);
|
||||
return immediate_rvalue_bcx(bcx, bx, box_ty);
|
||||
}
|
||||
}
|
||||
|
||||
@ -1507,6 +1520,42 @@ fn trans_addr_of<'a>(
|
||||
return immediate_rvalue_bcx(bcx, llval, expr_ty(bcx, expr));
|
||||
}
|
||||
|
||||
pub fn trans_gc<'a>(
|
||||
mut bcx: &'a Block<'a>,
|
||||
expr: &ast::Expr,
|
||||
contents: &ast::Expr,
|
||||
dest: Dest)
|
||||
-> &'a Block<'a> {
|
||||
let contents_ty = expr_ty(bcx, contents);
|
||||
let box_ty = ty::mk_box(bcx.tcx(), contents_ty);
|
||||
let expr_ty = expr_ty(bcx, expr);
|
||||
|
||||
let addr = match dest {
|
||||
Ignore => {
|
||||
return trans_boxed_expr(bcx,
|
||||
box_ty,
|
||||
contents,
|
||||
contents_ty,
|
||||
heap_managed).bcx
|
||||
}
|
||||
SaveIn(addr) => addr,
|
||||
};
|
||||
|
||||
let repr = adt::represent_type(bcx.ccx(), expr_ty);
|
||||
adt::trans_start_init(bcx, repr, addr, 0);
|
||||
let field_dest = adt::trans_field_ptr(bcx, repr, addr, 0, 0);
|
||||
let contents_datum_block = trans_boxed_expr(bcx,
|
||||
box_ty,
|
||||
contents,
|
||||
contents_ty,
|
||||
heap_managed);
|
||||
bcx = contents_datum_block.bcx;
|
||||
bcx = contents_datum_block.datum.move_to(bcx, INIT, field_dest);
|
||||
|
||||
// Next, wrap it up in the struct.
|
||||
bcx
|
||||
}
|
||||
|
||||
// Important to get types for both lhs and rhs, because one might be _|_
|
||||
// and the other not.
|
||||
fn trans_eager_binop<'a>(
|
||||
|
@ -13,8 +13,8 @@ use back::abi;
|
||||
use lib;
|
||||
use lib::llvm::{llvm, ValueRef};
|
||||
use middle::lang_items::StrDupUniqFnLangItem;
|
||||
use middle::trans::base;
|
||||
use middle::trans::base::*;
|
||||
use middle::trans::base;
|
||||
use middle::trans::build::*;
|
||||
use middle::trans::callee;
|
||||
use middle::trans::common::*;
|
||||
@ -23,14 +23,12 @@ use middle::trans::expr::{Dest, Ignore, SaveIn};
|
||||
use middle::trans::expr;
|
||||
use middle::trans::glue;
|
||||
use middle::trans::machine::{llsize_of, nonzero_llsize_of, llsize_of_alloc};
|
||||
use middle::trans::type_::Type;
|
||||
use middle::trans::type_of;
|
||||
use middle::ty;
|
||||
use util::common::indenter;
|
||||
use util::ppaux::ty_to_str;
|
||||
|
||||
use middle::trans::type_::Type;
|
||||
|
||||
use std::option::None;
|
||||
use syntax::ast;
|
||||
use syntax::codemap;
|
||||
|
||||
@ -689,3 +687,4 @@ pub fn iter_vec_unboxed<'r,
|
||||
let dataptr = get_dataptr(bcx, body_ptr);
|
||||
return iter_vec_raw(bcx, dataptr, vec_ty, fill, f);
|
||||
}
|
||||
|
||||
|
@ -12,8 +12,8 @@ use driver::session;
|
||||
use metadata::csearch;
|
||||
use metadata;
|
||||
use middle::const_eval;
|
||||
use middle::lang_items::{ExchangeHeapLangItem, OpaqueStructLangItem};
|
||||
use middle::lang_items::{TyDescStructLangItem, TyVisitorTraitLangItem};
|
||||
use middle::lang_items::OpaqueStructLangItem;
|
||||
use middle::freevars;
|
||||
use middle::resolve;
|
||||
use middle::resolve_lifetime;
|
||||
@ -3241,6 +3241,20 @@ pub fn expr_kind(tcx: ctxt,
|
||||
RvalueDatumExpr
|
||||
}
|
||||
|
||||
ast::ExprBox(place, _) => {
|
||||
// Special case `~T` for now:
|
||||
let def_map = tcx.def_map.borrow();
|
||||
let definition = match def_map.get().find(&place.id) {
|
||||
Some(&def) => def,
|
||||
None => fail!("no def for place"),
|
||||
};
|
||||
let def_id = ast_util::def_id_of_def(definition);
|
||||
match tcx.lang_items.items[ExchangeHeapLangItem as uint] {
|
||||
Some(item_def_id) if def_id == item_def_id => RvalueDatumExpr,
|
||||
Some(_) | None => RvalueDpsExpr,
|
||||
}
|
||||
}
|
||||
|
||||
ast::ExprParen(e) => expr_kind(tcx, method_map, e),
|
||||
|
||||
ast::ExprMac(..) => {
|
||||
|
@ -78,9 +78,11 @@ type parameter).
|
||||
|
||||
|
||||
use middle::const_eval;
|
||||
use middle::lang_items::{ExchangeHeapLangItem, GcLangItem};
|
||||
use middle::lang_items::{ManagedHeapLangItem};
|
||||
use middle::lint::unreachable_code;
|
||||
use middle::pat_util::pat_id_map;
|
||||
use middle::pat_util;
|
||||
use middle::lint::unreachable_code;
|
||||
use middle::subst::Subst;
|
||||
use middle::ty::{FnSig, VariantInfo};
|
||||
use middle::ty::{ty_param_bounds_and_ty, ty_param_substs_and_ty};
|
||||
@ -2679,6 +2681,73 @@ pub fn check_expr_with_unifier(fcx: @FnCtxt,
|
||||
fcx.write_ty(id, typ);
|
||||
}
|
||||
|
||||
ast::ExprBox(place, subexpr) => {
|
||||
check_expr(fcx, place);
|
||||
check_expr(fcx, subexpr);
|
||||
|
||||
let mut checked = false;
|
||||
match place.node {
|
||||
ast::ExprPath(ref path) => {
|
||||
// XXX(pcwalton): For now we hardcode the two permissible
|
||||
// places: the exchange heap and the managed heap.
|
||||
let definition = lookup_def(fcx, path.span, place.id);
|
||||
let def_id = ast_util::def_id_of_def(definition);
|
||||
match tcx.lang_items.items[ExchangeHeapLangItem as uint] {
|
||||
Some(item_def_id) if def_id == item_def_id => {
|
||||
fcx.write_ty(id, ty::mk_uniq(tcx, ty::mt {
|
||||
ty: fcx.expr_ty(subexpr),
|
||||
mutbl: ast::MutImmutable,
|
||||
}));
|
||||
checked = true
|
||||
}
|
||||
Some(_) | None => {}
|
||||
}
|
||||
if !checked {
|
||||
match tcx.lang_items
|
||||
.items[ManagedHeapLangItem as uint] {
|
||||
Some(item_def_id) if def_id == item_def_id => {
|
||||
// Assign the magic `Gc<T>` struct.
|
||||
let gc_struct_id =
|
||||
match tcx.lang_items
|
||||
.require(GcLangItem) {
|
||||
Ok(id) => id,
|
||||
Err(msg) => {
|
||||
tcx.sess.span_err(expr.span, msg);
|
||||
ast::DefId {
|
||||
crate: ast::CRATE_NODE_ID,
|
||||
node: ast::DUMMY_NODE_ID,
|
||||
}
|
||||
}
|
||||
};
|
||||
let regions =
|
||||
ty::NonerasedRegions(opt_vec::Empty);
|
||||
let sty = ty::mk_struct(tcx,
|
||||
gc_struct_id,
|
||||
substs {
|
||||
self_ty: None,
|
||||
tps: ~[
|
||||
fcx.expr_ty(
|
||||
subexpr)
|
||||
],
|
||||
regions: regions,
|
||||
});
|
||||
fcx.write_ty(id, sty);
|
||||
checked = true
|
||||
}
|
||||
Some(_) | None => {}
|
||||
}
|
||||
}
|
||||
}
|
||||
_ => {}
|
||||
}
|
||||
|
||||
if !checked {
|
||||
tcx.sess.span_err(expr.span,
|
||||
"only the managed heap and exchange heap are \
|
||||
currently supported")
|
||||
}
|
||||
}
|
||||
|
||||
ast::ExprLit(lit) => {
|
||||
let typ = check_lit(fcx, lit);
|
||||
fcx.write_ty(id, typ);
|
||||
|
@ -1048,6 +1048,7 @@ pub mod guarantor {
|
||||
ast::ExprAddrOf(..) |
|
||||
ast::ExprBinary(..) |
|
||||
ast::ExprVstore(..) |
|
||||
ast::ExprBox(..) |
|
||||
ast::ExprBreak(..) |
|
||||
ast::ExprAgain(..) |
|
||||
ast::ExprRet(..) |
|
||||
|
@ -21,6 +21,14 @@ use clone::{Clone, DeepClone};
|
||||
use managed;
|
||||
|
||||
/// Immutable garbage-collected pointer type
|
||||
#[lang="gc"]
|
||||
#[cfg(not(test))]
|
||||
#[no_send]
|
||||
pub struct Gc<T> {
|
||||
priv ptr: @T
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
#[no_send]
|
||||
pub struct Gc<T> {
|
||||
priv ptr: @T
|
||||
@ -54,6 +62,16 @@ impl<T> Clone for Gc<T> {
|
||||
}
|
||||
}
|
||||
|
||||
/// An value that represents the task-local managed heap.
|
||||
///
|
||||
/// Use this like `let foo = box(GC) Bar::new(...);`
|
||||
#[lang="managed_heap"]
|
||||
#[cfg(not(test))]
|
||||
pub static GC: () = ();
|
||||
|
||||
#[cfg(test)]
|
||||
pub static GC: () = ();
|
||||
|
||||
/// The `Send` bound restricts this to acyclic graphs where it is well-defined.
|
||||
///
|
||||
/// A `Freeze` bound would also work, but `Send` *or* `Freeze` cannot be expressed.
|
||||
|
@ -12,6 +12,20 @@
|
||||
|
||||
#[cfg(not(test))] use cmp::*;
|
||||
|
||||
/// A value that represents the global exchange heap. This is the default
|
||||
/// place that the `box` keyword allocates into when no place is supplied.
|
||||
///
|
||||
/// The following two examples are equivalent:
|
||||
///
|
||||
/// let foo = box(HEAP) Bar::new(...);
|
||||
/// let foo = box Bar::new(...);
|
||||
#[lang="exchange_heap"]
|
||||
#[cfg(not(test))]
|
||||
pub static HEAP: () = ();
|
||||
|
||||
#[cfg(test)]
|
||||
pub static HEAP: () = ();
|
||||
|
||||
#[cfg(not(test))]
|
||||
impl<T:Eq> Eq for ~T {
|
||||
#[inline]
|
||||
|
@ -86,6 +86,10 @@ pub use vec::{Vector, VectorVector, CopyableVector, ImmutableVector};
|
||||
pub use comm::{Port, Chan, SharedChan};
|
||||
pub use task::spawn;
|
||||
|
||||
// Reexported statics
|
||||
#[cfg(not(test))]
|
||||
pub use gc::GC;
|
||||
|
||||
/// Disposes of a value.
|
||||
#[inline]
|
||||
pub fn drop<T>(_x: T) { }
|
||||
|
@ -547,6 +547,8 @@ pub enum CallSugar {
|
||||
#[deriving(Clone, Eq, Encodable, Decodable, IterBytes)]
|
||||
pub enum Expr_ {
|
||||
ExprVstore(@Expr, ExprVstore),
|
||||
// First expr is the place; second expr is the value.
|
||||
ExprBox(@Expr, @Expr),
|
||||
ExprVec(~[@Expr], Mutability),
|
||||
ExprCall(@Expr, ~[@Expr], CallSugar),
|
||||
ExprMethodCall(NodeId, @Expr, Ident, ~[P<Ty>], ~[@Expr], CallSugar),
|
||||
|
@ -724,6 +724,9 @@ pub fn noop_fold_expr<T: ast_fold>(e: @Expr, folder: &mut T) -> @Expr {
|
||||
ExprVstore(e, v) => {
|
||||
ExprVstore(folder.fold_expr(e), v)
|
||||
}
|
||||
ExprBox(p, e) => {
|
||||
ExprBox(folder.fold_expr(p), folder.fold_expr(e))
|
||||
}
|
||||
ExprVec(ref exprs, mutt) => {
|
||||
ExprVec(exprs.map(|&x| folder.fold_expr(x)), mutt)
|
||||
}
|
||||
|
@ -23,7 +23,7 @@ use ast::{BlockCheckMode, UnBox};
|
||||
use ast::{Crate, CrateConfig, Decl, DeclItem};
|
||||
use ast::{DeclLocal, DefaultBlock, UnDeref, BiDiv, EMPTY_CTXT, enum_def, explicit_self};
|
||||
use ast::{Expr, Expr_, ExprAddrOf, ExprMatch, ExprAgain};
|
||||
use ast::{ExprAssign, ExprAssignOp, ExprBinary, ExprBlock};
|
||||
use ast::{ExprAssign, ExprAssignOp, ExprBinary, ExprBlock, ExprBox};
|
||||
use ast::{ExprBreak, ExprCall, ExprCast, ExprDoBody};
|
||||
use ast::{ExprField, ExprFnBlock, ExprIf, ExprIndex};
|
||||
use ast::{ExprLit, ExprLogLevel, ExprLoop, ExprMac};
|
||||
@ -2325,6 +2325,20 @@ impl Parser {
|
||||
token::IDENT(_, _) if self.is_keyword(keywords::Box) => {
|
||||
self.bump();
|
||||
|
||||
// Check for a place: `box(PLACE) EXPR`.
|
||||
if self.eat(&token::LPAREN) {
|
||||
// Support `box() EXPR` as the default.
|
||||
if !self.eat(&token::RPAREN) {
|
||||
let place = self.parse_expr();
|
||||
self.expect(&token::RPAREN);
|
||||
let subexpression = self.parse_prefix_expr();
|
||||
hi = subexpression.span.hi;
|
||||
ex = ExprBox(place, subexpression);
|
||||
return self.mk_expr(lo, hi, ex);
|
||||
}
|
||||
}
|
||||
|
||||
// Otherwise, we use the unique pointer default.
|
||||
let subexpression = self.parse_prefix_expr();
|
||||
hi = subexpression.span.hi;
|
||||
// HACK: turn `box [...]` into a boxed-evec
|
||||
|
@ -1155,6 +1155,13 @@ pub fn print_expr(s: &mut ps, expr: &ast::Expr) {
|
||||
print_expr_vstore(s, v);
|
||||
print_expr(s, e);
|
||||
},
|
||||
ast::ExprBox(p, e) => {
|
||||
word(&mut s.s, "box");
|
||||
word(&mut s.s, "(");
|
||||
print_expr(s, p);
|
||||
word_space(s, ")");
|
||||
print_expr(s, e);
|
||||
}
|
||||
ast::ExprVec(ref exprs, mutbl) => {
|
||||
ibox(s, indent_unit);
|
||||
word(&mut s.s, "[");
|
||||
|
@ -618,6 +618,10 @@ pub fn walk_expr<E: Clone, V: Visitor<E>>(visitor: &mut V, expression: &Expr, en
|
||||
ExprVstore(subexpression, _) => {
|
||||
visitor.visit_expr(subexpression, env.clone())
|
||||
}
|
||||
ExprBox(place, subexpression) => {
|
||||
visitor.visit_expr(place, env.clone());
|
||||
visitor.visit_expr(subexpression, env.clone())
|
||||
}
|
||||
ExprVec(ref subexpressions, _) => {
|
||||
walk_exprs(visitor, *subexpressions, env.clone())
|
||||
}
|
||||
|
14
src/test/compile-fail/new-box-syntax-bad.rs
Normal file
14
src/test/compile-fail/new-box-syntax-bad.rs
Normal file
@ -0,0 +1,14 @@
|
||||
/* Any copyright is dedicated to the Public Domain.
|
||||
* http://creativecommons.org/publicdomain/zero/1.0/ */
|
||||
|
||||
// Tests that the new `box` syntax works with unique pointers and GC pointers.
|
||||
|
||||
use std::gc::Gc;
|
||||
use std::owned::HEAP;
|
||||
|
||||
pub fn main() {
|
||||
let x: Gc<int> = box(HEAP) 2; //~ ERROR mismatched types
|
||||
let y: Gc<int> = box(HEAP)(1 + 2); //~ ERROR mismatched types
|
||||
let z: ~int = box(GC)(4 + 5); //~ ERROR mismatched types
|
||||
}
|
||||
|
@ -1,8 +1,26 @@
|
||||
/* Any copyright is dedicated to the Public Domain.
|
||||
* http://creativecommons.org/publicdomain/zero/1.0/ */
|
||||
|
||||
pub fn main() {
|
||||
let x: ~int = box 3;
|
||||
println!("{}", *x);
|
||||
// Tests that the new `box` syntax works with unique pointers and GC pointers.
|
||||
|
||||
use std::gc::Gc;
|
||||
use std::owned::HEAP;
|
||||
|
||||
struct Structure {
|
||||
x: int,
|
||||
y: int,
|
||||
}
|
||||
|
||||
pub fn main() {
|
||||
let x: ~int = box(HEAP) 2;
|
||||
let y: ~int = box 2;
|
||||
let z: Gc<int> = box(GC) 2;
|
||||
let a: Gc<Structure> = box(GC) Structure {
|
||||
x: 10,
|
||||
y: 20,
|
||||
};
|
||||
let b: ~int = box()(1 + 2);
|
||||
let c = box()(3 + 4);
|
||||
let d = box(GC)(5 + 6);
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user