Skip to content

Commit 381b778

Browse files
author
Lukas Markeffsky
committed
Make struct layout not depend on unsizeable tail
1 parent 70e04bd commit 381b778

File tree

2 files changed

+31
-2
lines changed

2 files changed

+31
-2
lines changed

compiler/rustc_abi/src/layout.rs

+6-2
Original file line numberDiff line numberDiff line change
@@ -828,6 +828,7 @@ fn univariant(
828828
if optimize && fields.len() > 1 {
829829
let end = if let StructKind::MaybeUnsized = kind { fields.len() - 1 } else { fields.len() };
830830
let optimizing = &mut inverse_memory_index.raw[..end];
831+
let fields_excluding_tail = &fields.raw[..end];
831832

832833
// If `-Z randomize-layout` was enabled for the type definition we can shuffle
833834
// the field ordering to try and catch some code making assumptions about layouts
@@ -844,8 +845,11 @@ fn univariant(
844845
}
845846
// Otherwise we just leave things alone and actually optimize the type's fields
846847
} else {
847-
let max_field_align = fields.iter().map(|f| f.align().abi.bytes()).max().unwrap_or(1);
848-
let largest_niche_size = fields
848+
// To allow unsizing `&Foo<Type>` -> `&Foo<dyn Trait>`, the layout of the struct must
849+
// not depend on the layout of the tail.
850+
let max_field_align =
851+
fields_excluding_tail.iter().map(|f| f.align().abi.bytes()).max().unwrap_or(1);
852+
let largest_niche_size = fields_excluding_tail
849853
.iter()
850854
.filter_map(|f| f.largest_niche())
851855
.map(|n| n.available(dl))
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
// run-pass
2+
3+
// Check that unsizing doesn't reorder fields.
4+
5+
#![allow(dead_code)]
6+
7+
use std::fmt::Debug;
8+
9+
#[derive(Debug)]
10+
struct GcNode<T: ?Sized> {
11+
gets_swapped_with_next: usize,
12+
next: Option<&'static GcNode<dyn Debug>>,
13+
tail: T,
14+
}
15+
16+
fn main() {
17+
let node: Box<GcNode<dyn Debug>> = Box::new(GcNode {
18+
gets_swapped_with_next: 42,
19+
next: None,
20+
tail: Box::new(1),
21+
});
22+
23+
assert_eq!(node.gets_swapped_with_next, 42);
24+
assert!(node.next.is_none());
25+
}

0 commit comments

Comments
 (0)