mirror of https://github.com/rust-lang/rust.git
rustc: Update how Gc<T> is recognized
This commit uses the same trick as ~/Box to map Gc<T> to @T internally inside the compiler. This moves a number of implementations of traits to the `gc` module in the standard library. This removes functions such as `Gc::new`, `Gc::borrow`, and `Gc::ptr_eq` in favor of the more modern equivalents, `box(GC)`, `Deref`, and pointer equality. The Gc pointer itself should be much more useful now, and subsequent commits will move the compiler away from @T towards Gc<T> [breaking-change]
This commit is contained in:
parent
ea41101b35
commit
531ed3d599
|
@ -320,8 +320,8 @@ mod tests {
|
|||
#[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());
|
||||
}
|
||||
|
||||
|
|
|
@ -248,13 +248,6 @@ impl<S: Writer, T: Hash<S>> Hash<S> for Box<T> {
|
|||
}
|
||||
}
|
||||
|
||||
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) {
|
||||
|
|
|
@ -39,12 +39,6 @@ pub trait Clone {
|
|||
}
|
||||
}
|
||||
|
||||
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]
|
||||
|
|
|
@ -326,29 +326,6 @@ mod impls {
|
|||
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)]
|
||||
|
|
|
@ -43,7 +43,3 @@ default_impl!(i64, 0i64)
|
|||
|
||||
default_impl!(f32, 0.0f32)
|
||||
default_impl!(f64, 0.0f64)
|
||||
|
||||
impl<T: Default + 'static> Default for @T {
|
||||
fn default() -> @T { @Default::default() }
|
||||
}
|
||||
|
|
|
@ -628,9 +628,6 @@ pub fn argumentuint<'a>(s: &'a uint) -> Argument<'a> {
|
|||
|
||||
// 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) }
|
||||
}
|
||||
|
|
|
@ -79,7 +79,6 @@ pub trait Repr<T> {
|
|||
|
||||
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)]
|
||||
|
|
|
@ -399,12 +399,20 @@ fn trans_datum_unadjusted<'a>(bcx: &'a Block<'a>,
|
|||
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) => {
|
||||
|
@ -773,11 +781,6 @@ fn trans_rvalue_dps_unadjusted<'a>(bcx: &'a Block<'a>,
|
|||
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,
|
||||
|
@ -1242,31 +1245,6 @@ fn trans_addr_of<'a>(bcx: &'a Block<'a>,
|
|||
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>(
|
||||
|
|
|
@ -18,7 +18,7 @@ use middle::lint;
|
|||
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;
|
||||
|
@ -3108,17 +3108,17 @@ pub fn expr_kind(tcx: &ctxt, expr: &ast::Expr) -> ExprKind {
|
|||
}
|
||||
|
||||
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
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -451,6 +451,53 @@ pub fn ast_ty_to_builtin_ty<AC:AstConv,
|
|||
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
|
||||
}
|
||||
}
|
||||
|
|
|
@ -2862,52 +2862,14 @@ fn check_expr_with_unifier(fcx: &FnCtxt,
|
|||
// 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
|
||||
}
|
||||
}
|
||||
_ => {}
|
||||
|
|
|
@ -129,6 +129,14 @@ fn type_is_defined_in_local_crate(tcx: &ty::ctxt, original_type: t) -> bool {
|
|||
_ => {}
|
||||
}
|
||||
}
|
||||
ty_box(..) => {
|
||||
match tcx.lang_items.gc() {
|
||||
Some(did) if did.krate == ast::LOCAL_CRATE => {
|
||||
found_nominal = true;
|
||||
}
|
||||
_ => {}
|
||||
}
|
||||
}
|
||||
|
||||
_ => { }
|
||||
}
|
||||
|
|
|
@ -510,7 +510,7 @@ impl<T:Repr> Repr for Rc<T> {
|
|||
}
|
||||
}
|
||||
|
||||
impl<T:Repr> Repr for @T {
|
||||
impl<T:Repr + 'static> Repr for Gc<T> {
|
||||
fn repr(&self, tcx: &ctxt) -> String {
|
||||
(&**self).repr(tcx)
|
||||
}
|
||||
|
|
|
@ -16,6 +16,7 @@ Core encoding and decoding interfaces.
|
|||
|
||||
use std::path;
|
||||
use std::rc::Rc;
|
||||
use std::gc::Gc;
|
||||
|
||||
pub trait Encoder<E> {
|
||||
// Primitive types:
|
||||
|
@ -387,7 +388,7 @@ impl<E, D:Decoder<E>,T:Decodable<D, E>> Decodable<D, E> for Box<T> {
|
|||
}
|
||||
}
|
||||
|
||||
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)
|
||||
}
|
||||
|
@ -407,9 +408,9 @@ impl<E, D:Decoder<E>,T:Decodable<D, E>> Decodable<D, E> for Rc<T> {
|
|||
}
|
||||
}
|
||||
|
||||
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)))
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -18,52 +18,33 @@ collector is task-local so `Gc<T>` is not sendable.
|
|||
|
||||
#![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.
|
||||
|
@ -73,8 +54,54 @@ impl<T> Clone for Gc<T> {
|
|||
#[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 {
|
||||
|
|
|
@ -135,6 +135,8 @@ extern crate rustrt;
|
|||
#[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
|
||||
|
@ -219,6 +221,7 @@ pub mod rand;
|
|||
|
||||
pub mod ascii;
|
||||
|
||||
#[cfg(not(test))]
|
||||
pub mod gc;
|
||||
|
||||
/* Common traits */
|
||||
|
|
Loading…
Reference in New Issue