]> git.lizzy.rs Git - rust.git/commitdiff
rustc: Update how Gc<T> is recognized
authorAlex Crichton <alex@alexcrichton.com>
Fri, 16 May 2014 01:18:00 +0000 (18:18 -0700)
committerAlex Crichton <alex@alexcrichton.com>
Wed, 11 Jun 2014 16:11:40 +0000 (09:11 -0700)
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]

16 files changed:
src/liballoc/rc.rs
src/libcollections/hash/mod.rs
src/libcore/clone.rs
src/libcore/cmp.rs
src/libcore/default.rs
src/libcore/fmt/mod.rs
src/libcore/raw.rs
src/librustc/middle/trans/expr.rs
src/librustc/middle/ty.rs
src/librustc/middle/typeck/astconv.rs
src/librustc/middle/typeck/check/mod.rs
src/librustc/middle/typeck/coherence.rs
src/librustc/util/ppaux.rs
src/libserialize/serialize.rs
src/libstd/gc.rs
src/libstd/lib.rs

index 416a6ad2d8b7a3d5a8c064909fce9b76d2e1c9c1..8b28ab917b35f1e576f0a1647545475804c36495 100644 (file)
@@ -320,8 +320,8 @@ fn test_dead() {
     #[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());
     }
 
index 4220c0b5559b35f7d588255e4791a729ff7cf0f3..b484b2c8128f13f7b903ace57837b8d3a55e3aef 100644 (file)
@@ -248,13 +248,6 @@ fn hash(&self, state: &mut S) {
     }
 }
 
-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) {
index c7befe2f4b1e0a64d23bd7c162577b79f067ef7e..b552cb511305fcf1dc362532e772d4c8600c082f 100644 (file)
@@ -39,12 +39,6 @@ fn clone_from(&mut self, source: &Self) {
     }
 }
 
-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]
index b25f69bca40b8f361e080b7b65221033d9a979c4..d7a3edccfd822115c5f9ec55f8466061fb5ab285 100644 (file)
@@ -326,29 +326,6 @@ impl<'a, T: Ord> Ord for &'a mut T {
         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)]
index 809706b4fd73be962a7d8fffd2eac688e0b930a6..0fcc02aae0d2b31619294a81749bda2b7e6be261 100644 (file)
@@ -43,7 +43,3 @@ fn default() -> $t { $v }
 
 default_impl!(f32, 0.0f32)
 default_impl!(f64, 0.0f64)
-
-impl<T: Default + 'static> Default for @T {
-    fn default() -> @T { @Default::default() }
-}
index 91fd183d8c3ac76c03403bc684773d4405e2b67f..0e6a0d1c6f5770c24ea44aab36f716ca236f1198 100644 (file)
@@ -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) }
 }
index 979eeb657b6a62609ac1d7e000a12e8b72129fe4..56db4ee8059fab8596cda3a784f6e1489e8f6dae 100644 (file)
@@ -79,7 +79,6 @@ fn repr(&self) -> T { unsafe { mem::transmute_copy(self) } }
 
 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)]
index b21877e4fa030f56c6348e14d6714da110889c7f..19ce88d3d856f1983ae783ad17735da1aa06ca76 100644 (file)
@@ -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>(
index 6275abdc8ab209a893742e8a0dd017833e535b75..e905e4f4cb3b7c00123d3eb63d48ad884e6e16d1 100644 (file)
@@ -18,7 +18,7 @@
 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
             }
         }
 
index 1e6f5fe870be321b74df6f78cf03f976afef45a0..f2b94771a7f462d3ab3b5e20115240ffc5341d35 100644 (file)
@@ -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
             }
         }
index be19c2ef19953a9da32b50258738b23d80b1adba..8398b46437d26d020a15f268b6c953ab6740791d 100644 (file)
@@ -2862,52 +2862,14 @@ fn check_struct_enum_variant(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
                   }
               }
               _ => {}
index 2c0593184786e961ec20fad955d4df55666a92db..fdc279394e4b949ea38b6bec5a12385fc994cc39 100644 (file)
@@ -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;
+                    }
+                    _ => {}
+                }
+            }
 
             _ => { }
         }
index eb84ed32335b95ba7b09667dda38eaa5d01b86ee..fcf4d21a96233db9b57fbdf87da7008e5a23d1b6 100644 (file)
@@ -510,7 +510,7 @@ fn repr(&self, tcx: &ctxt) -> String {
     }
 }
 
-impl<T:Repr> Repr for @T {
+impl<T:Repr + 'static> Repr for Gc<T> {
     fn repr(&self, tcx: &ctxt) -> String {
         (&**self).repr(tcx)
     }
index 9252ac55d24e59a630577f495309112b082115e4..d4987bd0afe0bb362911c9b31ee8c6efe8a8fb8c 100644 (file)
@@ -16,6 +16,7 @@
 
 use std::path;
 use std::rc::Rc;
+use std::gc::Gc;
 
 pub trait Encoder<E> {
     // Primitive types:
@@ -387,7 +388,7 @@ fn decode(d: &mut D) -> Result<Box<T>, E> {
     }
 }
 
-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 @@ fn decode(d: &mut D) -> Result<Rc<T>, E> {
     }
 }
 
-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)))
     }
 }
 
index 9260d8d7ab2be2ad07827ef5cb8a6e0e8b34bc79..7988735e80fdff3b648b76e926ee2ccd877ee512 100644 (file)
 
 #![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 @@ fn clone(&self) -> 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 {
index e147997334ccc4259296366d347a96c18824c427..318410c45c1fe9902db72da2cbb29b65e5b3c3ee 100644 (file)
 #[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 @@ fn start(argc: int, argv: **u8) -> int {
 
 pub mod ascii;
 
+#[cfg(not(test))]
 pub mod gc;
 
 /* Common traits */