Skip to content

Commit d272e2f

Browse files
committed
Get rid of the non_zero lang item in favour of arbitrary range specifications
1 parent 1f02f23 commit d272e2f

File tree

4 files changed

+40
-10
lines changed

4 files changed

+40
-10
lines changed

src/libcore/nonzero.rs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,8 @@ use ops::CoerceUnsized;
1414

1515
/// A wrapper type for raw pointers and integers that will never be
1616
/// NULL or 0 that might allow certain optimizations.
17-
#[lang = "non_zero"]
17+
#[cfg_attr(stage0, lang = "non_zero")]
18+
#[cfg_attr(not(stage0), rustc_layout_scalar_range_start(1))]
1819
#[derive(Copy, Clone, Eq, PartialEq, Ord, PartialOrd, Hash)]
1920
#[repr(transparent)]
2021
pub(crate) struct NonZero<T>(pub(crate) T);

src/librustc/middle/lang_items.rs

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -326,8 +326,6 @@ language_item_table! {
326326

327327
PhantomDataItem, "phantom_data", phantom_data;
328328

329-
NonZeroItem, "non_zero", non_zero;
330-
331329
ManuallyDropItem, "manually_drop", manually_drop;
332330

333331
DebugTraitLangItem, "debug_trait", debug_trait;

src/librustc/ty/context.rs

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1083,6 +1083,29 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> {
10831083
interned
10841084
}
10851085

1086+
/// Returns a range of the start/end indices specified with the `rustc_layout_scalar_range`
1087+
/// attribute. Missing range ends may be denoted by `None` and will just use the max/min of
1088+
/// the type.
1089+
pub fn layout_scalar_range(self, def_id: DefId) -> Option<(Option<u128>, Option<u128>)> {
1090+
let attrs = self.get_attrs(def_id);
1091+
let get = |name| -> Option<u128> {
1092+
let attr = attrs.iter().find(|a| a.check_name(name))?;
1093+
for meta in attr.meta_item_list().expect("rustc_layout_scalar_range takes args") {
1094+
match meta.literal().expect("rustc_layout_scalar_range attribute takes lit").node {
1095+
ast::LitKind::Int(a, _) => return Some(a),
1096+
_ => span_bug!(attr.span, "rustc_layout_scalar_range expects integer arg"),
1097+
}
1098+
}
1099+
bug!("no arguments to `rustc_layout_scalar_range` attribute");
1100+
};
1101+
let start = get("rustc_layout_scalar_range_start");
1102+
let end = get("rustc_layout_scalar_range_end");
1103+
if start.is_none() && end.is_none() {
1104+
return None;
1105+
}
1106+
Some((start, end))
1107+
}
1108+
10861109
pub fn lift<T: ?Sized + Lift<'tcx>>(self, value: &T) -> Option<T::Lifted> {
10871110
value.lift_to_tcx(self)
10881111
}

src/librustc/ty/layout.rs

Lines changed: 15 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -761,16 +761,19 @@ impl<'a, 'tcx> LayoutCx<'tcx, TyCtxt<'a, 'tcx, 'tcx>> {
761761

762762
let mut st = univariant_uninterned(&variants[v], &def.repr, kind)?;
763763
st.variants = Variants::Single { index: v };
764-
// Exclude 0 from the range of a newtype ABI NonZero<T>.
765-
if Some(def.did) == self.tcx.lang_items().non_zero() {
764+
if let Some((start, end)) = self.tcx.layout_scalar_range(def.did) {
766765
match st.abi {
767766
Abi::Scalar(ref mut scalar) |
768767
Abi::ScalarPair(ref mut scalar, _) => {
769-
if *scalar.valid_range.start() == 0 {
770-
scalar.valid_range = 1..=*scalar.valid_range.end();
771-
}
768+
let start = start.unwrap_or(*scalar.valid_range.start());
769+
let end = end.unwrap_or(*scalar.valid_range.end());
770+
scalar.valid_range = start..=end;
772771
}
773-
_ => {}
772+
_ => bug!(
773+
"nonscalar layout for rustc_layout_scalar_range type {:?}: {:#?}",
774+
def,
775+
st,
776+
),
774777
}
775778
}
776779
return Ok(tcx.intern_layout(st));
@@ -1351,7 +1354,12 @@ impl<'a, 'tcx> SizeSkeleton<'tcx> {
13511354
if let Some(SizeSkeleton::Pointer { non_zero, tail }) = v0 {
13521355
return Ok(SizeSkeleton::Pointer {
13531356
non_zero: non_zero ||
1354-
Some(def.did) == tcx.lang_items().non_zero(),
1357+
tcx.layout_scalar_range(def.did).map_or(false, |(start, end)| {
1358+
// `n..` for `n > 0` or `n..m` for `n > 0 && m > n`
1359+
start.map_or(true, |start| start > 0 && end.map_or(true, |end| {
1360+
end > start
1361+
}))
1362+
}),
13551363
tail,
13561364
});
13571365
} else {

0 commit comments

Comments
 (0)