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
|
/// A wrapper type for raw pointers and integers that will never be
|
||||||
/// NULL or 0 that might allow certain optimizations.
|
/// 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)]
|
#[derive(Copy, Clone, Eq, PartialEq, Ord, PartialOrd, Hash)]
|
||||||
#[repr(transparent)]
|
#[repr(transparent)]
|
||||||
pub(crate) struct NonZero<T>(pub(crate) T);
|
pub(crate) struct NonZero<T>(pub(crate) T);
|
||||||
|
|
|
@ -326,8 +326,6 @@ language_item_table! {
|
||||||
|
|
||||||
PhantomDataItem, "phantom_data", phantom_data;
|
PhantomDataItem, "phantom_data", phantom_data;
|
||||||
|
|
||||||
NonZeroItem, "non_zero", non_zero;
|
|
||||||
|
|
||||||
ManuallyDropItem, "manually_drop", manually_drop;
|
ManuallyDropItem, "manually_drop", manually_drop;
|
||||||
|
|
||||||
DebugTraitLangItem, "debug_trait", debug_trait;
|
DebugTraitLangItem, "debug_trait", debug_trait;
|
||||||
|
|
|
@ -1083,6 +1083,29 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> {
|
||||||
interned
|
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> {
|
pub fn lift<T: ?Sized + Lift<'tcx>>(self, value: &T) -> Option<T::Lifted> {
|
||||||
value.lift_to_tcx(self)
|
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)?;
|
let mut st = univariant_uninterned(&variants[v], &def.repr, kind)?;
|
||||||
st.variants = Variants::Single { index: v };
|
st.variants = Variants::Single { index: v };
|
||||||
// Exclude 0 from the range of a newtype ABI NonZero<T>.
|
if let Some((start, end)) = self.tcx.layout_scalar_range(def.did) {
|
||||||
if Some(def.did) == self.tcx.lang_items().non_zero() {
|
|
||||||
match st.abi {
|
match st.abi {
|
||||||
Abi::Scalar(ref mut scalar) |
|
Abi::Scalar(ref mut scalar) |
|
||||||
Abi::ScalarPair(ref mut scalar, _) => {
|
Abi::ScalarPair(ref mut scalar, _) => {
|
||||||
if *scalar.valid_range.start() == 0 {
|
let start = start.unwrap_or(*scalar.valid_range.start());
|
||||||
scalar.valid_range = 1..=*scalar.valid_range.end();
|
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));
|
return Ok(tcx.intern_layout(st));
|
||||||
|
@ -1351,7 +1354,12 @@ impl<'a, 'tcx> SizeSkeleton<'tcx> {
|
||||||
if let Some(SizeSkeleton::Pointer { non_zero, tail }) = v0 {
|
if let Some(SizeSkeleton::Pointer { non_zero, tail }) = v0 {
|
||||||
return Ok(SizeSkeleton::Pointer {
|
return Ok(SizeSkeleton::Pointer {
|
||||||
non_zero: non_zero ||
|
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,
|
tail,
|
||||||
});
|
});
|
||||||
} else {
|
} else {
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue