1
Fork 0

Rollup merge of #137043 - Sky9x:unsafe-pinned-pt1-libs, r=tgross35,RalfJung,WaffleLapkin

Initial `UnsafePinned` implementation [Part 1: Libs]

Initial libs changes necessary to unblock further work on [RFC 3467](https://rust-lang.github.io/rfcs/3467-unsafe-pinned.html).
Tracking issue: #125735

This PR is split off from #136964, and includes just the libs changes:
- `UnsafePinned` struct
- private `UnsafeUnpin` structural auto trait
- Lang items for both
- Compiler changes necessary to block niches on `UnsafePinned`

This PR does not change codegen, miri, the existing `!Unpin` hack, or anything else. That work is to be split into later PRs.

---

cc ``@RalfJung`` ``@Noratrieb``

``@rustbot`` label F-unsafe_pinned T-libs-api
This commit is contained in:
Jacob Pratt 2025-04-13 17:37:51 -04:00 committed by GitHub
commit d04df1cba9
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
11 changed files with 290 additions and 8 deletions

View file

@ -315,7 +315,7 @@ impl<Cx: HasDataLayout> LayoutCalculator<Cx> {
repr: &ReprOptions,
variants: &IndexSlice<VariantIdx, IndexVec<FieldIdx, F>>,
is_enum: bool,
is_unsafe_cell: bool,
is_special_no_niche: bool,
scalar_valid_range: (Bound<u128>, Bound<u128>),
discr_range_of_repr: impl Fn(i128, i128) -> (Integer, bool),
discriminants: impl Iterator<Item = (VariantIdx, i128)>,
@ -348,7 +348,7 @@ impl<Cx: HasDataLayout> LayoutCalculator<Cx> {
repr,
variants,
is_enum,
is_unsafe_cell,
is_special_no_niche,
scalar_valid_range,
always_sized,
present_first,
@ -505,7 +505,7 @@ impl<Cx: HasDataLayout> LayoutCalculator<Cx> {
repr: &ReprOptions,
variants: &IndexSlice<VariantIdx, IndexVec<FieldIdx, F>>,
is_enum: bool,
is_unsafe_cell: bool,
is_special_no_niche: bool,
scalar_valid_range: (Bound<u128>, Bound<u128>),
always_sized: bool,
present_first: VariantIdx,
@ -524,7 +524,7 @@ impl<Cx: HasDataLayout> LayoutCalculator<Cx> {
let mut st = self.univariant(&variants[v], repr, kind)?;
st.variants = Variants::Single { index: v };
if is_unsafe_cell {
if is_special_no_niche {
let hide_niches = |scalar: &mut _| match scalar {
Scalar::Initialized { value, valid_range } => {
*valid_range = WrappingRange::full(value.size(dl))

View file

@ -182,6 +182,7 @@ language_item_table! {
DynMetadata, sym::dyn_metadata, dyn_metadata, Target::Struct, GenericRequirement::None;
Freeze, sym::freeze, freeze_trait, Target::Trait, GenericRequirement::Exact(0);
UnsafeUnpin, sym::unsafe_unpin, unsafe_unpin_trait, Target::Trait, GenericRequirement::Exact(0);
FnPtrTrait, sym::fn_ptr_trait, fn_ptr_trait, Target::Trait, GenericRequirement::Exact(0);
FnPtrAddr, sym::fn_ptr_addr, fn_ptr_addr, Target::Method(MethodKind::Trait { body: false }), GenericRequirement::None;
@ -235,6 +236,8 @@ language_item_table! {
IndexMut, sym::index_mut, index_mut_trait, Target::Trait, GenericRequirement::Exact(1);
UnsafeCell, sym::unsafe_cell, unsafe_cell_type, Target::Struct, GenericRequirement::None;
UnsafePinned, sym::unsafe_pinned, unsafe_pinned_type, Target::Struct, GenericRequirement::None;
VaList, sym::va_list, va_list, Target::Struct, GenericRequirement::None;
Deref, sym::deref, deref_trait, Target::Trait, GenericRequirement::Exact(0);

View file

@ -864,8 +864,8 @@ fn ty_is_known_nonnull<'tcx>(
return true;
}
// `UnsafeCell` has its niche hidden.
if def.is_unsafe_cell() {
// `UnsafeCell` and `UnsafePinned` have their niche hidden.
if def.is_unsafe_cell() || def.is_unsafe_pinned() {
return false;
}

View file

@ -53,6 +53,10 @@ bitflags::bitflags! {
const IS_VARIANT_LIST_NON_EXHAUSTIVE = 1 << 8;
/// Indicates whether the type is `UnsafeCell`.
const IS_UNSAFE_CELL = 1 << 9;
/// Indicates whether the type is `UnsafePinned`.
const IS_UNSAFE_PINNED = 1 << 10;
/// Indicates whether the type is anonymous.
const IS_ANONYMOUS = 1 << 11;
}
}
rustc_data_structures::external_bitflags_debug! { AdtFlags }
@ -302,6 +306,9 @@ impl AdtDefData {
if tcx.is_lang_item(did, LangItem::UnsafeCell) {
flags |= AdtFlags::IS_UNSAFE_CELL;
}
if tcx.is_lang_item(did, LangItem::UnsafePinned) {
flags |= AdtFlags::IS_UNSAFE_PINNED;
}
AdtDefData { did, variants, flags, repr }
}
@ -405,6 +412,12 @@ impl<'tcx> AdtDef<'tcx> {
self.flags().contains(AdtFlags::IS_UNSAFE_CELL)
}
/// Returns `true` if this is `UnsafePinned<T>`.
#[inline]
pub fn is_unsafe_pinned(self) -> bool {
self.flags().contains(AdtFlags::IS_UNSAFE_PINNED)
}
/// Returns `true` if this is `ManuallyDrop<T>`.
#[inline]
pub fn is_manually_drop(self) -> bool {

View file

@ -2215,6 +2215,8 @@ symbols! {
unsafe_fields,
unsafe_no_drop_flag,
unsafe_pin_internals,
unsafe_pinned,
unsafe_unpin,
unsize,
unsized_const_param_ty,
unsized_const_params,

View file

@ -514,6 +514,9 @@ fn layout_of_uncached<'tcx>(
return map_layout(cx.calc.layout_of_union(&def.repr(), &variants));
}
// UnsafeCell and UnsafePinned both disable niche optimizations
let is_special_no_niche = def.is_unsafe_cell() || def.is_unsafe_pinned();
let get_discriminant_type =
|min, max| abi::Integer::repr_discr(tcx, ty, &def.repr(), min, max);
@ -542,7 +545,7 @@ fn layout_of_uncached<'tcx>(
&def.repr(),
&variants,
def.is_enum(),
def.is_unsafe_cell(),
is_special_no_niche,
tcx.layout_scalar_valid_range(def.did()),
get_discriminant_type,
discriminants_iter(),
@ -568,7 +571,7 @@ fn layout_of_uncached<'tcx>(
&def.repr(),
&variants,
def.is_enum(),
def.is_unsafe_cell(),
is_special_no_niche,
tcx.layout_scalar_valid_range(def.did()),
get_discriminant_type,
discriminants_iter(),