Skip to content

Commit 797b484

Browse files
committed
Rip out rustc_layout_scalar_valid_range_* attribute support
1 parent 3c13d7b commit 797b484

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<S: Stage> NoArgsAttributeParser<S> for RustcNoImplicitAutorefsParser {
9292
const CREATE: fn(Span) -> AttributeKind = |_| AttributeKind::RustcNoImplicitAutorefs;
9393
}
9494

95-
pub(crate) struct RustcLayoutScalarValidRangeStartParser;
96-
97-
impl<S: Stage> SingleAttributeParser<S> 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<'_, '_, S>, 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<S: Stage> SingleAttributeParser<S> 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<'_, '_, S>, 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<S: Stage> SingleAttributeParser<S> 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<S: Stage>(

compiler/rustc_attr_parsing/src/context.rs

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -225,8 +225,6 @@ attribute_parsers!(
225225
Single<RustcDumpSymbolNameParser>,
226226
Single<RustcForceInlineParser>,
227227
Single<RustcIfThisChangedParser>,
228-
Single<RustcLayoutScalarValidRangeEndParser>,
229-
Single<RustcLayoutScalarValidRangeStartParser>,
230228
Single<RustcLegacyConstGenericsParser>,
231229
Single<RustcLintOptDenyFieldAccessParser>,
232230
Single<RustcMacroTransparencyParser>,

compiler/rustc_const_eval/src/interpret/validity.rs

Lines changed: 66 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -1442,7 +1442,7 @@ impl<'rt, 'tcx, M: Machine<'tcx>> ValueVisitor<'tcx, M> for ValidityVisitor<'rt,
14421442
// First check that the base type is valid
14431443
self.visit_value(&val.transmute(self.ecx.layout_of(*base)?, self.ecx)?)?;
14441444
// When you extend this match, make sure to also add tests to
1445-
// tests/ui/type/pattern_types/validity.rs((
1445+
// tests/ui/type/pattern_types/validity.rs
14461446
match **pat {
14471447
// Range and non-null patterns are precisely reflected into `valid_range` and thus
14481448
// handled fully by `visit_scalar` (called below).
@@ -1457,6 +1457,34 @@ impl<'rt, 'tcx, M: Machine<'tcx>> ValueVisitor<'tcx, M> for ValidityVisitor<'rt,
14571457
// we won't see optimizations actually breaking such programs.
14581458
ty::PatternKind::Or(_patterns) => {}
14591459
}
1460+
// FIXME(pattern_types): handle everything based on the pattern, not on the layout.
1461+
// it's ok to run scalar validation even if the pattern type is `u8 is 0..=255` and thus
1462+
// allows uninit values, because that's rare and so not a perf issue.
1463+
match val.layout.backend_repr {
1464+
BackendRepr::Scalar(scalar_layout) => {
1465+
if !scalar_layout.is_uninit_valid() {
1466+
// There is something to check here.
1467+
// We read directly via `ecx` since the read cannot fail -- we already read
1468+
// this field above when recursing into the field.
1469+
let scalar = self.ecx.read_scalar(val)?;
1470+
self.visit_scalar(scalar, scalar_layout)?;
1471+
}
1472+
}
1473+
BackendRepr::ScalarPair(a_layout, b_layout) => {
1474+
// We can only proceed if *both* scalars need to be initialized.
1475+
// FIXME: find a way to also check ScalarPair when one side can be uninit but
1476+
// the other must be init.
1477+
if !a_layout.is_uninit_valid() && !b_layout.is_uninit_valid() {
1478+
// We read directly via `ecx` since the read cannot fail -- we already read
1479+
// this field above when recursing into the field.
1480+
let (a, b) = self.ecx.read_immediate(val)?.to_scalar_pair();
1481+
self.visit_scalar(a, a_layout)?;
1482+
self.visit_scalar(b, b_layout)?;
1483+
}
1484+
}
1485+
BackendRepr::SimdVector { .. } | BackendRepr::SimdScalableVector { .. } => unreachable!(),
1486+
BackendRepr::Memory { .. } => unreachable!()
1487+
}
14601488
}
14611489
ty::Adt(adt, _) if adt.is_maybe_dangling() => {
14621490
let old_may_dangle = mem::replace(&mut self.may_dangle, true);
@@ -1479,51 +1507,55 @@ impl<'rt, 'tcx, M: Machine<'tcx>> ValueVisitor<'tcx, M> for ValidityVisitor<'rt,
14791507
}
14801508
}
14811509

