Get rid of the non_zero
lang item in favour of arbitrary range specifications
This commit is contained in:
parent
1f02f23263
commit
d272e2f6e2
4 changed files with 40 additions and 10 deletions
|
@ -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);
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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)
|
||||
}
|
||||
|
|
|
@ -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 {
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue