Skip to content

Commit 97e5045

Browse files
committed
Fix taking address of truly unsized type field of unsized adt
1 parent f557a7e commit 97e5045

File tree

3 files changed

+70
-1
lines changed

3 files changed

+70
-1
lines changed

Diff for: example/issue-91827-extern-types.rs

+60
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,60 @@
1+
// Copied from rustc ui test suite
2+
3+
// run-pass
4+
//
5+
// Test that we can handle unsized types with an extern type tail part.
6+
// Regression test for issue #91827.
7+
8+
#![feature(const_ptr_offset_from)]
9+
#![feature(const_slice_from_raw_parts)]
10+
#![feature(extern_types)]
11+
12+
use std::ptr::addr_of;
13+
14+
extern "C" {
15+
type Opaque;
16+
}
17+
18+
unsafe impl Sync for Opaque {}
19+
20+
#[repr(C)]
21+
pub struct List<T> {
22+
len: usize,
23+
data: [T; 0],
24+
tail: Opaque,
25+
}
26+
27+
#[repr(C)]
28+
pub struct ListImpl<T, const N: usize> {
29+
len: usize,
30+
data: [T; N],
31+
}
32+
33+
impl<T> List<T> {
34+
const fn as_slice(&self) -> &[T] {
35+
unsafe { std::slice::from_raw_parts(self.data.as_ptr(), self.len) }
36+
}
37+
}
38+
39+
impl<T, const N: usize> ListImpl<T, N> {
40+
const fn as_list(&self) -> &List<T> {
41+
unsafe { std::mem::transmute(self) }
42+
}
43+
}
44+
45+
pub static A: ListImpl<u128, 3> = ListImpl {
46+
len: 3,
47+
data: [5, 6, 7],
48+
};
49+
pub static A_REF: &'static List<u128> = A.as_list();
50+
pub static A_TAIL_OFFSET: isize = tail_offset(A.as_list());
51+
52+
const fn tail_offset<T>(list: &List<T>) -> isize {
53+
unsafe { (addr_of!(list.tail) as *const u8).offset_from(list as *const List<T> as *const u8) }
54+
}
55+
56+
fn main() {
57+
assert_eq!(A_REF.as_slice(), &[5, 6, 7]);
58+
// Check that interpreter and code generation agree about the position of the tail field.
59+
assert_eq!(A_TAIL_OFFSET, tail_offset(A_REF));
60+
}

Diff for: scripts/tests.sh

+4
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,10 @@ function base_sysroot_tests() {
3535
$MY_RUSTC example/arbitrary_self_types_pointers_and_wrappers.rs --crate-name arbitrary_self_types_pointers_and_wrappers --crate-type bin --target "$TARGET_TRIPLE"
3636
$RUN_WRAPPER ./target/out/arbitrary_self_types_pointers_and_wrappers
3737

38+
echo "[AOT] issue_91827_extern_types"
39+
$MY_RUSTC example/issue-91827-extern-types.rs --crate-name issue_91827_extern_types --crate-type bin --target "$TARGET_TRIPLE"
40+
$RUN_WRAPPER ./target/out/issue_91827_extern_types
41+
3842
echo "[AOT] alloc_system"
3943
$MY_RUSTC example/alloc_system.rs --crate-type lib --target "$TARGET_TRIPLE"
4044

Diff for: src/value_and_place.rs

+6-1
Original file line numberDiff line numberDiff line change
@@ -672,7 +672,12 @@ impl<'tcx> CPlace<'tcx> {
672672

673673
let (field_ptr, field_layout) = codegen_field(fx, base, extra, layout, field);
674674
if field_layout.is_unsized() {
675-
CPlace::for_ptr_with_extra(field_ptr, extra.unwrap(), field_layout)
675+
if let ty::Foreign(_) = field_layout.ty.kind() {
676+
assert!(extra.is_none());
677+
CPlace::for_ptr(field_ptr, field_layout)
678+
} else {
679+
CPlace::for_ptr_with_extra(field_ptr, extra.unwrap(), field_layout)
680+
}
676681
} else {
677682
CPlace::for_ptr(field_ptr, field_layout)
678683
}

0 commit comments

Comments
 (0)