]> git.lizzy.rs Git - rust.git/commitdiff
Get rid of the `non_zero` lang item in favour of arbitrary range specifications
authorOliver Schneider <github35764891676564198441@oli-obk.de>
Fri, 7 Sep 2018 11:41:59 +0000 (13:41 +0200)
committerOliver Schneider <github35764891676564198441@oli-obk.de>
Tue, 11 Sep 2018 09:19:48 +0000 (11:19 +0200)
src/libcore/nonzero.rs
src/librustc/middle/lang_items.rs
src/librustc/ty/context.rs
src/librustc/ty/layout.rs

index cc36ea7f71391ed99f9eabf697c9475c97b126bd..6f27d3207bb7ab841c967538016e389837554070 100644 (file)
@@ -14,7 +14,8 @@
 
 /// 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);
index d92f856fa4dbff90445e78b1276bd011d5255b9b..bfde4e4a3aed8abb8d94d85aa8381f15908f1633 100644 (file)
@@ -326,8 +326,6 @@ pub fn collect<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>) -> LanguageItems {
 
     PhantomDataItem,                 "phantom_data",            phantom_data;
 
-    NonZeroItem,                     "non_zero",                non_zero;
-
     ManuallyDropItem,                "manually_drop",           manually_drop;
 
     DebugTraitLangItem,              "debug_trait",             debug_trait;
index eb6f7140a7db79692d6d526a0ee4161abea86398..922308d51fb763e3000f68595225123271cddd32 100644 (file)
@@ -1083,6 +1083,29 @@ pub fn intern_layout(self, layout: LayoutDetails) -> &'gcx LayoutDetails {
         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)
     }
index 17d613a2b181a14fb685d30c232ea4127a25af15..be9357dd4a7cf8e130f704232dbbd412234e50b4 100644 (file)
@@ -761,16 +761,19 @@ enum StructKind {
 
                     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 @@ pub fn compute(ty: Ty<'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 {