// 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 is the only field,
+ // we treat this struct just the same. Else, this is an error
+ // (for now).
+ if layout.fields.count() == 1 {
+ return Ok(None)
+ } else {
+ bug!("Fields cannot be extern types, unless they are the only field")
+ }
+ }
+ };
// FIXME (#26403, #27023): We should be adding padding
// to `sized_size` (to accommodate the `unsized_align`
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");
+ // If this is an extern type, we fall back to its static size and alignment.
+ .unwrap_or_else(|| base.layout.size_and_align());
(base.meta, offset.abi_align(align))
} else {
// base.meta could be present; we might be accessing a sized field of an unsized
--- /dev/null
+// compile-pass
+
+// Test that we can handle newtypes wrapping extern types
+
+#![feature(extern_types, const_transmute)]
+
+extern "C" {
+ pub type ExternType;
+}
+unsafe impl Sync for ExternType {}
+
+#[repr(transparent)]
+pub struct Wrapper(ExternType);
+
+static MAGIC_FFI_STATIC: u8 = 42;
+
+pub static MAGIC_FFI_REF: &'static Wrapper = unsafe {
+ std::mem::transmute(&MAGIC_FFI_STATIC)
+};
+
+fn main() {}