Skip to content

Commit 11d88ee

Browse files
committed
Rip out rustc_layout_scalar_valid_range_* attribute support
1 parent 8882bf0 commit 11d88ee

76 files changed

Lines changed: 377 additions & 1376 deletions

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

compiler/rustc_abi/src/layout.rs

Lines changed: 1 addition & 50 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
use std::collections::BTreeSet;
22
use std::fmt::{self, Write};
3-
use std::ops::{Bound, Deref};
3+
use std::ops::Deref;
44
use std::{cmp, iter};
55

66
use rustc_hashes::Hash64;
@@ -348,7 +348,6 @@ impl<Cx: HasDataLayout> LayoutCalculator<Cx> {
348348
variants: &IndexSlice<VariantIdx, IndexVec<FieldIdx, F>>,
349349
is_enum: bool,
350350
is_special_no_niche: bool,
351-
scalar_valid_range: (Bound<u128>, Bound<u128>),
352351
discr_range_of_repr: impl Fn(i128, i128) -> (Integer, bool),
353352
discriminants: impl Iterator<Item = (VariantIdx, i128)>,
354353
always_sized: bool,
@@ -380,7 +379,6 @@ impl<Cx: HasDataLayout> LayoutCalculator<Cx> {
380379
variants,
381380
is_enum,
382381
is_special_no_niche,
383-
scalar_valid_range,
384382
always_sized,
385383
present_first,
386384
)
@@ -530,7 +528,6 @@ impl<Cx: HasDataLayout> LayoutCalculator<Cx> {
530528
variants: &IndexSlice<VariantIdx, IndexVec<FieldIdx, F>>,
531529
is_enum: bool,
532530
is_special_no_niche: bool,
533-
scalar_valid_range: (Bound<u128>, Bound<u128>),
534531
always_sized: bool,
535532
present_first: VariantIdx,
536533
) -> LayoutCalculatorResult<FieldIdx, VariantIdx, F> {
@@ -570,52 +567,6 @@ impl<Cx: HasDataLayout> LayoutCalculator<Cx> {
570567
return Ok(st);
571568
}
572569

573-
let (start, end) = scalar_valid_range;
574-
match st.backend_repr {
575-
BackendRepr::Scalar(ref mut scalar) | BackendRepr::ScalarPair(ref mut scalar, _) => {
576-
// Enlarging validity ranges would result in missed
577-
// optimizations, *not* wrongly assuming the inner
578-
// value is valid. e.g. unions already enlarge validity ranges,
579-
// because the values may be uninitialized.
580-
//
581-
// Because of that we only check that the start and end
582-
// of the range is representable with this scalar type.
583-
584-
let max_value = scalar.size(dl).unsigned_int_max();
585-
if let Bound::Included(start) = start {
586-
// FIXME(eddyb) this might be incorrect - it doesn't
587-
// account for wrap-around (end < start) ranges.
588-
assert!(start <= max_value, "{start} > {max_value}");
589-
scalar.valid_range_mut().start = start;
590-
}
591-
if let Bound::Included(end) = end {
592-
// FIXME(eddyb) this might be incorrect - it doesn't
593-
// account for wrap-around (end < start) ranges.
594-
assert!(end <= max_value, "{end} > {max_value}");
595-
scalar.valid_range_mut().end = end;
596-
}
597-
598-
// Update `largest_niche` if we have introduced a larger niche.
599-
let niche = Niche::from_scalar(dl, Size::ZERO, *scalar);
600-
if let Some(niche) = niche {
601-
match st.largest_niche {
602-
Some(largest_niche) => {
603-
// Replace the existing niche even if they're equal,
604-
// because this one is at a lower offset.
605-
if largest_niche.available(dl) <= niche.available(dl) {
606-
st.largest_niche = Some(niche);
607-
}
608-
}
609-
None => st.largest_niche = Some(niche),
610-
}
611-
}
612-
}
613-
_ => assert!(
614-
start == Bound::Unbounded && end == Bound::Unbounded,
615-
"nonscalar layout for layout_scalar_valid_range type: {st:#?}",
616-
),
617-
}
618-
619570
Ok(st)
620571
}
621572

compiler/rustc_attr_parsing/src/attributes/rustc_internal.rs

Lines changed: 0 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -92,32 +92,6 @@ impl NoArgsAttributeParser for RustcNoImplicitAutorefsParser {
9292
const CREATE: fn(Span) -> AttributeKind = |_| AttributeKind::RustcNoImplicitAutorefs;
9393
}
9494

95-
pub(crate) struct RustcLayoutScalarValidRangeStartParser;
96-
97-
impl SingleAttributeParser for RustcLayoutScalarValidRangeStartParser {
98-
const PATH: &[Symbol] = &[sym::rustc_layout_scalar_valid_range_start];
99-
const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::AllowList(&[Allow(Target::Struct)]);
100-
const TEMPLATE: AttributeTemplate = template!(List: &["start"]);
101-
102-
fn convert(cx: &mut AcceptContext<'_, '_>, args: &ArgParser) -> Option<AttributeKind> {
103-
parse_single_integer(cx, args)
104-
.map(|n| AttributeKind::RustcLayoutScalarValidRangeStart(Box::new(n), cx.attr_span))
105-
}
106-
}
107-
108-
pub(crate) struct RustcLayoutScalarValidRangeEndParser;
109-
110-
impl SingleAttributeParser for RustcLayoutScalarValidRangeEndParser {
111-
const PATH: &[Symbol] = &[sym::rustc_layout_scalar_valid_range_end];
112-
const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::AllowList(&[Allow(Target::Struct)]);
113-
const TEMPLATE: AttributeTemplate = template!(List: &["end"]);
114-
115-
fn convert(cx: &mut AcceptContext<'_, '_>, args: &ArgParser) -> Option<AttributeKind> {
116-
parse_single_integer(cx, args)
117-
.map(|n| AttributeKind::RustcLayoutScalarValidRangeEnd(Box::new(n), cx.attr_span))
118-
}
119-
}
120-
12195
pub(crate) struct RustcLegacyConstGenericsParser;
12296

12397
impl SingleAttributeParser for RustcLegacyConstGenericsParser {

compiler/rustc_attr_parsing/src/attributes/util.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,7 @@ pub fn is_builtin_attr(attr: &ast::Attribute) -> bool {
3333
/// Parse a single integer.
3434
///
3535
/// Used by attributes that take a single integer as argument, such as
36-
/// `#[link_ordinal]` and `#[rustc_layout_scalar_valid_range_start]`.
36+
/// `#[link_ordinal]`.
3737
/// `cx` is the context given to the attribute.
3838
/// `args` is the parser for the attribute arguments.
3939
pub(crate) fn parse_single_integer(

compiler/rustc_attr_parsing/src/context.rs

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -208,8 +208,6 @@ attribute_parsers!(
208208
Single<RustcDumpSymbolNameParser>,
209209
Single<RustcForceInlineParser>,
210210
Single<RustcIfThisChangedParser>,
211-
Single<RustcLayoutScalarValidRangeEndParser>,
212-
Single<RustcLayoutScalarValidRangeStartParser>,
213211
Single<RustcLegacyConstGenericsParser>,
214212
Single<RustcLintOptDenyFieldAccessParser>,
215213
Single<RustcMacroTransparencyParser>,

compiler/rustc_const_eval/src/interpret/validity.rs

Lines changed: 66 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -1492,7 +1492,7 @@ impl<'rt, 'tcx, M: Machine<'tcx>> ValueVisitor<'tcx, M> for ValidityVisitor<'rt,
14921492
// First check that the base type is valid
14931493
self.visit_value(&val.transmute(self.ecx.layout_of(*base)?, self.ecx)?)?;
14941494
// When you extend this match, make sure to also add tests to
1495-
// tests/ui/type/pattern_types/validity.rs((
1495+
// tests/ui/type/pattern_types/validity.rs
14961496
match **pat {
14971497
// Range and non-null patterns are precisely reflected into `valid_range` and thus
14981498
// handled fully by `visit_scalar` (called below).
@@ -1507,6 +1507,34 @@ impl<'rt, 'tcx, M: Machine<'tcx>> ValueVisitor<'tcx, M> for ValidityVisitor<'rt,
15071507
// we won't see optimizations actually breaking such programs.
15081508
ty::PatternKind::Or(_patterns) => {}
15091509
}
1510+
// FIXME(pattern_types): handle everything based on the pattern, not on the layout.
1511+
// it's ok to run scalar validation even if the pattern type is `u8 is 0..=255` and thus
1512+
// allows uninit values, because that's rare and so not a perf issue.
1513+
match val.layout.backend_repr {
1514+
BackendRepr::Scalar(scalar_layout) => {
1515+
if !scalar_layout.is_uninit_valid() {
1516+
// There is something to check here.
1517+
// We read directly via `ecx` since the read cannot fail -- we already read
1518+
// this field above when recursing into the field.
1519+
let scalar = self.ecx.read_scalar(val)?;
1520+
self.visit_scalar(scalar, scalar_layout)?;
1521+
}
1522+
}
1523+
BackendRepr::ScalarPair(a_layout, b_layout) => {
1524+
// We can only proceed if *both* scalars need to be initialized.
1525+
// FIXME: find a way to also check ScalarPair when one side can be uninit but
1526+
// the other must be init.
1527+
if !a_layout.is_uninit_valid() && !b_layout.is_uninit_valid() {
1528+
// We read directly via `ecx` since the read cannot fail -- we already read
1529+
// this field above when recursing into the field.
1530+
let (a, b) = self.ecx.read_immediate(val)?.to_scalar_pair();
1531+
self.visit_scalar(a, a_layout)?;
1532+
self.visit_scalar(b, b_layout)?;
1533+
}
1534+
}
1535+
BackendRepr::SimdVector { .. } | BackendRepr::SimdScalableVector { .. } => unreachable!(),
1536+
BackendRepr::Memory { .. } => unreachable!()
1537+
}
15101538
}
15111539
ty::Adt(adt, _) if adt.is_maybe_dangling() => {
15121540
let old_may_dangle = mem::replace(&mut self.may_dangle, true);
@@ -1529,51 +1557,55 @@ impl<'rt, 'tcx, M: Machine<'tcx>> ValueVisitor<'tcx, M> for ValidityVisitor<'rt,
15291557
}
15301558
}
15311559

1532-
// *After* all of this, check further information stored in the layout. We need to check
1533-
// this to handle types like `NonNull` where the `Scalar` info is more restrictive than what
1534-
// the fields say (`rustc_layout_scalar_valid_range_start`). But in most cases, this will
1535-
// just propagate what the fields say, and then we want the error to point at the field --
1536-
// so, we first recurse, then we do this check.
1560+
// *After* all of this, check further information stored in the layout.
1561+
// On leaf types like `!` or empty enums, this will raise the error.
1562+
// This means that for types wrapping such a type, we won't ever get here, but it's
1563+
// just the simplest way to check for this case.
15371564
//
15381565
// FIXME: We could avoid some redundant checks here. For newtypes wrapping
15391566
// scalars, we do the same check on every "level" (e.g., first we check
1540-
// MyNewtype and then the scalar in there).
1567+
// the fields of MyNewtype, and then we check MyNewType again).
15411568
if val.layout.is_uninhabited() {
15421569
let ty = val.layout.ty;
15431570
throw_validation_failure!(
15441571
self.path,
15451572
format!("encountered a value of uninhabited type `{ty}`")
15461573
);
15471574
}
1548-
match val.layout.backend_repr {
1549-
BackendRepr::Scalar(scalar_layout) => {
1550-
if !scalar_layout.is_uninit_valid() {
1551-
// There is something to check here.
1552-
// We read directly via `ecx` since the read cannot fail -- we already read
1553-
// this field above when recursing into the field.
1554-
let scalar = self.ecx.read_scalar(val)?;
1555-
self.visit_scalar(scalar, scalar_layout)?;
1575+
if cfg!(debug_assertions) {
1576+
// Check that we don't miss any new changes to layout computation in our checks above.
1577+
match val.layout.backend_repr {
1578+
BackendRepr::Scalar(scalar_layout) => {
1579+
if !scalar_layout.is_uninit_valid() {
1580+
// There is something to check here.
1581+
// We read directly via `ecx` since the read cannot fail -- we already read
1582+
// this field above when recursing into the field.
1583+
let scalar = self
1584+
.ecx
1585+
.read_scalar(val)
1586+
.expect("the above checks should have fully handled this situation");
1587+
self.visit_scalar(scalar, scalar_layout)
1588+
.expect("the above checks should have fully handled this situation");
1589+
}
15561590
}
1557-
}
1558-
BackendRepr::ScalarPair(a_layout, b_layout) => {
1559-
// We can only proceed if *both* scalars need to be initialized.
1560-
// FIXME: find a way to also check ScalarPair when one side can be uninit but
1561-
// the other must be init.
1562-
if !a_layout.is_uninit_valid() && !b_layout.is_uninit_valid() {
1563-
// We read directly via `ecx` since the read cannot fail -- we already read
1564-
// this field above when recursing into the field.
1565-
let (a, b) = self.ecx.read_immediate(val)?.to_scalar_pair();
1566-
self.visit_scalar(a, a_layout)?;
1567-
self.visit_scalar(b, b_layout)?;
1591+
BackendRepr::ScalarPair(a_layout, b_layout) => {
1592+
// We can only proceed if *both* scalars need to be initialized.
1593+
// FIXME: find a way to also check ScalarPair when one side can be uninit but
1594+
// the other must be init.
1595+
if !a_layout.is_uninit_valid() && !b_layout.is_uninit_valid() {
1596+
let (a, b) = self
1597+
.ecx
1598+
.read_immediate(val)
1599+
.expect("the above checks should have fully handled this situation")
1600+
.to_scalar_pair();
1601+
self.visit_scalar(a, a_layout)
1602+
.expect("the above checks should have fully handled this situation");
1603+
self.visit_scalar(b, b_layout)
1604+
.expect("the above checks should have fully handled this situation");
1605+
}
15681606
}
1569-
}
1570-
BackendRepr::SimdVector { .. } | BackendRepr::SimdScalableVector { .. } => {
1571-
// No checks here, we assume layout computation gets this right.
1572-
// (This is harder to check since Miri does not represent these as `Immediate`. We
1573-
// also cannot use field projections since this might be a newtype around a vector.)
1574-
}
1575-
BackendRepr::Memory { .. } => {
1576-
// Nothing to do.
1607+
BackendRepr::SimdVector { .. } | BackendRepr::SimdScalableVector { .. } => {}
1608+
BackendRepr::Memory { .. } => {}
15771609
}
15781610
}
15791611

compiler/rustc_feature/src/builtin_attrs.rs

Lines changed: 0 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -573,16 +573,6 @@ pub static BUILTIN_ATTRIBUTES: &[BuiltinAttribute] = &[
573573
// Internal attributes, Layout related:
574574
// ==========================================================================
575575

576-
rustc_attr!(
577-
rustc_layout_scalar_valid_range_start,
578-
"the `#[rustc_layout_scalar_valid_range_start]` attribute is just used to enable \
579-
niche optimizations in the standard library",
580-
),
581-
rustc_attr!(
582-
rustc_layout_scalar_valid_range_end,
583-
"the `#[rustc_layout_scalar_valid_range_end]` attribute is just used to enable \
584-
niche optimizations in the standard library",
585-
),
586576
rustc_attr!(
587577
rustc_simd_monomorphize_lane_limit,
588578
"the `#[rustc_simd_monomorphize_lane_limit]` attribute is just used by std::simd \

compiler/rustc_hir/src/attrs/data_structures.rs

Lines changed: 0 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1435,12 +1435,6 @@ pub enum AttributeKind {
14351435
/// Represents `#[rustc_intrinsic_const_stable_indirect]`
14361436
RustcIntrinsicConstStableIndirect,
14371437

1438-
/// Represents `#[rustc_layout_scalar_valid_range_end]`.
1439-
RustcLayoutScalarValidRangeEnd(Box<u128>, Span),
1440-
1441-
/// Represents `#[rustc_layout_scalar_valid_range_start]`.
1442-
RustcLayoutScalarValidRangeStart(Box<u128>, Span),
1443-
14441438
/// Represents `#[rustc_legacy_const_generics]`
14451439
RustcLegacyConstGenerics {
14461440
fn_indexes: ThinVec<(usize, Span)>,

compiler/rustc_hir/src/attrs/encode_cross_crate.rs

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -147,8 +147,6 @@ impl AttributeKind {
147147
RustcInsignificantDtor => Yes,
148148
RustcIntrinsic => Yes,
149149
RustcIntrinsicConstStableIndirect => No,
150-
RustcLayoutScalarValidRangeEnd(..) => Yes,
151-
RustcLayoutScalarValidRangeStart(..) => Yes,
152150
RustcLegacyConstGenerics { .. } => Yes,
153151
RustcLintOptDenyFieldAccess { .. } => Yes,
154152
RustcLintOptTy => Yes,

compiler/rustc_hir_analysis/src/collect.rs

Lines changed: 2 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@
1515
//! crate as a kind of pass. This should eventually be factored away.
1616
1717
use std::cell::Cell;
18-
use std::ops::{Bound, ControlFlow};
18+
use std::ops::ControlFlow;
1919
use std::{assert_matches, iter};
2020

2121
use rustc_abi::{ExternAbi, Size};
@@ -1039,12 +1039,7 @@ fn fn_sig(tcx: TyCtxt<'_>, def_id: LocalDefId) -> ty::EarlyBinder<'_, ty::PolyFn
10391039
.fields()
10401040
.iter()
10411041
.map(|f| tcx.type_of(f.def_id).instantiate_identity().skip_norm_wip());
1042-
// constructors for structs with `layout_scalar_valid_range` are unsafe to call
1043-
let safety = match tcx.layout_scalar_valid_range(adt_def_id) {
1044-
(Bound::Unbounded, Bound::Unbounded) => hir::Safety::Safe,
1045-
_ => hir::Safety::Unsafe,
1046-
};
1047-
ty::Binder::dummy(tcx.mk_fn_sig_rust_abi(inputs, ty, safety))
1042+
ty::Binder::dummy(tcx.mk_fn_sig_rust_abi(inputs, ty, hir::Safety::Safe))
10481043
}
10491044

10501045
Expr(&hir::Expr { kind: hir::ExprKind::Closure { .. }, .. }) => {

compiler/rustc_middle/src/ty/context.rs

Lines changed: 1 addition & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ use std::env::VarError;
1111
use std::ffi::OsStr;
1212
use std::hash::{Hash, Hasher};
1313
use std::marker::PointeeSized;
14-
use std::ops::{Bound, Deref};
14+
use std::ops::Deref;
1515
use std::sync::{Arc, OnceLock};
1616
use std::{fmt, iter, mem};
1717

@@ -908,17 +908,6 @@ impl<'tcx> TyCtxt<'tcx> {
908908
matches!(self.as_lang_item(def_id), Some(LangItem::Sized | LangItem::MetaSized))
909909
}
910910

911-
/// Returns a range of the start/end indices specified with the
912-
/// `rustc_layout_scalar_valid_range` attribute.
913-
// FIXME(eddyb) this is an awkward spot for this method, maybe move it?
914-
pub fn layout_scalar_valid_range(self, def_id: DefId) -> (Bound<u128>, Bound<u128>) {
915-
let start = find_attr!(self, def_id, RustcLayoutScalarValidRangeStart(n, _) => Bound::Included(**n)).unwrap_or(Bound::Unbounded);
916-
let end =
917-
find_attr!(self, def_id, RustcLayoutScalarValidRangeEnd(n, _) => Bound::Included(**n))
918-
.unwrap_or(Bound::Unbounded);
919-
(start, end)
920-
}
921-
922911
pub fn lift<T: Lift<TyCtxt<'tcx>>>(self, value: T) -> T::Lifted {
923912
value.lift_to_interner(self)
924913
}

0 commit comments

Comments
 (0)