diff --git a/compiler/rustc_middle/src/query/erase.rs b/compiler/rustc_middle/src/query/erase.rs index 81c3c7baa07af..7a31682b4ad98 100644 --- a/compiler/rustc_middle/src/query/erase.rs +++ b/compiler/rustc_middle/src/query/erase.rs @@ -109,8 +109,6 @@ pub fn restore_val(erased_value: Erased) -> T { unsafe { transmute_unchecked::, T>(data) } } -// FIXME(#151565): Using `T: ?Sized` here should let us remove the separate -// impls for fat reference types. impl Erasable for &'_ T { type Storage = [u8; size_of::<&'_ ()>()]; } @@ -119,12 +117,14 @@ impl Erasable for &'_ [T] { type Storage = [u8; size_of::<&'_ [()]>()]; } -impl Erasable for &'_ ty::List { - type Storage = [u8; size_of::<&'_ ty::List<()>>()]; -} - -impl Erasable for &'_ ty::ListWithCachedTypeInfo { - type Storage = [u8; size_of::<&'_ ty::ListWithCachedTypeInfo<()>>()]; +// Note: this impl does not overlap with the impl for `&'_ T` above because `RawList` is unsized +// and does not satisfy the implicit `T: Sized` bound. +// +// Furthermore, even if that implicit bound was removed (by adding `T: ?Sized`) this impl still +// wouldn't overlap because `?Sized` is equivalent to `MetaSized` and `RawList` does not satisfy +// `MetaSized` because it contains an extern type. +impl Erasable for &'_ ty::RawList { + type Storage = [u8; size_of::<&'_ ty::RawList<(), ()>>()]; } impl Erasable for Result<&'_ T, traits::query::NoSolution> { diff --git a/compiler/rustc_middle/src/ty/list.rs b/compiler/rustc_middle/src/ty/list.rs index 82c23abefce45..a2bbc1ec75b99 100644 --- a/compiler/rustc_middle/src/ty/list.rs +++ b/compiler/rustc_middle/src/ty/list.rs @@ -37,7 +37,18 @@ pub type List = RawList<(), T>; #[repr(C)] pub struct RawList { skel: ListSkeleton, - opaque: OpaqueListContents, + + // `List`/`RawList` is variable-sized. So we want it to be an unsized + // type because calling `size_of::>` would be dangerous. + // + // We also want `&List`/`&RawList` to be thin pointers. + // + // A field with an extern type is a hacky way to achieve this. (See + // https://github.com/rust-lang/rust/pull/154399#issuecomment-4157036415 + // for some discussion.) This field is never directly manipulated because + // `RawList` instances are created with manual memory layout in + // `from_arena`. + _extern_ty: ExternTy, } /// A [`RawList`] without the unsized tail. This type is used for layout computation @@ -47,7 +58,8 @@ struct ListSkeleton { header: H, len: usize, /// Although this claims to be a zero-length array, in practice `len` - /// elements are actually present. + /// elements are actually present. This is achieved with manual memory + /// layout in `from_arena`. See also the comment on `RawList::_extern_ty`. data: [T; 0], } @@ -58,9 +70,7 @@ impl Default for &List { } unsafe extern "C" { - /// A dummy type used to force `List` to be unsized while not requiring - /// references to it be wide pointers. - type OpaqueListContents; + type ExternTy; } impl RawList { @@ -257,12 +267,13 @@ impl<'a, H, T: Copy> IntoIterator for &'a RawList { unsafe impl Sync for RawList {} -// We need this since `List` uses extern type `OpaqueListContents`. +// We need this because `List` uses the extern type `ExternTy`. unsafe impl DynSync for RawList {} // Safety: -// Layouts of `ListSkeleton` and `RawList` are the same, modulo opaque tail, -// thus aligns of `ListSkeleton` and `RawList` must be the same. +// Layouts of `ListSkeleton` and `RawList` are the same, modulo the +// `_extern_ty` field (which is never instantiated in practice). Therefore, +// aligns of `ListSkeleton` and `RawList` must be the same. unsafe impl Aligned for RawList { #[cfg(bootstrap)] const ALIGN: ptr::Alignment = align_of::>(); @@ -310,3 +321,14 @@ impl<'tcx> From>> for TypeInfo { } } } + +#[cfg(target_pointer_width = "64")] +mod size_asserts { + use rustc_data_structures::static_assert_size; + + use super::*; + // tidy-alphabetical-start + static_assert_size!(&List, 8); // thin pointer + static_assert_size!(&RawList, 8); // thin pointer + // tidy-alphabetical-end +} diff --git a/compiler/rustc_middle/src/ty/mod.rs b/compiler/rustc_middle/src/ty/mod.rs index 674799cb41bad..822bbe079327f 100644 --- a/compiler/rustc_middle/src/ty/mod.rs +++ b/compiler/rustc_middle/src/ty/mod.rs @@ -85,6 +85,7 @@ pub use self::context::{ }; pub use self::fold::*; pub use self::instance::{Instance, InstanceKind, ReifyReason}; +pub(crate) use self::list::RawList; pub use self::list::{List, ListWithCachedTypeInfo}; pub use self::opaque_types::OpaqueTypeKey; pub use self::pattern::{Pattern, PatternKind};