Skip to content
/ rust Public
forked from rust-lang/rust

Commit 21b7360

Browse files
committed
Initial UnsafePinned/UnsafeUnpin impl [Part 1: Libs]
1 parent ae06b79 commit 21b7360

File tree

11 files changed

+290
-8
lines changed

11 files changed

+290
-8
lines changed

compiler/rustc_abi/src/layout.rs

+4-4
Original file line numberDiff line numberDiff line change
@@ -315,7 +315,7 @@ impl<Cx: HasDataLayout> LayoutCalculator<Cx> {
315315
repr: &ReprOptions,
316316
variants: &IndexSlice<VariantIdx, IndexVec<FieldIdx, F>>,
317317
is_enum: bool,
318-
is_unsafe_cell: bool,
318+
is_special_no_niche: bool,
319319
scalar_valid_range: (Bound<u128>, Bound<u128>),
320320
discr_range_of_repr: impl Fn(i128, i128) -> (Integer, bool),
321321
discriminants: impl Iterator<Item = (VariantIdx, i128)>,
@@ -348,7 +348,7 @@ impl<Cx: HasDataLayout> LayoutCalculator<Cx> {
348348
repr,
349349
variants,
350350
is_enum,
351-
is_unsafe_cell,
351+
is_special_no_niche,
352352
scalar_valid_range,
353353
always_sized,
354354
present_first,
@@ -505,7 +505,7 @@ impl<Cx: HasDataLayout> LayoutCalculator<Cx> {
505505
repr: &ReprOptions,
506506
variants: &IndexSlice<VariantIdx, IndexVec<FieldIdx, F>>,
507507
is_enum: bool,
508-
is_unsafe_cell: bool,
508+
is_special_no_niche: bool,
509509
scalar_valid_range: (Bound<u128>, Bound<u128>),
510510
always_sized: bool,
511511
present_first: VariantIdx,
@@ -524,7 +524,7 @@ impl<Cx: HasDataLayout> LayoutCalculator<Cx> {
524524
let mut st = self.univariant(&variants[v], repr, kind)?;
525525
st.variants = Variants::Single { index: v };
526526

527-
if is_unsafe_cell {
527+
if is_special_no_niche {
528528
let hide_niches = |scalar: &mut _| match scalar {
529529
Scalar::Initialized { value, valid_range } => {
530530
*valid_range = WrappingRange::full(value.size(dl))

compiler/rustc_hir/src/lang_items.rs

+3
Original file line numberDiff line numberDiff line change
@@ -182,6 +182,7 @@ language_item_table! {
182182
DynMetadata, sym::dyn_metadata, dyn_metadata, Target::Struct, GenericRequirement::None;
183183

184184
Freeze, sym::freeze, freeze_trait, Target::Trait, GenericRequirement::Exact(0);
185+
UnsafeUnpin, sym::unsafe_unpin, unsafe_unpin_trait, Target::Trait, GenericRequirement::Exact(0);
185186

186187
FnPtrTrait, sym::fn_ptr_trait, fn_ptr_trait, Target::Trait, GenericRequirement::Exact(0);
187188
FnPtrAddr, sym::fn_ptr_addr, fn_ptr_addr, Target::Method(MethodKind::Trait { body: false }), GenericRequirement::None;
@@ -235,6 +236,8 @@ language_item_table! {
235236
IndexMut, sym::index_mut, index_mut_trait, Target::Trait, GenericRequirement::Exact(1);
236237

237238
UnsafeCell, sym::unsafe_cell, unsafe_cell_type, Target::Struct, GenericRequirement::None;
239+
UnsafePinned, sym::unsafe_pinned, unsafe_pinned_type, Target::Struct, GenericRequirement::None;
240+
238241
VaList, sym::va_list, va_list, Target::Struct, GenericRequirement::None;
239242

240243
Deref, sym::deref, deref_trait, Target::Trait, GenericRequirement::Exact(0);

compiler/rustc_lint/src/types.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -864,8 +864,8 @@ fn ty_is_known_nonnull<'tcx>(
864864
return true;
865865
}
866866

867-
// `UnsafeCell` has its niche hidden.
868-
if def.is_unsafe_cell() {
867+
// `UnsafeCell` and `UnsafePinned` have their niche hidden.
868+
if def.is_unsafe_cell() || def.is_unsafe_pinned() {
869869
return false;
870870
}
871871

compiler/rustc_middle/src/ty/adt.rs

+13
Original file line numberDiff line numberDiff line change
@@ -53,6 +53,10 @@ bitflags::bitflags! {
5353
const IS_VARIANT_LIST_NON_EXHAUSTIVE = 1 << 8;
5454
/// Indicates whether the type is `UnsafeCell`.
5555
const IS_UNSAFE_CELL = 1 << 9;
56+
/// Indicates whether the type is `UnsafePinned`.
57+
const IS_UNSAFE_PINNED = 1 << 10;
58+
/// Indicates whether the type is anonymous.
59+
const IS_ANONYMOUS = 1 << 11;
5660
}
5761
}
5862
rustc_data_structures::external_bitflags_debug! { AdtFlags }
@@ -302,6 +306,9 @@ impl AdtDefData {
302306
if tcx.is_lang_item(did, LangItem::UnsafeCell) {
303307
flags |= AdtFlags::IS_UNSAFE_CELL;
304308
}
309+
if tcx.is_lang_item(did, LangItem::UnsafePinned) {
310+
flags |= AdtFlags::IS_UNSAFE_PINNED;
311+
}
305312

306313
AdtDefData { did, variants, flags, repr }
307314
}
@@ -405,6 +412,12 @@ impl<'tcx> AdtDef<'tcx> {
405412
self.flags().contains(AdtFlags::IS_UNSAFE_CELL)
406413
}
407414

415+
/// Returns `true` if this is `UnsafePinned<T>`.
416+
#[inline]
417+
pub fn is_unsafe_pinned(self) -> bool {
418+
self.flags().contains(AdtFlags::IS_UNSAFE_PINNED)
419+
}
420+
408421
/// Returns `true` if this is `ManuallyDrop<T>`.
409422
#[inline]
410423
pub fn is_manually_drop(self) -> bool {

compiler/rustc_span/src/symbol.rs

+2
Original file line numberDiff line numberDiff line change
@@ -2215,6 +2215,8 @@ symbols! {
22152215
unsafe_fields,
22162216
unsafe_no_drop_flag,
22172217
unsafe_pin_internals,
2218+
unsafe_pinned,
2219+
unsafe_unpin,
22182220
unsize,
22192221
unsized_const_param_ty,
22202222
unsized_const_params,

compiler/rustc_ty_utils/src/layout.rs

+5-2
Original file line numberDiff line numberDiff line change
@@ -514,6 +514,9 @@ fn layout_of_uncached<'tcx>(
514514
return map_layout(cx.calc.layout_of_union(&def.repr(), &variants));
515515
}
516516

517+
// UnsafeCell and UnsafePinned both disable niche optimizations
518+
let is_special_no_niche = def.is_unsafe_cell() || def.is_unsafe_pinned();
519+
517520
let get_discriminant_type =
518521
|min, max| abi::Integer::repr_discr(tcx, ty, &def.repr(), min, max);
519522

@@ -542,7 +545,7 @@ fn layout_of_uncached<'tcx>(
542545
&def.repr(),
543546
&variants,
544547
def.is_enum(),
545-
def.is_unsafe_cell(),
548+
is_special_no_niche,
546549
tcx.layout_scalar_valid_range(def.did()),
547550
get_discriminant_type,
548551
discriminants_iter(),
@@ -568,7 +571,7 @@ fn layout_of_uncached<'tcx>(
568571
&def.repr(),
569572
&variants,
570573
def.is_enum(),
571-
def.is_unsafe_cell(),
574+
is_special_no_niche,
572575
tcx.layout_scalar_valid_range(def.did()),
573576
get_discriminant_type,
574577
discriminants_iter(),

library/core/src/lib.rs

+1
Original file line numberDiff line numberDiff line change
@@ -127,6 +127,7 @@
127127
#![feature(ub_checks)]
128128
#![feature(unchecked_neg)]
129129
#![feature(unchecked_shifts)]
130+
#![feature(unsafe_pinned)]
130131
#![feature(utf16_extra)]
131132
#![feature(variant_count)]
132133
// tidy-alphabetical-end

library/core/src/marker.rs

+29
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@ use crate::cell::UnsafeCell;
1717
use crate::cmp;
1818
use crate::fmt::Debug;
1919
use crate::hash::{Hash, Hasher};
20+
use crate::pin::UnsafePinned;
2021

2122
/// Implements a given marker trait for multiple types at the same time.
2223
///
@@ -878,6 +879,23 @@ marker_impls! {
878879
{T: ?Sized} &mut T,
879880
}
880881

882+
/// Used to determine whether a type contains any `UnsafePinned` (or `PhantomPinned`) internally,
883+
/// but not through an indirection. This affects, for example, whether we emit `noalias` metadata
884+
/// for `&mut T` or not.
885+
///
886+
/// This is part of [RFC 3467](https://rust-lang.github.io/rfcs/3467-unsafe-pinned.html), and is
887+
/// tracked by [#125735](https://github.com/rust-lang/rust/issues/125735).
888+
#[cfg_attr(not(bootstrap), lang = "unsafe_unpin")]
889+
#[cfg_attr(bootstrap, allow(dead_code))]
890+
pub(crate) unsafe auto trait UnsafeUnpin {}
891+
892+
impl<T: ?Sized> !UnsafeUnpin for UnsafePinned<T> {}
893+
unsafe impl<T: ?Sized> UnsafeUnpin for PhantomData<T> {}
894+
unsafe impl<T: ?Sized> UnsafeUnpin for *const T {}
895+
unsafe impl<T: ?Sized> UnsafeUnpin for *mut T {}
896+
unsafe impl<T: ?Sized> UnsafeUnpin for &T {}
897+
unsafe impl<T: ?Sized> UnsafeUnpin for &mut T {}
898+
881899
/// Types that do not require any pinning guarantees.
882900
///
883901
/// For information on what "pinning" is, see the [`pin` module] documentation.
@@ -953,13 +971,24 @@ pub auto trait Unpin {}
953971
/// A marker type which does not implement `Unpin`.
954972
///
955973
/// If a type contains a `PhantomPinned`, it will not implement `Unpin` by default.
974+
//
975+
// FIXME(unsafe_pinned): This is *not* a stable guarantee we want to make, at least not yet.
976+
// Note that for backwards compatibility with the new [`UnsafePinned`] wrapper type, placing this
977+
// marker in your struct acts as if you wrapped the entire struct in an `UnsafePinned`. This type
978+
// will likely eventually be deprecated, and all new code should be using `UnsafePinned` instead.
956979
#[stable(feature = "pin", since = "1.33.0")]
957980
#[derive(Debug, Default, Copy, Clone, Eq, PartialEq, Ord, PartialOrd, Hash)]
958981
pub struct PhantomPinned;
959982

960983
#[stable(feature = "pin", since = "1.33.0")]
961984
impl !Unpin for PhantomPinned {}
962985

986+
// This is a small hack to allow existing code which uses PhantomPinned to opt-out of noalias to
987+
// continue working. Ideally PhantomPinned could just wrap an `UnsafePinned<()>` to get the same
988+
// effect, but we can't add a new field to an already stable unit struct -- that would be a breaking
989+
// change.
990+
impl !UnsafeUnpin for PhantomPinned {}
991+
963992
marker_impls! {
964993
#[stable(feature = "pin", since = "1.33.0")]
965994
Unpin for

library/core/src/pin.rs

+5
Original file line numberDiff line numberDiff line change
@@ -931,6 +931,11 @@ use crate::{
931931
};
932932
use crate::{cmp, fmt};
933933

934+
mod unsafe_pinned;
935+
936+
#[unstable(feature = "unsafe_pinned", issue = "125735")]
937+
pub use self::unsafe_pinned::UnsafePinned;
938+
934939
/// A pointer which pins its pointee in place.
935940
///
936941
/// [`Pin`] is a wrapper around some kind of pointer `Ptr` which makes that pointer "pin" its

0 commit comments

Comments
 (0)