abi_stable/
marker_type.rs

1//! Zero-sized types .
2
3use std::{cell::Cell, marker::PhantomData, rc::Rc};
4
5use crate::{
6    abi_stability::PrefixStableAbi,
7    derive_macro_reexports::*,
8    type_layout::{GenericTLData, MonoTLData, MonoTypeLayout, ReprAttr, TypeLayout},
9};
10
11#[macro_use]
12mod stable_abi_impls;
13
14/////////////////
15
16/// Marker type used to mark a type as being `Send + Sync`.
17#[repr(C)]
18#[derive(StableAbi)]
19pub struct SyncSend;
20
21const _: () = zst_assert! {SyncSend};
22
23/////////////////
24
25/// Marker type used to mark a type as being `!Send + !Sync`.
26pub struct UnsyncUnsend {
27    _marker: UnsafeIgnoredType<Rc<()>>,
28}
29
30monomorphic_marker_type! {UnsyncUnsend, UnsafeIgnoredType<Rc<()>>}
31
32impl UnsyncUnsend {
33    /// Constructs a `UnsyncUnsend`
34    pub const NEW: Self = Self {
35        _marker: UnsafeIgnoredType::NEW,
36    };
37}
38
39/////////////////
40
41/// Marker type used to mark a type as being `Send + !Sync`.
42pub struct UnsyncSend {
43    _marker: UnsafeIgnoredType<Cell<()>>,
44}
45
46monomorphic_marker_type! {UnsyncSend, UnsafeIgnoredType<Cell<()>>}
47
48impl UnsyncSend {
49    /// Constructs a `UnsyncSend`
50    pub const NEW: Self = Self {
51        _marker: UnsafeIgnoredType::NEW,
52    };
53}
54
55/////////////////
56
57/// Marker type used to mark a type as being `!Send + Sync`.
58// #[sabi(debug_print)]
59pub struct SyncUnsend {
60    _marker: UnsyncUnsend,
61}
62
63monomorphic_marker_type! {SyncUnsend, UnsyncUnsend}
64
65impl SyncUnsend {
66    /// Constructs a `SyncUnsend`
67    pub const NEW: Self = Self {
68        _marker: UnsyncUnsend::NEW,
69    };
70}
71
72unsafe impl Sync for SyncUnsend {}
73
74/////////////////
75
76/// Zero-sized marker type used to signal that even though a type
77/// could implement `Copy` and `Clone`,
78/// it is semantically an error to do so.
79#[repr(C)]
80#[derive(StableAbi)]
81// #[sabi(debug_print)]
82pub struct NotCopyNotClone;
83
84const _: () = zst_assert! {NotCopyNotClone};
85
86//////////////////////////////////////////////////////////////
87
88/// Used by vtables/pointers to signal that the type has been erased.
89///
90#[repr(C)]
91#[derive(StableAbi)]
92pub struct ErasedObject<T = ()> {
93    _marker: NonOwningPhantom<T>,
94}
95
96const _: () = zst_assert! {ErasedObject};
97
98//////////////////////////////////////////////////////////////
99
100/// Used by pointers to vtables/modules to signal that the type has been erased.
101///
102pub struct ErasedPrefix {
103    _priv: PhantomData<u8>,
104}
105
106const _: () = zst_assert!(ErasedPrefix);
107
108unsafe impl GetStaticEquivalent_ for ErasedPrefix {
109    type StaticEquivalent = ErasedPrefix;
110}
111
112unsafe impl PrefixStableAbi for ErasedPrefix {
113    type IsNonZeroType = False;
114    const LAYOUT: &'static TypeLayout = <ErasedObject as StableAbi>::LAYOUT;
115}
116
117//////////////////////////////////////////////////////////////
118
119/// MarkerType which ignores its type parameter in its [`StableAbi`] implementation.
120///
121/// # Safety
122///
123/// `Unsafe` is part of its name,
124/// because users can violate memory safety
125/// if they depend on the value of the type parameter passed to `UnsafeIgnoredType` for safety,
126/// since the type parameter is ignored when type checking dynamic libraries.
127///
128///
129/// [`StableAbi`]: ../trait.StableAbi.html
130///
131pub struct UnsafeIgnoredType<T: ?Sized> {
132    /// This field must be public to promise (for semver) that a repr change would be a breaking
133    /// change (see <https://github.com/rust-lang/rust/issues/78586>), which is important as this is
134    /// used as a zero-sized type in `repr(transparent)` structs.
135    pub _inner: PhantomData<T>,
136}
137
138impl<T: ?Sized> UnsafeIgnoredType<T> {
139    /// Constructs an `UnsafeIgnoredType`.
140    pub const DEFAULT: Self = Self {
141        _inner: PhantomData,
142    };
143
144    /// Constructs an `UnsafeIgnoredType`.
145    pub const NEW: Self = Self {
146        _inner: PhantomData,
147    };
148}
149
150impl<T: ?Sized> Copy for UnsafeIgnoredType<T> {}
151
152impl<T: ?Sized> Default for UnsafeIgnoredType<T> {
153    fn default() -> Self {
154        Self::DEFAULT
155    }
156}
157
158impl<T: ?Sized> Clone for UnsafeIgnoredType<T> {
159    fn clone(&self) -> Self {
160        *self
161    }
162}
163
164unsafe impl<T> GetStaticEquivalent_ for UnsafeIgnoredType<T> {
165    type StaticEquivalent = ();
166}
167unsafe impl<T> StableAbi for UnsafeIgnoredType<T> {
168    type IsNonZeroType = False;
169
170    const LAYOUT: &'static TypeLayout = {
171        const MONO_TYPE_LAYOUT: &MonoTypeLayout = &MonoTypeLayout::new(
172            *mono_shared_vars,
173            rstr!("UnsafeIgnoredType"),
174            make_item_info!(),
175            MonoTLData::struct_(rslice![]),
176            tl_genparams!(;;),
177            ReprAttr::C,
178            ModReflMode::Module,
179            rslice![],
180        );
181
182        make_shared_vars! {
183            impl[T] UnsafeIgnoredType<T>;
184
185            let (mono_shared_vars,shared_vars)={};
186        }
187
188        zst_assert!(Self);
189
190        &TypeLayout::from_std::<Self>(
191            shared_vars,
192            MONO_TYPE_LAYOUT,
193            Self::ABI_CONSTS,
194            GenericTLData::Struct,
195        )
196    };
197}
198
199//////////////////////////////////////////////////////////////
200
201/// An ffi-safe equivalent of a `PhantomData<fn()->T>`
202pub struct NonOwningPhantom<T: ?Sized> {
203    // The StableAbi layout for a `NonOwningPhantom<T>` is the same as `PhantomData<T>`,
204    // the type of this field is purely for variance.
205    _marker: PhantomData<extern "C" fn() -> T>,
206}
207
208impl<T: ?Sized> NonOwningPhantom<T> {
209    /// Constructs a `NonOwningPhantom`
210    pub const DEFAULT: Self = Self {
211        _marker: PhantomData,
212    };
213
214    /// Constructs a `NonOwningPhantom`
215    pub const NEW: Self = Self {
216        _marker: PhantomData,
217    };
218}
219
220impl<T: ?Sized> Copy for NonOwningPhantom<T> {}
221
222impl<T: ?Sized> Default for NonOwningPhantom<T> {
223    #[inline(always)]
224    fn default() -> Self {
225        Self::DEFAULT
226    }
227}
228
229impl<T: ?Sized> Clone for NonOwningPhantom<T> {
230    #[inline(always)]
231    fn clone(&self) -> Self {
232        *self
233    }
234}
235
236unsafe impl<T: ?Sized> GetStaticEquivalent_ for NonOwningPhantom<T>
237where
238    PhantomData<T>: GetStaticEquivalent_,
239{
240    type StaticEquivalent = GetStaticEquivalent<PhantomData<T>>;
241}
242
243unsafe impl<T: ?Sized> StableAbi for NonOwningPhantom<T>
244where
245    PhantomData<T>: StableAbi,
246{
247    type IsNonZeroType = False;
248
249    const LAYOUT: &'static TypeLayout = {
250        zst_assert!(Self);
251        <PhantomData<T> as StableAbi>::LAYOUT
252    };
253}