Skip to content

Commit a9b791b

Browse files
committed
Auto merge of #55672 - RalfJung:miri-extern-types, r=eddyb
miri: accept extern types in structs if they are the only field Fixes #55541 Cc @oli-obk @eddyb #43467
2 parents 13c9439 + ba0bab3 commit a9b791b

File tree

3 files changed

+53
-4
lines changed

3 files changed

+53
-4
lines changed

src/librustc_mir/interpret/eval_context.rs

+15-2
Original file line numberDiff line numberDiff line change
@@ -341,8 +341,21 @@ impl<'a, 'mir, 'tcx: 'mir, M: Machine<'a, 'mir, 'tcx>> EvalContext<'a, 'mir, 'tc
341341
// the last field). Can't have foreign types here, how would we
342342
// adjust alignment and size for them?
343343
let field = layout.field(self, layout.fields.count() - 1)?;
344-
let (unsized_size, unsized_align) = self.size_and_align_of(metadata, field)?
345-
.expect("Fields cannot be extern types");
344+
let (unsized_size, unsized_align) = match self.size_and_align_of(metadata, field)? {
345+
Some(size_and_align) => size_and_align,
346+
None => {
347+
// A field with extern type. If this field is at offset 0, we behave
348+
// like the underlying extern type.
349+
// FIXME: Once we have made decisions for how to handle size and alignment
350+
// of `extern type`, this should be adapted. It is just a temporary hack
351+
// to get some code to work that probably ought to work.
352+
if sized_size == Size::ZERO {
353+
return Ok(None)
354+
} else {
355+
bug!("Fields cannot be extern types, unless they are at offset 0")
356+
}
357+
}
358+
};
346359

347360
// FIXME (#26403, #27023): We should be adding padding
348361
// to `sized_size` (to accommodate the `unsized_align`

src/librustc_mir/interpret/place.rs

+11-2
Original file line numberDiff line numberDiff line change
@@ -351,8 +351,17 @@ where
351351
// Offset may need adjustment for unsized fields
352352
let (meta, offset) = if field_layout.is_unsized() {
353353
// re-use parent metadata to determine dynamic field layout
354-
let (_, align) = self.size_and_align_of(base.meta, field_layout)?
355-
.expect("Fields cannot be extern types");
354+
let align = match self.size_and_align_of(base.meta, field_layout)? {
355+
Some((_, align)) => align,
356+
None if offset == Size::ZERO =>
357+
// An extern type at offset 0, we fall back to its static alignment.
358+
// FIXME: Once we have made decisions for how to handle size and alignment
359+
// of `extern type`, this should be adapted. It is just a temporary hack
360+
// to get some code to work that probably ought to work.
361+
field_layout.align,
362+
None =>
363+
bug!("Cannot compute offset for extern type field at non-0 offset"),
364+
};
356365
(base.meta, offset.abi_align(align))
357366
} else {
358367
// base.meta could be present; we might be accessing a sized field of an unsized
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
// compile-pass
2+
3+
// Test that we can handle newtypes wrapping extern types
4+
5+
#![feature(extern_types, const_transmute)]
6+
7+
use std::marker::PhantomData;
8+
9+
extern "C" {
10+
pub type ExternType;
11+
}
12+
unsafe impl Sync for ExternType {}
13+
static MAGIC_FFI_STATIC: u8 = 42;
14+
15+
#[repr(transparent)]
16+
pub struct Wrapper(ExternType);
17+
pub static MAGIC_FFI_REF: &'static Wrapper = unsafe {
18+
std::mem::transmute(&MAGIC_FFI_STATIC)
19+
};
20+
21+
#[repr(transparent)]
22+
pub struct Wrapper2(PhantomData<Vec<i32>>, ExternType);
23+
pub static MAGIC_FFI_REF2: &'static Wrapper2 = unsafe {
24+
std::mem::transmute(&MAGIC_FFI_STATIC)
25+
};
26+
27+
fn main() {}

0 commit comments

Comments
 (0)