Skip to content

Commit e753d21

Browse files
committed
miri: accept extern types in structs if they are the only field
1 parent 6d69fe7 commit e753d21

File tree

3 files changed

+36
-3
lines changed

3 files changed

+36
-3
lines changed

src/librustc_mir/interpret/eval_context.rs

+13-2
Original file line numberDiff line numberDiff line change
@@ -371,8 +371,19 @@ impl<'a, 'mir, 'tcx: 'mir, M: Machine<'a, 'mir, 'tcx>> EvalContext<'a, 'mir, 'tc
371371
// the last field). Can't have foreign types here, how would we
372372
// adjust alignment and size for them?
373373
let field = layout.field(self, layout.fields.count() - 1)?;
374-
let (unsized_size, unsized_align) = self.size_and_align_of(metadata, field)?
375-
.expect("Fields cannot be extern types");
374+
let (unsized_size, unsized_align) = match self.size_and_align_of(metadata, field)? {
375+
Some(size_and_align) => size_and_align,
376+
None => {
377+
// A field with extern type. If this is the only field,
378+
// we treat this struct just the same. Else, this is an error
379+
// (for now).
380+
if layout.fields.count() == 1 {
381+
return Ok(None)
382+
} else {
383+
bug!("Fields cannot be extern types, unless they are the only field")
384+
}
385+
}
386+
};
376387

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

src/librustc_mir/interpret/place.rs

+2-1
Original file line numberDiff line numberDiff line change
@@ -354,7 +354,8 @@ where
354354
let (meta, offset) = if field_layout.is_unsized() {
355355
// re-use parent metadata to determine dynamic field layout
356356
let (_, align) = self.size_and_align_of(base.meta, field_layout)?
357-
.expect("Fields cannot be extern types");
357+
// If this is an extern type, we fall back to its static size and alignment.
358+
.unwrap_or_else(|| base.layout.size_and_align());
358359
(base.meta, offset.abi_align(align))
359360
} else {
360361
// 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,21 @@
1+
// compile-pass
2+
3+
// Test that we can handle newtypes wrapping extern types
4+
5+
#![feature(extern_types, const_transmute)]
6+
7+
extern "C" {
8+
pub type ExternType;
9+
}
10+
unsafe impl Sync for ExternType {}
11+
12+
#[repr(transparent)]
13+
pub struct Wrapper(ExternType);
14+
15+
static MAGIC_FFI_STATIC: u8 = 42;
16+
17+
pub static MAGIC_FFI_REF: &'static Wrapper = unsafe {
18+
std::mem::transmute(&MAGIC_FFI_STATIC)
19+
};
20+
21+
fn main() {}

0 commit comments

Comments
 (0)