Skip to content

Commit 69b1b3c

Browse files
committed
Create a custom layout path for UnsafeCell instead of piggy backing on the layout_scalar_valid_range logic
1 parent 4bfba76 commit 69b1b3c

File tree

2 files changed

+48
-21
lines changed

2 files changed

+48
-21
lines changed

compiler/rustc_middle/src/ty/layout.rs

Lines changed: 39 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -1076,6 +1076,34 @@ impl<'tcx> LayoutCx<'tcx, TyCtxt<'tcx>> {
10761076

10771077
let mut st = self.univariant_uninterned(ty, &variants[v], &def.repr(), kind)?;
10781078
st.variants = Variants::Single { index: v };
1079+
1080+
if def.is_unsafe_cell() {
1081+
let fill = |scalar: &mut _| match scalar {
1082+
Scalar::Initialized { value, valid_range } => {
1083+
*valid_range = WrappingRange::full(value.size(dl))
1084+
}
1085+
// Already doesn't have any niches
1086+
Scalar::Union { .. } => {}
1087+
};
1088+
match &mut st.abi {
1089+
Abi::Uninhabited => {}
1090+
Abi::Scalar(scalar) => fill(scalar),
1091+
Abi::ScalarPair(a, b) => {
1092+
fill(a);
1093+
fill(b);
1094+
}
1095+
Abi::Vector { element, count: _ } => {
1096+
// Until we support types other than floats and integers in SIMD,
1097+
// `element` must already be a full for its range, so there's nothing to
1098+
// do here.
1099+
assert!(element.is_always_valid(dl));
1100+
}
1101+
Abi::Aggregate { sized: _ } => {}
1102+
}
1103+
st.largest_niche = None;
1104+
return Ok(tcx.intern_layout(st));
1105+
}
1106+
10791107
let (start, end) = self.tcx.layout_scalar_valid_range(def.did());
10801108
match st.abi {
10811109
Abi::Scalar(ref mut scalar) | Abi::ScalarPair(ref mut scalar, _) => {
@@ -1102,29 +1130,19 @@ impl<'tcx> LayoutCx<'tcx, TyCtxt<'tcx>> {
11021130
assert!(valid_range.end >= end);
11031131
valid_range.end = end;
11041132
}
1105-
if def.is_unsafe_cell() {
1106-
match scalar {
1107-
Scalar::Initialized { value, valid_range } => {
1108-
*valid_range = WrappingRange::full(value.size(dl))
1109-
}
1110-
// Already doesn't have any niches
1111-
Scalar::Union { .. } => {}
1112-
}
1113-
st.largest_niche = None;
1114-
} else {
1115-
// Update `largest_niche` if we have introduced a larger niche.
1116-
let niche = Niche::from_scalar(dl, Size::ZERO, *scalar);
1117-
if let Some(niche) = niche {
1118-
match st.largest_niche {
1119-
Some(largest_niche) => {
1120-
// Replace the existing niche even if they're equal,
1121-
// because this one is at a lower offset.
1122-
if largest_niche.available(dl) <= niche.available(dl) {
1123-
st.largest_niche = Some(niche);
1124-
}
1133+
1134+
// Update `largest_niche` if we have introduced a larger niche.
1135+
let niche = Niche::from_scalar(dl, Size::ZERO, *scalar);
1136+
if let Some(niche) = niche {
1137+
match st.largest_niche {
1138+
Some(largest_niche) => {
1139+
// Replace the existing niche even if they're equal,
1140+
// because this one is at a lower offset.
1141+
if largest_niche.available(dl) <= niche.available(dl) {
1142+
st.largest_niche = Some(niche);
11251143
}
1126-
None => st.largest_niche = Some(niche),
11271144
}
1145+
None => st.largest_niche = Some(niche),
11281146
}
11291147
}
11301148
}

src/test/ui/layout/unsafe-cell-hides-niche.rs

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -38,4 +38,13 @@ fn main() {
3838
assert_eq!(size_of::<Option< RwLock<&()>>>(), 32); // (✗ niche opt)
3939
assert_eq!(size_of::< Mutex<&()> >(), 16);
4040
assert_eq!(size_of::<Option< Mutex<&()>>>(), 24); // (✗ niche opt)
41+
42+
assert_eq!(size_of::< UnsafeCell<&[i32]> >(), 16);
43+
assert_eq!(size_of::<Option<UnsafeCell<&[i32]>>>(), 24); // (✗ niche opt)
44+
assert_eq!(size_of::< UnsafeCell<(&(), &())> >(), 16);
45+
assert_eq!(size_of::<Option<UnsafeCell<(&(), &())>>>(), 24); // (✗ niche opt)
46+
47+
trait Trait {}
48+
assert_eq!(size_of::< UnsafeCell<&dyn Trait> >(), 16);
49+
assert_eq!(size_of::<Option<UnsafeCell<&dyn Trait>>>(), 24); // (✗ niche opt)
4150
}

0 commit comments

Comments
 (0)