Skip to content

Commit fc23a81

Browse files
committed
Auto merge of #68491 - pnkfelix:hide-niches-under-unsafe-cell, r=oli
Hide niches under UnsafeCell Hide any niche of T from type-construction context of `UnsafeCell<T>`. Fix #68303 Fix #68206
2 parents 3f32e30 + 1b12232 commit fc23a81

File tree

17 files changed

+521
-24
lines changed

17 files changed

+521
-24
lines changed

src/ci/docker/dist-various-2/Dockerfile

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -48,7 +48,7 @@ RUN /tmp/build-solaris-toolchain.sh sparcv9 sparcv9 solaris-sparc
4848
COPY dist-various-2/build-x86_64-fortanix-unknown-sgx-toolchain.sh /tmp/
4949
# We pass the commit id of the port of LLVM's libunwind to the build script.
5050
# Any update to the commit id here, should cause the container image to be re-built from this point on.
51-
RUN /tmp/build-x86_64-fortanix-unknown-sgx-toolchain.sh "53b586346f2c7870e20b170decdc30729d97c42b"
51+
RUN /tmp/build-x86_64-fortanix-unknown-sgx-toolchain.sh "5125c169b30837208a842f85f7ae44a83533bd0e"
5252

5353
COPY dist-various-2/build-wasi-toolchain.sh /tmp/
5454
RUN /tmp/build-wasi-toolchain.sh

src/libcore/cell.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1475,6 +1475,7 @@ impl<T: ?Sized + fmt::Display> fmt::Display for RefMut<'_, T> {
14751475
#[lang = "unsafe_cell"]
14761476
#[stable(feature = "rust1", since = "1.0.0")]
14771477
#[repr(transparent)]
1478+
#[cfg_attr(not(bootstrap), repr(no_niche))] // rust-lang/rust#68303.
14781479
pub struct UnsafeCell<T: ?Sized> {
14791480
value: T,
14801481
}

src/libcore/lib.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -139,6 +139,7 @@
139139
#![feature(const_type_id)]
140140
#![feature(const_caller_location)]
141141
#![feature(assoc_int_consts)]
142+
#![cfg_attr(not(bootstrap), feature(no_niche))] // rust-lang/rust#68303
142143

143144
#[prelude_import]
144145
#[allow(unused)]

src/librustc/ty/layout.rs

Lines changed: 18 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -356,12 +356,14 @@ impl<'tcx> LayoutCx<'tcx, TyCtxt<'tcx>> {
356356
debug!("univariant offset: {:?} field: {:#?}", offset, field);
357357
offsets[i as usize] = offset;
358358

