#[test]
fn gc_inside() {
// see issue #11532
- use std::gc::Gc;
- let a = Rc::new(RefCell::new(Gc::new(1)));
+ use realstd::gc::Gc;
+ let a = Rc::new(RefCell::new(box(GC) 1));
assert!(a.try_borrow_mut().is_some());
}
}
}
-impl<S: Writer, T: Hash<S>> Hash<S> for @T {
- #[inline]
- fn hash(&self, state: &mut S) {
- (**self).hash(state);
- }
-}
-
impl<S: Writer, T: Hash<S>> Hash<S> for Rc<T> {
#[inline]
fn hash(&self, state: &mut S) {
}
}
-impl<T> Clone for @T {
- /// Return a shallow copy of the managed box.
- #[inline]
- fn clone(&self) -> @T { *self }
-}
-
impl<'a, T> Clone for &'a T {
/// Return a shallow copy of the reference.
#[inline]
fn cmp(&self, other: &&'a mut T) -> Ordering { (**self).cmp(*other) }
}
impl<'a, T: Eq> Eq for &'a mut T {}
-
- // @ pointers
- impl<T:PartialEq> PartialEq for @T {
- #[inline]
- fn eq(&self, other: &@T) -> bool { *(*self) == *(*other) }
- #[inline]
- fn ne(&self, other: &@T) -> bool { *(*self) != *(*other) }
- }
- impl<T:PartialOrd> PartialOrd for @T {
- #[inline]
- fn lt(&self, other: &@T) -> bool { *(*self) < *(*other) }
- #[inline]
- fn le(&self, other: &@T) -> bool { *(*self) <= *(*other) }
- #[inline]
- fn ge(&self, other: &@T) -> bool { *(*self) >= *(*other) }
- #[inline]
- fn gt(&self, other: &@T) -> bool { *(*self) > *(*other) }
- }
- impl<T: Ord> Ord for @T {
- #[inline]
- fn cmp(&self, other: &@T) -> Ordering { (**self).cmp(*other) }
- }
- impl<T: Eq> Eq for @T {}
}
#[cfg(test)]
default_impl!(f32, 0.0f32)
default_impl!(f64, 0.0f64)
-
-impl<T: Default + 'static> Default for @T {
- fn default() -> @T { @Default::default() }
-}
// Implementations of the core formatting traits
-impl<T: Show> Show for @T {
- fn fmt(&self, f: &mut Formatter) -> Result { secret_show(&**self, f) }
-}
impl<'a, T: Show> Show for &'a T {
fn fmt(&self, f: &mut Formatter) -> Result { secret_show(*self, f) }
}
impl<'a, T> Repr<Slice<T>> for &'a [T] {}
impl<'a> Repr<Slice<u8>> for &'a str {}
-impl<T> Repr<*Box<T>> for @T {}
impl<T> Repr<*Vec<T>> for ~[T] {}
#[cfg(test)]
bcx = fcx.pop_and_trans_ast_cleanup_scope(bcx, contents.id);
DatumBlock::new(bcx, datum)
}
- ast::ExprBox(_, contents) => {
- // Special case for `box T`. (The other case, for GC, is handled
- // in `trans_rvalue_dps_unadjusted`.)
+ ast::ExprBox(_, ref contents) => {
+ // Special case for `Box<T>` and `Gc<T>`
let box_ty = expr_ty(bcx, expr);
- let contents_ty = expr_ty(bcx, contents);
- trans_uniq_expr(bcx, box_ty, contents, contents_ty)
+ let contents_ty = expr_ty(bcx, &**contents);
+ match ty::get(box_ty).sty {
+ ty::ty_uniq(..) => {
+ trans_uniq_expr(bcx, box_ty, &**contents, contents_ty)
+ }
+ ty::ty_box(..) => {
+ trans_managed_expr(bcx, box_ty, &**contents, contents_ty)
+ }
+ _ => bcx.sess().span_bug(expr.span,
+ "expected unique or managed box")
+ }
}
ast::ExprLit(lit) => trans_immediate_lit(bcx, expr, (*lit).clone()),
ast::ExprBinary(op, lhs, rhs) => {
ast::ExprAssignOp(op, dst, src) => {
trans_assign_op(bcx, expr, 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`.
- trans_gc(bcx, expr, contents, dest)
- }
_ => {
bcx.tcx().sess.span_bug(
expr.span,
return immediate_rvalue_bcx(bcx, sub_datum.val, ty).to_expr_datumblock();
}
-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 contents_datum = unpack_datum!(bcx, trans_managed_expr(bcx,
- box_ty,
- contents,
- contents_ty));
-
- match dest {
- Ignore => bcx,
- SaveIn(addr) => {
- let expr_ty = expr_ty(bcx, expr);
- 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);
- contents_datum.store_to(bcx, field_dest)
- }
- }
-}
-
// Important to get types for both lhs and rhs, because one might be _|_
// and the other not.
fn trans_eager_binop<'a>(
use middle::const_eval;
use middle::def;
use middle::dependency_format;
-use middle::lang_items::{ExchangeHeapLangItem, OpaqueStructLangItem};
+use middle::lang_items::OpaqueStructLangItem;
use middle::lang_items::{TyDescStructLangItem, TyVisitorTraitLangItem};
use middle::freevars;
use middle::resolve;
}
ast::ExprBox(place, _) => {
- // Special case `Box<T>` for now:
+ // Special case `Box<T>`/`Gc<T>` for now:
let definition = match tcx.def_map.borrow().find(&place.id) {
Some(&def) => def,
None => fail!("no def for place"),
};
let def_id = definition.def_id();
- match tcx.lang_items.items.get(ExchangeHeapLangItem as uint) {
- &Some(item_def_id) if def_id == item_def_id => {
- RvalueDatumExpr
- }
- &Some(_) | &None => RvalueDpsExpr,
+ if tcx.lang_items.exchange_heap() == Some(def_id) ||
+ tcx.lang_items.managed_heap() == Some(def_id) {
+ RvalueDatumExpr
+ } else {
+ RvalueDpsExpr
}
}
supplied to `Box<T>`");
Some(ty::mk_err())
}
+ ast::DefTy(did) | ast::DefStruct(did)
+ if Some(did) == this.tcx().lang_items.gc() => {
+ if path.segments
+ .iter()
+ .flat_map(|s| s.types.iter())
+ .len() > 1 {
+ this.tcx()
+ .sess
+ .span_err(path.span,
+ "`Gc` has only one type parameter")
+ }
+
+ for inner_ast_type in path.segments
+ .iter()
+ .flat_map(|s| s.types.iter()) {
+ let mt = ast::MutTy {
+ ty: *inner_ast_type,
+ mutbl: ast::MutImmutable,
+ };
+ return Some(mk_pointer(this,
+ rscope,
+ &mt,
+ Box,
+ |typ| {
+ match ty::get(typ).sty {
+ ty::ty_str => {
+ this.tcx()
+ .sess
+ .span_err(path.span,
+ "`Gc<str>` is not a type");
+ ty::mk_err()
+ }
+ ty::ty_vec(_, None) => {
+ this.tcx()
+ .sess
+ .span_err(path.span,
+ "`Gc<[T]>` is not a type");
+ ty::mk_err()
+ }
+ _ => ty::mk_box(this.tcx(), typ),
+ }
+ }))
+ }
+ this.tcx().sess.span_bug(path.span,
+ "not enough type parameters \
+ supplied to `Gc<T>`")
+ }
_ => None
}
}
// places: the exchange heap and the managed heap.
let definition = lookup_def(fcx, path.span, place.id);
let def_id = definition.def_id();
- match tcx.lang_items
- .items
- .get(ExchangeHeapLangItem as uint) {
- &Some(item_def_id) if def_id == item_def_id => {
- fcx.write_ty(id, ty::mk_uniq(tcx,
- fcx.expr_ty(subexpr)));
- checked = true
- }
- &Some(_) | &None => {}
- }
- if !checked {
- match tcx.lang_items
- .items
- .get(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.as_slice());
- ast::DefId {
- krate: ast::CRATE_NODE_ID,
- node: ast::DUMMY_NODE_ID,
- }
- }
- };
- let regions =
- subst::NonerasedRegions(Vec::new());
- let sty = ty::mk_struct(tcx,
- gc_struct_id,
- subst::Substs {
- self_ty: None,
- tps: vec!(
- fcx.expr_ty(
- subexpr)
- ),
- regions: regions,
- });
- fcx.write_ty(id, sty);
- checked = true
- }
- &Some(_) | &None => {}
- }
+ if tcx.lang_items.exchange_heap() == Some(def_id) {
+ fcx.write_ty(id, ty::mk_uniq(tcx,
+ fcx.expr_ty(&**subexpr)));
+ checked = true
+ } else if tcx.lang_items.managed_heap() == Some(def_id) {
+ fcx.write_ty(id, ty::mk_box(tcx,
+ fcx.expr_ty(&**subexpr)));
+ checked = true
}
}
_ => {}
_ => {}
}
}
+ ty_box(..) => {
+ match tcx.lang_items.gc() {
+ Some(did) if did.krate == ast::LOCAL_CRATE => {
+ found_nominal = true;
+ }
+ _ => {}
+ }
+ }
_ => { }
}
}
}
-impl<T:Repr> Repr for @T {
+impl<T:Repr + 'static> Repr for Gc<T> {
fn repr(&self, tcx: &ctxt) -> String {
(&**self).repr(tcx)
}
use std::path;
use std::rc::Rc;
+use std::gc::Gc;
pub trait Encoder<E> {
// Primitive types:
}
}
-impl<E, S:Encoder<E>,T:Encodable<S, E>> Encodable<S, E> for @T {
+impl<E, S:Encoder<E>,T:'static + Encodable<S, E>> Encodable<S, E> for Gc<T> {
fn encode(&self, s: &mut S) -> Result<(), E> {
(**self).encode(s)
}
}
}
-impl<E, D:Decoder<E>,T:Decodable<D, E> + 'static> Decodable<D, E> for @T {
- fn decode(d: &mut D) -> Result<@T, E> {
- Ok(@try!(Decodable::decode(d)))
+impl<E, D:Decoder<E>,T:Decodable<D, E> + 'static> Decodable<D, E> for Gc<T> {
+ fn decode(d: &mut D) -> Result<Gc<T>, E> {
+ Ok(box(GC) try!(Decodable::decode(d)))
}
}
#![allow(experimental)]
-use kinds::marker;
use clone::Clone;
+use cmp::{TotalOrd, Ord, Ordering, TotalEq, Eq};
+use default::Default;
+use fmt;
+use hash::Hash;
+use io::Writer;
+use kinds::marker;
+use ops::Deref;
+use raw;
/// Immutable garbage-collected pointer type
#[lang="gc"]
-#[cfg(not(test))]
#[experimental = "Gc is currently based on reference-counting and will not collect cycles until \
task annihilation. For now, cycles need to be broken manually by using `Rc<T>` \
with a non-owning `Weak<T>` pointer. A tracing garbage collector is planned."]
pub struct Gc<T> {
+ #[cfg(stage0)]
ptr: @T,
+ #[cfg(not(stage0))]
+ ptr: *T,
marker: marker::NoSend,
}
-#[cfg(test)]
-pub struct Gc<T> {
- ptr: @T,
- marker: marker::NoSend,
-}
-
-impl<T: 'static> Gc<T> {
- /// Construct a new garbage-collected box
- #[inline]
- pub fn new(value: T) -> Gc<T> {
- Gc { ptr: @value, marker: marker::NoSend }
- }
-
- /// Borrow the value contained in the garbage-collected box
- #[inline]
- pub fn borrow<'r>(&'r self) -> &'r T {
- &*self.ptr
- }
-
- /// Determine if two garbage-collected boxes point to the same object
- #[inline]
- pub fn ptr_eq(&self, other: &Gc<T>) -> bool {
- self.borrow() as *T == other.borrow() as *T
- }
-}
-
-impl<T> Clone for Gc<T> {
+impl<T: 'static> Clone for Gc<T> {
/// Clone the pointer only
#[inline]
- fn clone(&self) -> Gc<T> {
- Gc{ ptr: self.ptr, marker: marker::NoSend }
- }
+ fn clone(&self) -> Gc<T> { *self }
}
/// An value that represents the task-local managed heap.
#[cfg(not(test))]
pub static GC: () = ();
-#[cfg(test)]
-pub static GC: () = ();
+impl<T: Eq + 'static> Eq for Gc<T> {
+ #[inline]
+ fn eq(&self, other: &Gc<T>) -> bool { *(*self) == *(*other) }
+ #[inline]
+ fn ne(&self, other: &Gc<T>) -> bool { *(*self) != *(*other) }
+}
+impl<T: Ord + 'static> Ord for Gc<T> {
+ #[inline]
+ fn lt(&self, other: &Gc<T>) -> bool { *(*self) < *(*other) }
+ #[inline]
+ fn le(&self, other: &Gc<T>) -> bool { *(*self) <= *(*other) }
+ #[inline]
+ fn ge(&self, other: &Gc<T>) -> bool { *(*self) >= *(*other) }
+ #[inline]
+ fn gt(&self, other: &Gc<T>) -> bool { *(*self) > *(*other) }
+}
+impl<T: TotalOrd + 'static> TotalOrd for Gc<T> {
+ #[inline]
+ fn cmp(&self, other: &Gc<T>) -> Ordering { (**self).cmp(&**other) }
+}
+impl<T: TotalEq + 'static> TotalEq for Gc<T> {}
+
+impl<T: 'static> Deref<T> for Gc<T> {
+ #[cfg(stage0)]
+ fn deref<'a>(&'a self) -> &'a T { &*self.ptr }
+ #[cfg(not(stage0))]
+ fn deref<'a>(&'a self) -> &'a T { &**self }
+}
+
+impl<T: Default + 'static> Default for Gc<T> {
+ fn default() -> Gc<T> {
+ box(GC) Default::default()
+ }
+}
+
+impl<T: 'static> raw::Repr<*raw::Box<T>> for Gc<T> {}
+
+impl<S: Writer, T: Hash<S> + 'static> Hash<S> for Gc<T> {
+ fn hash(&self, s: &mut S) {
+ (**self).hash(s)
+ }
+}
+
+impl<T: 'static + fmt::Show> fmt::Show for Gc<T> {
+ fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+ (**self).fmt(f)
+ }
+}
#[cfg(test)]
mod tests {
#[cfg(test)] pub use realstd::ops;
#[cfg(test)] pub use realstd::cmp;
#[cfg(test)] pub use realstd::ty;
+#[cfg(test)] pub use realstd::owned;
+#[cfg(test)] pub use realstd::gc;
// NB: These reexports are in the order they should be listed in rustdoc
pub mod ascii;
+#[cfg(not(test))]
pub mod gc;
/* Common traits */