Skip to content

Commit

Permalink
Rollup merge of rust-lang#55672 - RalfJung:miri-extern-types, r=eddyb
Browse files Browse the repository at this point in the history
miri: accept extern types in structs if they are the only field

Fixes rust-lang#55541

Cc @oli-obk @eddyb rust-lang#43467
  • Loading branch information
pietroalbini committed Nov 12, 2018
2 parents 0195812 + ba0bab3 commit 1a61f26
Show file tree
Hide file tree
Showing 3 changed files with 53 additions and 4 deletions.
17 changes: 15 additions & 2 deletions src/librustc_mir/interpret/eval_context.rs
Original file line number Diff line number Diff line change
Expand Up @@ -341,8 +341,21 @@ impl<'a, 'mir, 'tcx: 'mir, M: Machine<'a, 'mir, 'tcx>> EvalContext<'a, 'mir, 'tc
// the last field). Can't have foreign types here, how would we
// adjust alignment and size for them?
let field = layout.field(self, layout.fields.count() - 1)?;
let (unsized_size, unsized_align) = self.size_and_align_of(metadata, field)?
.expect("Fields cannot be extern types");
let (unsized_size, unsized_align) = match self.size_and_align_of(metadata, field)? {
Some(size_and_align) => size_and_align,
None => {
// A field with extern type. If this field is at offset 0, we behave
// like the underlying extern type.
// FIXME: Once we have made decisions for how to handle size and alignment
// of `extern type`, this should be adapted. It is just a temporary hack
// to get some code to work that probably ought to work.
if sized_size == Size::ZERO {
return Ok(None)
} else {
bug!("Fields cannot be extern types, unless they are at offset 0")
}
}
};

// FIXME (#26403, #27023): We should be adding padding
// to `sized_size` (to accommodate the `unsized_align`
Expand Down
13 changes: 11 additions & 2 deletions src/librustc_mir/interpret/place.rs
Original file line number Diff line number Diff line change
Expand Up @@ -346,8 +346,17 @@ where
// Offset may need adjustment for unsized fields
let (meta, offset) = if field_layout.is_unsized() {
// re-use parent metadata to determine dynamic field layout
let (_, align) = self.size_and_align_of(base.meta, field_layout)?
.expect("Fields cannot be extern types");
let align = match self.size_and_align_of(base.meta, field_layout)? {
Some((_, align)) => align,
None if offset == Size::ZERO =>
// An extern type at offset 0, we fall back to its static alignment.
// FIXME: Once we have made decisions for how to handle size and alignment
// of `extern type`, this should be adapted. It is just a temporary hack
// to get some code to work that probably ought to work.
field_layout.align,
None =>
bug!("Cannot compute offset for extern type field at non-0 offset"),
};
(base.meta, offset.abi_align(align))
} else {
// base.meta could be present; we might be accessing a sized field of an unsized
Expand Down
27 changes: 27 additions & 0 deletions src/test/ui/consts/const-eval/issue-55541.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
// compile-pass

// Test that we can handle newtypes wrapping extern types

#![feature(extern_types, const_transmute)]

use std::marker::PhantomData;

extern "C" {
pub type ExternType;
}
unsafe impl Sync for ExternType {}
static MAGIC_FFI_STATIC: u8 = 42;

#[repr(transparent)]
pub struct Wrapper(ExternType);
pub static MAGIC_FFI_REF: &'static Wrapper = unsafe {
std::mem::transmute(&MAGIC_FFI_STATIC)
};

#[repr(transparent)]
pub struct Wrapper2(PhantomData<Vec<i32>>, ExternType);
pub static MAGIC_FFI_REF2: &'static Wrapper2 = unsafe {
std::mem::transmute(&MAGIC_FFI_STATIC)
};

fn main() {}

0 comments on commit 1a61f26

Please sign in to comment.