359-
if let Some(mut niche) = field.largest_niche.clone() {
360-
let available = niche.available(dl);
361-
if available > largest_niche_available {
362-
largest_niche_available = available;
363-
niche.offset += offset;
364-
largest_niche = Some(niche);
359+
if !repr.hide_niche() {
360+
if let Some(mut niche) = field.largest_niche.clone() {
361+
let available = niche.available(dl);
362+
if available > largest_niche_available {
363+
largest_niche_available = available;
364+
niche.offset += offset;
365+
largest_niche = Some(niche);
366+
}
365367
}
366368
}
367369

@@ -838,7 +840,11 @@ impl<'tcx> LayoutCx<'tcx, TyCtxt<'tcx>> {
838840
}
839841

840842
// Update `largest_niche` if we have introduced a larger niche.
841-
let niche = Niche::from_scalar(dl, Size::ZERO, scalar.clone());
843+
let niche = if def.repr.hide_niche() {
844+
None
845+
} else {
846+
Niche::from_scalar(dl, Size::ZERO, scalar.clone())
847+
};
842848
if let Some(niche) = niche {
843849
match &st.largest_niche {
844850
Some(largest_niche) => {
@@ -863,6 +869,11 @@ impl<'tcx> LayoutCx<'tcx, TyCtxt<'tcx>> {
863869
return Ok(tcx.intern_layout(st));
864870
}
865871

872+
// At this point, we have handled all unions and
873+
// structs. (We have also handled univariant enums
874+
// that allow representation optimization.)
875+
assert!(def.is_enum());
876+
866877
// The current code for niche-filling relies on variant indices
867878
// instead of actual discriminants, so dataful enums with
868879
// explicit discriminants (RFC #2363) would misbehave.

src/librustc/ty/mod.rs

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2041,7 +2041,8 @@ bitflags! {
20412041
const IS_TRANSPARENT = 1 << 2;
20422042
// Internal only for now. If true, don't reorder fields.
20432043
const IS_LINEAR = 1 << 3;
2044-
2044+
// If true, don't expose any niche to type's context.
2045+
const HIDE_NICHE = 1 << 4;
20452046
// Any of these flags being set prevent field reordering optimisation.
20462047
const IS_UNOPTIMISABLE = ReprFlags::IS_C.bits |
20472048
ReprFlags::IS_SIMD.bits |
@@ -2078,6 +2079,7 @@ impl ReprOptions {
20782079
ReprFlags::empty()
20792080
}
20802081
attr::ReprTransparent => ReprFlags::IS_TRANSPARENT,
2082+
attr::ReprNoNiche => ReprFlags::HIDE_NICHE,
20812083
attr::ReprSimd => ReprFlags::IS_SIMD,
20822084
attr::ReprInt(i) => {
20832085
size = Some(i);
@@ -2118,6 +2120,10 @@ impl ReprOptions {
21182120
pub fn linear(&self) -> bool {
21192121
self.flags.contains(ReprFlags::IS_LINEAR)
21202122
}
2123+
#[inline]
2124+
pub fn hide_niche(&self) -> bool {
2125+
self.flags.contains(ReprFlags::HIDE_NICHE)
2126+
}
21212127

21222128
pub fn discr_type(&self) -> attr::IntType {
21232129
self.int.unwrap_or(attr::SignedInt(ast::IntTy::Isize))

src/librustc_attr/builtin.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -840,6 +840,7 @@ pub enum ReprAttr {
840840
ReprSimd,
841841
ReprTransparent,
842842
ReprAlign(u32),
843+
ReprNoNiche,
843844
}
844845

845846
#[derive(Eq, PartialEq, Debug, RustcEncodable, RustcDecodable, Copy, Clone, HashStable_Generic)]
@@ -895,6 +896,7 @@ pub fn find_repr_attrs(sess: &ParseSess, attr: &Attribute) -> Vec<ReprAttr> {
895896
sym::packed => Some(ReprPacked(1)),
896897
sym::simd => Some(ReprSimd),
897898
sym::transparent => Some(ReprTransparent),
899+
sym::no_niche => Some(ReprNoNiche),
898900
name => int_type_of_word(name).map(ReprInt),
899901
};
900902

src/librustc_builtin_macros/deriving/generic/mod.rs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -825,7 +825,8 @@ fn find_repr_type_name(sess: &ParseSess, type_attrs: &[ast::Attribute]) -> &'sta
825825
attr::ReprPacked(_)
826826
| attr::ReprSimd
827827
| attr::ReprAlign(_)
828-
| attr::ReprTransparent => continue,
828+
| attr::ReprTransparent
829+
| attr::ReprNoNiche => continue,
829830

830831
attr::ReprC => "i32",
831832

src/librustc_feature/active.rs

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -204,6 +204,10 @@ declare_features! (
204204
/// Added for testing E0705; perma-unstable.
205205
(active, test_2018_feature, "1.31.0", None, Some(Edition::Edition2018)),
206206

207+
/// Allows `#[repr(no_niche)]` (an implementation detail of `rustc`,
208+
/// it is not on path for eventual stabilization).
209+
(active, no_niche, "1.42.0", None, None),
210+
207211
// no-tracking-issue-end
208212

209213
// -------------------------------------------------------------------------

src/librustc_passes/check_attr.rs

Lines changed: 21 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -16,9 +16,10 @@ use rustc_hir::intravisit::{self, NestedVisitorMap, Visitor};
1616
use rustc_hir::DUMMY_HIR_ID;
1717
use rustc_hir::{self, HirId, Item, ItemKind, TraitItem};
1818
use rustc_session::lint::builtin::{CONFLICTING_REPR_HINTS, UNUSED_ATTRIBUTES};
19+
use rustc_session::parse::feature_err;
1920
use rustc_span::symbol::sym;
2021
use rustc_span::Span;
21-
use syntax::ast::Attribute;
22+
use syntax::ast::{Attribute, NestedMetaItem};
2223
use syntax::attr;
2324

2425
fn target_from_impl_item<'tcx>(tcx: TyCtxt<'tcx>, impl_item: &hir::ImplItem<'_>) -> Target {
@@ -278,6 +279,21 @@ impl CheckAttrVisitor<'tcx> {
278279
_ => ("a", "struct, enum, or union"),
279280
}
280281
}
282+
sym::no_niche => {
283+
if !self.tcx.features().enabled(sym::no_niche) {
284+
feature_err(
285+
&self.tcx.sess.parse_sess,
286+
sym::no_niche,
287+
hint.span(),
288+
"the attribute `repr(no_niche)` is currently unstable",
289+
)
290+
.emit();
291+
}
292+
match target {
293+
Target::Struct | Target::Enum => continue,
294+
_ => ("a", "struct or enum"),
295+
}
296+
}
281297
sym::i8
282298
| sym::u8
283299
| sym::i16
@@ -305,8 +321,10 @@ impl CheckAttrVisitor<'tcx> {
305321
// This is not ideal, but tracking precisely which ones are at fault is a huge hassle.
306322
let hint_spans = hints.iter().map(|hint| hint.span());
307323

308-
// Error on repr(transparent, <anything else>).
309-
if is_transparent && hints.len() > 1 {
324+
// Error on repr(transparent, <anything else apart from no_niche>).
325+
let non_no_niche = |hint: &&NestedMetaItem| hint.name_or_empty() != sym::no_niche;
326+
let non_no_niche_count = hints.iter().filter(non_no_niche).count();
327+
if is_transparent && non_no_niche_count > 1 {
310328
let hint_spans: Vec<_> = hint_spans.clone().collect();
311329
struct_span_err!(
312330
self.tcx.sess,

src/librustc_span/symbol.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -491,6 +491,7 @@ symbols! {
491491
non_exhaustive,
492492
non_modrs_mods,
493493
no_sanitize,
494+
no_niche,
494495
no_stack_check,
495496
no_start,
496497
no_std,
@@ -587,6 +588,7 @@ symbols! {
587588
repr128,
588589
repr_align,
589590
repr_align_enum,
591+
repr_no_niche,
590592
repr_packed,
591593
repr_simd,
592594
repr_transparent,

0 commit comments

Comments
 (0)