1482-
// *After* all of this, check further information stored in the layout. We need to check
1483-
// this to handle types like `NonNull` where the `Scalar` info is more restrictive than what
1484-
// the fields say (`rustc_layout_scalar_valid_range_start`). But in most cases, this will
1485-
// just propagate what the fields say, and then we want the error to point at the field --
1486-
// so, we first recurse, then we do this check.
1510+
// *After* all of this, check further information stored in the layout.
1511+
// On leaf types like `!` or empty enums, this will raise the error.
1512+
// This means that for types wrapping such a type, we won't ever get here, but it's
1513+
// just the simplest way to check for this case.
14871514
//
14881515
// FIXME: We could avoid some redundant checks here. For newtypes wrapping
14891516
// scalars, we do the same check on every "level" (e.g., first we check
1490-
// MyNewtype and then the scalar in there).
1517+
// the fields of MyNewtype, and then we check MyNewType again).
14911518
if val.layout.is_uninhabited() {
14921519
let ty = val.layout.ty;
14931520
throw_validation_failure!(
14941521
self.path,
14951522
format!("encountered a value of uninhabited type `{ty}`")
14961523
);
14971524
}
1498-
match val.layout.backend_repr {
1499-
BackendRepr::Scalar(scalar_layout) => {
1500-
if !scalar_layout.is_uninit_valid() {
1501-
// There is something to check here.
1502-
// We read directly via `ecx` since the read cannot fail -- we already read
1503-
// this field above when recursing into the field.
1504-
let scalar = self.ecx.read_scalar(val)?;
1505-
self.visit_scalar(scalar, scalar_layout)?;
1525+
if cfg!(debug_assertions) {
1526+
// Check that we don't miss any new changes to layout computation in our checks above.
1527+
match val.layout.backend_repr {
1528+
BackendRepr::Scalar(scalar_layout) => {
1529+
if !scalar_layout.is_uninit_valid() {
1530+
// There is something to check here.
1531+
// We read directly via `ecx` since the read cannot fail -- we already read
1532+
// this field above when recursing into the field.
1533+
let scalar = self
1534+
.ecx
1535+
.read_scalar(val)
1536+
.expect("the above checks should have fully handled this situation");
1537+
self.visit_scalar(scalar, scalar_layout)
1538+
.expect("the above checks should have fully handled this situation");
1539+
}
15061540
}
1507-
}
1508-
BackendRepr::ScalarPair(a_layout, b_layout) => {
1509-
// We can only proceed if *both* scalars need to be initialized.
1510-
// FIXME: find a way to also check ScalarPair when one side can be uninit but
1511-
// the other must be init.
1512-
if !a_layout.is_uninit_valid() && !b_layout.is_uninit_valid() {
1513-
// We read directly via `ecx` since the read cannot fail -- we already read
1514-
// this field above when recursing into the field.
1515-
let (a, b) = self.ecx.read_immediate(val)?.to_scalar_pair();
1516-
self.visit_scalar(a, a_layout)?;
1517-
self.visit_scalar(b, b_layout)?;
1541+
BackendRepr::ScalarPair(a_layout, b_layout) => {
1542+
// We can only proceed if *both* scalars need to be initialized.
1543+
// FIXME: find a way to also check ScalarPair when one side can be uninit but
1544+
// the other must be init.
1545+
if !a_layout.is_uninit_valid() && !b_layout.is_uninit_valid() {
1546+
let (a, b) = self
1547+
.ecx
1548+
.read_immediate(val)
1549+
.expect("the above checks should have fully handled this situation")
1550+
.to_scalar_pair();
1551+
self.visit_scalar(a, a_layout)
1552+
.expect("the above checks should have fully handled this situation");
1553+
self.visit_scalar(b, b_layout)
1554+
.expect("the above checks should have fully handled this situation");
1555+
}
15181556
}
1519-
}
1520-
BackendRepr::SimdVector { .. } | BackendRepr::SimdScalableVector { .. } => {
1521-
// No checks here, we assume layout computation gets this right.
1522-
// (This is harder to check since Miri does not represent these as `Immediate`. We
1523-
// also cannot use field projections since this might be a newtype around a vector.)
1524-
}
1525-
BackendRepr::Memory { .. } => {
1526-
// Nothing to do.
1557+
BackendRepr::SimdVector { .. } | BackendRepr::SimdScalableVector { .. } => {}
1558+
BackendRepr::Memory { .. } => {}
15271559
}
15281560
}
15291561

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
@@ -1455,12 +1455,6 @@ pub enum AttributeKind {
14551455
/// Represents `#[rustc_intrinsic_const_stable_indirect]`
14561456
RustcIntrinsicConstStableIndirect,
14571457

1458-
/// Represents `#[rustc_layout_scalar_valid_range_end]`.
1459-
RustcLayoutScalarValidRangeEnd(Box<u128>, Span),
1460-
1461-
/// Represents `#[rustc_layout_scalar_valid_range_start]`.
1462-
RustcLayoutScalarValidRangeStart(Box<u128>, Span),
1463-
14641458
/// Represents `#[rustc_legacy_const_generics]`
14651459
RustcLegacyConstGenerics {
14661460
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::{PhantomData, 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

@@ -991,17 +991,6 @@ impl<'tcx> TyCtxt<'tcx> {
991991
matches!(self.as_lang_item(def_id), Some(LangItem::Sized | LangItem::MetaSized))
992992
}
993993

994-
/// Returns a range of the start/end indices specified with the
995-
/// `rustc_layout_scalar_valid_range` attribute.
996-
// FIXME(eddyb) this is an awkward spot for this method, maybe move it?
997-
pub fn layout_scalar_valid_range(self, def_id: DefId) -> (Bound<u128>, Bound<u128>) {
998-
let start = find_attr!(self, def_id, RustcLayoutScalarValidRangeStart(n, _) => Bound::Included(**n)).unwrap_or(Bound::Unbounded);
999-
let end =
1000-
find_attr!(self, def_id, RustcLayoutScalarValidRangeEnd(n, _) => Bound::Included(**n))
1001-
.unwrap_or(Bound::Unbounded);
1002-
(start, end)
1003-
}
1004-
1005994
pub fn lift<T: Lift<TyCtxt<'tcx>>>(self, value: T) -> Option<T::Lifted> {
1006995
value.lift_to_interner(self)
1007996
}

0 commit comments

Comments
 (0)