about summary refs log tree commit diff
diff options
context:
space:
mode:
authorOliver Schneider <github35764891676564198441@oli-obk.de>2018-09-07 13:41:59 +0200
committerOliver Schneider <github35764891676564198441@oli-obk.de>2018-09-11 11:19:48 +0200
commitd272e2f6e2e40dadcc68a0f4be5a4145e3d6a006 (patch)
tree2a490237dd51b2ff43408ed09b95afd41039d82b
parent1f02f23263ff03d7f590f19d31741c5d6b08b44f (diff)
downloadrust-d272e2f6e2e40dadcc68a0f4be5a4145e3d6a006.tar.gz
rust-d272e2f6e2e40dadcc68a0f4be5a4145e3d6a006.zip
Get rid of the `non_zero` lang item in favour of arbitrary range specifications
-rw-r--r--src/libcore/nonzero.rs3
-rw-r--r--src/librustc/middle/lang_items.rs2
-rw-r--r--src/librustc/ty/context.rs23
-rw-r--r--src/librustc/ty/layout.rs22
4 files changed, 40 insertions, 10 deletions
diff --git a/src/libcore/nonzero.rs b/src/libcore/nonzero.rs
index cc36ea7f713..6f27d3207bb 100644
--- a/src/libcore/nonzero.rs
+++ b/src/libcore/nonzero.rs
@@ -14,7 +14,8 @@ use ops::CoerceUnsized;
 
 /// A wrapper type for raw pointers and integers that will never be
 /// NULL or 0 that might allow certain optimizations.
-#[lang = "non_zero"]
+#[cfg_attr(stage0, lang = "non_zero")]
+#[cfg_attr(not(stage0), rustc_layout_scalar_range_start(1))]
 #[derive(Copy, Clone, Eq, PartialEq, Ord, PartialOrd, Hash)]
 #[repr(transparent)]
 pub(crate) struct NonZero<T>(pub(crate) T);
diff --git a/src/librustc/middle/lang_items.rs b/src/librustc/middle/lang_items.rs
index d92f856fa4d..bfde4e4a3ae 100644
--- a/src/librustc/middle/lang_items.rs
+++ b/src/librustc/middle/lang_items.rs
@@ -326,8 +326,6 @@ language_item_table! {
 
     PhantomDataItem,                 "phantom_data",            phantom_data;
 
-    NonZeroItem,                     "non_zero",                non_zero;
-
     ManuallyDropItem,                "manually_drop",           manually_drop;
 
     DebugTraitLangItem,              "debug_trait",             debug_trait;
diff --git a/src/librustc/ty/context.rs b/src/librustc/ty/context.rs
index eb6f7140a7d..922308d51fb 100644
--- a/src/librustc/ty/context.rs
+++ b/src/librustc/ty/context.rs
@@ -1083,6 +1083,29 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> {
         interned
     }
 
+    /// Returns a range of the start/end indices specified with the `rustc_layout_scalar_range`
+    /// attribute. Missing range ends may be denoted by `None` and will just use the max/min of
+    /// the type.
+    pub fn layout_scalar_range(self, def_id: DefId) -> Option<(Option<u128>, Option<u128>)> {
+        let attrs = self.get_attrs(def_id);
+        let get = |name| -> Option<u128> {
+            let attr = attrs.iter().find(|a| a.check_name(name))?;
+            for meta in attr.meta_item_list().expect("rustc_layout_scalar_range takes args") {
+                match meta.literal().expect("rustc_layout_scalar_range attribute takes lit").node {
+                    ast::LitKind::Int(a, _) => return Some(a),
+                    _ => span_bug!(attr.span, "rustc_layout_scalar_range expects integer arg"),
+                }
+            }
+            bug!("no arguments to `rustc_layout_scalar_range` attribute");
+        };
+        let start = get("rustc_layout_scalar_range_start");
+        let end = get("rustc_layout_scalar_range_end");
+        if start.is_none() && end.is_none() {
+            return None;
+        }
+        Some((start, end))
+    }
+
     pub fn lift<T: ?Sized + Lift<'tcx>>(self, value: &T) -> Option<T::Lifted> {
         value.lift_to_tcx(self)
     }
diff --git a/src/librustc/ty/layout.rs b/src/librustc/ty/layout.rs
index 17d613a2b18..be9357dd4a7 100644
--- a/src/librustc/ty/layout.rs
+++ b/src/librustc/ty/layout.rs
@@ -761,16 +761,19 @@ impl<'a, 'tcx> LayoutCx<'tcx, TyCtxt<'a, 'tcx, 'tcx>> {
 
                     let mut st = univariant_uninterned(&variants[v], &def.repr, kind)?;
                     st.variants = Variants::Single { index: v };
-                    // Exclude 0 from the range of a newtype ABI NonZero<T>.
-                    if Some(def.did) == self.tcx.lang_items().non_zero() {
+                    if let Some((start, end)) = self.tcx.layout_scalar_range(def.did) {
                         match st.abi {
                             Abi::Scalar(ref mut scalar) |
                             Abi::ScalarPair(ref mut scalar, _) => {
-                                if *scalar.valid_range.start() == 0 {
-                                    scalar.valid_range = 1..=*scalar.valid_range.end();
-                                }
+                                let start = start.unwrap_or(*scalar.valid_range.start());
+                                let end = end.unwrap_or(*scalar.valid_range.end());
+                                scalar.valid_range = start..=end;
                             }
-                            _ => {}
+                            _ => bug!(
+                                "nonscalar layout for rustc_layout_scalar_range type {:?}: {:#?}",
+                                def,
+                                st,
+                            ),
                         }
                     }
                     return Ok(tcx.intern_layout(st));
@@ -1351,7 +1354,12 @@ impl<'a, 'tcx> SizeSkeleton<'tcx> {
                     if let Some(SizeSkeleton::Pointer { non_zero, tail }) = v0 {
                         return Ok(SizeSkeleton::Pointer {
                             non_zero: non_zero ||
-                                Some(def.did) == tcx.lang_items().non_zero(),
+                                tcx.layout_scalar_range(def.did).map_or(false, |(start, end)| {
+                                    // `n..` for `n > 0` or `n..m` for `n > 0 && m > n`
+                                    start.map_or(true, |start| start > 0 && end.map_or(true, |end| {
+                                        end > start
+                                    }))
+                                }),
                             tail,
                         });
                     } else {