about summary refs log tree commit diff
diff options
context:
space:
mode:
authorDavid Wood <david@davidtw.co>2018-09-30 21:19:55 +0200
committerDavid Wood <david@davidtw.co>2018-10-01 13:50:21 +0200
commitda4a12038bac647b8d07211588c21f1ca07c12e3 (patch)
treee739f669e9665a433a53a16f9062e325450cff3f
parent1886d5fe1cdd1a016ecea9fc93d68b3052c528c8 (diff)
Introduce language items for `Arc` and `Rc`.
This commit introduces language items for `Arc` and `Rc` so that types
can later be checked to be `Arc` or `Rc` in the NLL borrow checker. The
`lang` attribute is currently limited to `stage1` as it requires a
compiler built with knowledge of the expected language items.
-rw-r--r--src/doc/unstable-book/src/language-features/lang-items.md2
-rw-r--r--src/liballoc/rc.rs1
-rw-r--r--src/liballoc/sync.rs1
-rw-r--r--src/librustc/middle/lang_items.rs3
-rw-r--r--src/librustc/ty/mod.rs22
-rw-r--r--src/librustc/ty/sty.rs16
6 files changed, 44 insertions, 1 deletions
diff --git a/src/doc/unstable-book/src/language-features/lang-items.md b/src/doc/unstable-book/src/language-features/lang-items.md
index bac619fd4a3..b16739b4743 100644
--- a/src/doc/unstable-book/src/language-features/lang-items.md
+++ b/src/doc/unstable-book/src/language-features/lang-items.md
@@ -311,3 +311,5 @@ the source code.
   - `freeze`: `libcore/marker.rs`
   - `debug_trait`: `libcore/fmt/mod.rs`
   - `non_zero`: `libcore/nonzero.rs`
+  - `arc`: `liballoc/sync.rs`
+  - `rc`: `liballoc/rc.rs`
diff --git a/src/liballoc/rc.rs b/src/liballoc/rc.rs
index 9d951691a34..915b8e7787e 100644
--- a/src/liballoc/rc.rs
+++ b/src/liballoc/rc.rs
@@ -282,6 +282,7 @@ struct RcBox<T: ?Sized> {
 /// type `T`.
 ///
 /// [get_mut]: #method.get_mut
+#[cfg_attr(all(not(stage0), not(test)), lang = "rc")]
 #[stable(feature = "rust1", since = "1.0.0")]
 pub struct Rc<T: ?Sized> {
     ptr: NonNull<RcBox<T>>,
diff --git a/src/liballoc/sync.rs b/src/liballoc/sync.rs
index 116393bdad1..9e245fbd7bb 100644
--- a/src/liballoc/sync.rs
+++ b/src/liballoc/sync.rs
@@ -199,6 +199,7 @@ const MAX_REFCOUNT: usize = (isize::MAX) as usize;
 /// counting in general.
 ///
 /// [rc_examples]: ../../std/rc/index.html#examples
+#[cfg_attr(all(not(stage0), not(test)), lang = "arc")]
 #[stable(feature = "rust1", since = "1.0.0")]
 pub struct Arc<T: ?Sized> {
     ptr: NonNull<ArcInner<T>>,
diff --git a/src/librustc/middle/lang_items.rs b/src/librustc/middle/lang_items.rs
index bfde4e4a3ae..ef70a4cc45d 100644
--- a/src/librustc/middle/lang_items.rs
+++ b/src/librustc/middle/lang_items.rs
@@ -362,6 +362,9 @@ language_item_table! {
     AlignOffsetLangItem,             "align_offset",            align_offset_fn;
 
     TerminationTraitLangItem,        "termination",             termination;
+
+    Arc,                             "arc",                     arc;
+    Rc,                              "rc",                      rc;
 }
 
 impl<'a, 'tcx, 'gcx> TyCtxt<'a, 'tcx, 'gcx> {
diff --git a/src/librustc/ty/mod.rs b/src/librustc/ty/mod.rs
index b2281691bd6..633551aed18 100644
--- a/src/librustc/ty/mod.rs
+++ b/src/librustc/ty/mod.rs
@@ -1694,9 +1694,13 @@ bitflags! {
         const IS_FUNDAMENTAL      = 1 << 2;
         const IS_UNION            = 1 << 3;
         const IS_BOX              = 1 << 4;
+        /// Indicates whether the type is an `Arc`.
+        const IS_ARC              = 1 << 5;
+        /// Indicates whether the type is an `Rc`.
+        const IS_RC               = 1 << 6;
         /// Indicates whether the variant list of this ADT is `#[non_exhaustive]`.
         /// (i.e., this flag is never set unless this ADT is an enum).
-        const IS_VARIANT_LIST_NON_EXHAUSTIVE   = 1 << 5;
+        const IS_VARIANT_LIST_NON_EXHAUSTIVE   = 1 << 7;
     }
 }
 
@@ -2016,6 +2020,12 @@ impl<'a, 'gcx, 'tcx> AdtDef {
         if Some(did) == tcx.lang_items().owned_box() {
             flags = flags | AdtFlags::IS_BOX;
         }
+        if Some(did) == tcx.lang_items().arc() {
+            flags = flags | AdtFlags::IS_ARC;
+        }
+        if Some(did) == tcx.lang_items().rc() {
+            flags = flags | AdtFlags::IS_RC;
+        }
         if kind == AdtKind::Enum && tcx.has_attr(did, "non_exhaustive") {
             debug!("found non-exhaustive variant list for {:?}", did);
             flags = flags | AdtFlags::IS_VARIANT_LIST_NON_EXHAUSTIVE;
@@ -2094,6 +2104,16 @@ impl<'a, 'gcx, 'tcx> AdtDef {
         self.flags.intersects(AdtFlags::IS_PHANTOM_DATA)
     }
 
+    /// Returns `true` if this is `Arc<T>`.
+    pub fn is_arc(&self) -> bool {
+        self.flags.intersects(AdtFlags::IS_ARC)
+    }
+
+    /// Returns `true` if this is `Rc<T>`.
+    pub fn is_rc(&self) -> bool {
+        self.flags.intersects(AdtFlags::IS_RC)
+    }
+
     /// Returns true if this is Box<T>.
     #[inline]
     pub fn is_box(&self) -> bool {
diff --git a/src/librustc/ty/sty.rs b/src/librustc/ty/sty.rs
index 6c40dd89239..4f80bf45ab1 100644
--- a/src/librustc/ty/sty.rs
+++ b/src/librustc/ty/sty.rs
@@ -1598,6 +1598,22 @@ impl<'a, 'gcx, 'tcx> TyS<'tcx> {
         }
     }
 
+    /// Returns `true` if this type is an `Arc<T>`.
+    pub fn is_arc(&self) -> bool {
+        match self.sty {
+            Adt(def, _) => def.is_arc(),
+            _ => false,
+        }
+    }
+
+    /// Returns `true` if this type is an `Rc<T>`.
+    pub fn is_rc(&self) -> bool {
+        match self.sty {
+            Adt(def, _) => def.is_rc(),
+            _ => false,
+        }
+    }
+
     pub fn is_box(&self) -> bool {
         match self.sty {
             Adt(def, _) => def.is_box(),