Change:
A slightly different reproducer that doesn't rely on constant propagation pass, and so should be more robust: label +A-const-eval +F-extern_types
Error: Malformed in master branch. missing field for key at line 156 column 1 Please let know if you're having trouble with this bot.

Discussion:
match self.size_and_align_of(metadata, &field)? { Some(size_and_align) => size_and_align, None => { <del> // 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 { span_bug!( self.cur_span(), "Fields cannot be extern types, unless they are at offset 0" ) } </del> <ins> // A field with an extern type. We don't know the actual dynamic size // or the alignment. return Ok(None); </ins> } };

// Re-use parent metadata to determine dynamic field layout. // With custom DSTS, this *will* execute user-defined code, but the same // happens at run-time so that's okay. <del> 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.abi </del> <ins> match self.size_and_align_of(&base.meta, &field_layout)? { Some((_, align)) => (base.meta, offset.align_to(align)), None => { // For unsized types with an extern type tail we perform no adjustments. // NOTE: keep this in sync with `PlaceRef::project_field` in the codegen backend. assert!(matches!(base.meta, MemPlaceMeta::None)); (base.meta, offset) </ins> } <del> None => span_bug!( self.cur_span(), "cannot compute offset for extern type field at non-0 offset" ), }; (base.meta, offset.align_to(align)) </del> <ins> } </ins> } else { // base.meta could be present; we might be accessing a sized field of an unsized // struct.

<ins> // run-pass // // Test that we can handle unsized types with an extern type tail part. // Regression test for issue #91827. #![feature(const_ptr_offset_from)] #![feature(const_slice_from_raw_parts)] #![feature(extern_types)] use std::ptr::addr_of; extern "C" { type Opaque; } unsafe impl Sync for Opaque {} #[repr(C)] pub struct List<T> { len: usize, data: [T; 0], tail: Opaque, } #[repr(C)] pub struct ListImpl<T, const N: usize> { len: usize, data: [T; N], } impl<T> List<T> { const fn as_slice(&self) -> &[T] { unsafe { std::slice::from_raw_parts(self.data.as_ptr(), self.len) } } } impl<T, const N: usize> ListImpl<T, N> { const fn as_list(&self) -> &List<T> { unsafe { std::mem::transmute(self) } } } pub static A: ListImpl<u128, 3> = ListImpl { len: 3, data: [5, 6, 7], }; pub static A_REF: &'static List<u128> = A.as_list(); pub static A_TAIL_OFFSET: isize = tail_offset(A.as_list()); const fn tail_offset<T>(list: &List<T>) -> isize { unsafe { (addr_of!(list.tail) as *const u8).offset_from(list as *const List<T> as *const u8) } } fn main() { assert_eq!(A_REF.as_slice(), &[5, 6, 7]); // Check that interpreter and code generation agree about the position of the tail field. assert_eq!(A_TAIL_OFFSET, tail_offset(A_REF)); } </ins>