File tree Expand file tree Collapse file tree 2 files changed +31
-2
lines changed Expand file tree Collapse file tree 2 files changed +31
-2
lines changed Original file line number Diff line number Diff line change @@ -828,6 +828,7 @@ fn univariant(
828
828
if optimize && fields.len() > 1 {
829
829
let end = if let StructKind::MaybeUnsized = kind { fields.len() - 1 } else { fields.len() };
830
830
let optimizing = &mut inverse_memory_index.raw[..end];
831
+ let fields_excluding_tail = &fields.raw[..end];
831
832
832
833
// If `-Z randomize-layout` was enabled for the type definition we can shuffle
833
834
// the field ordering to try and catch some code making assumptions about layouts
@@ -844,8 +845,11 @@ fn univariant(
844
845
}
845
846
// Otherwise we just leave things alone and actually optimize the type's fields
846
847
} 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
849
853
.iter()
850
854
.filter_map(|f| f.largest_niche())
851
855
.map(|n| n.available(dl))
Original file line number Diff line number Diff line change
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
+ }
You can’t perform that action at this time.
0 commit comments