Skip to main content

rust_spec/
lib.rs

1//! **Compile-time classification of types** according to the Rust specification.
2//!
3//! # Classification Axes
4//!
5//! [`RustSpec`] describes a type across the following axes:
6//! - [`layout`]: representation stability.
7//! - [`size`]: statically sized, metadata-sized, or extern-type-like shape.
8//! - `alignment`: whether ABI alignment is one or greater than one.
9//! - [`trap`](layout): whether the value representation has trap values.
10//! - [`niche`]: whether a type has a stable, unstable, or no niche value.
11//! - [`drop`](mod@drop): whether dropping runs custom or compiler-generated code.
12//!
13//! ## Layout
14//!
15//! Describes total reachable (through pointer indirection) representation stability:
16//! - [`Stable`]: compiler-guaranteed representation.
17//! - [`Unstable`]: representation is not guaranteed.
18//!
19//! ## Size
20//!
21//! Describes compile-time size and pointer metadata shape:
22//! - [`Sized`](size::Sized)<[`Zero`]>: compile-time known zero-sized type.
23//! - [`Sized`](size::Sized)<[`Gt`]<[`Zero`]>>: compile-time known non-zero-sized type.
24//! - [`MetaSized`](size::MetaSized)<[`SliceLike`](size::SliceLike)>: dynamically sized slice-like type.
25//! - [`MetaSized`](size::MetaSized)<[`DynTraitLike`](size::DynTraitLike)>: dynamically sized trait-object-like type.
26//! - [`ExternTypeLike`](size::ExternTypeLike): dynamically sized extern-type-like type.
27//! - [`NulTerminated`](size::NulTerminated): unsized nul-terminated data.
28//!
29//! ## Alignment
30//!
31//! - [`One`] means ABI alignment is exactly one;
32//! - [`Gt`]<[`One`]> means it is greater than one.
33//!
34//! ## Trap
35//!
36//! Describes total reachable (through pointer indirection) value-representation validity:
37//! - [`Robust`](layout::Robust): every bit pattern is valid.
38//! - [`NonRobust`](layout::NonRobust): some bit patterns are trap/invalid values.
39//!
40//! ## Niche
41//!
42//! Describes whether and what kind of niche is available for the type:
43//! - [`WithoutNiche`]: no niche is available.
44//! - [`WithNiche`]<[`Stable`]>: compiler-guaranteed niche.
45//! - [`WithNiche`]<[`Unstable`]>: niche exists but is not guaranteed.
46//!
47//! **Use `#[rust_spec(custom_niche)]` when deriving [`RustSpec`] to select WithNiche<Unstable>**.
48//!
49//! ## Drop
50//!
51//! Describes the type's behavior when dropped:
52//! - [`NoDrop`]: dropping the type runs no drop glue.
53//! - [`AutoDrop`](drop::AutoDrop): owned contents need automatic drop glue.
54//! - [`CustomDrop`]<[`NoDrop`]>: the type implements [`Drop`] and its contents need no automatic drop glue.
55//! - [`CustomDrop`]<[`AutoDrop`](drop::AutoDrop)>: the type implements [`Drop`] and its contents need automatic drop glue.
56//!
57//! **Use `#[rust_spec(custom_drop)]` when deriving [`RustSpec`] for a type that implements `Drop`**.
58//!
59//! ## How to Use
60//!
61//! Derive [`RustSpec`] for your types, then use its associated marker families as bounds when implementing other traits:
62//!
63//! ```rust
64//! # #[cfg(feature = "derive")]
65//! # {
66//! use disjoint_impls::disjoint_impls;
67//! use rust_spec::{RustSpec, Stable, Unstable, niche::{WithNiche, WithoutNiche}};
68//!
69//! #[derive(RustSpec)]
70//! struct Header {
71//!     id: u32,
72//!     flags: u16,
73//! }
74//!
75//! disjoint_impls! {
76//!     trait NullableEncoding {
77//!         const NEEDS_TAG: bool;
78//!     }
79//!
80//!     impl<T: RustSpec<Niche = WithoutNiche>> NullableEncoding for T {
81//!         const NEEDS_TAG: bool = true;
82//!     }
83//!
84//!     impl<T: RustSpec<Niche = WithNiche<Stable>>> NullableEncoding for T {
85//!         const NEEDS_TAG: bool = false;
86//!     }
87//!
88//!     impl<T: RustSpec<Niche = WithNiche<Unstable>>> NullableEncoding for T {
89//!         const NEEDS_TAG: bool = false;
90//!     }
91//! }
92//!
93//! const HEADER_OPTION_NEEDS_TAG: bool = Header::NEEDS_TAG;
94//! # }
95//! ```
96//!
97//! Check out [CO3](https://github.com/mversic/co3) to see how this crate allows for building higher zero-cost abstractions.
98#![no_std]
99
100#[cfg(feature = "alloc")]
101extern crate alloc;
102extern crate self as rust_spec;
103
104#[cfg(feature = "alloc")]
105use alloc::boxed::Box;
106use core::ops::Add;
107
108#[cfg(feature = "alloc")]
109use crate::drop::CustomDrop;
110use crate::{
111    drop::NoDrop,
112    niche::{WithNiche, WithoutNiche},
113    size::{MetadataKind, SizedKind},
114};
115use disjoint_impls::disjoint_impls;
116#[cfg(feature = "derive")]
117pub use rust_spec_derive::RustSpec;
118
119mod core_impls;
120pub mod drop;
121pub mod layout;
122#[doc(hidden)]
123pub mod mutability;
124pub mod niche;
125mod primitives;
126pub mod size;
127mod tuple;
128
129/// Marker for a compiler-guaranteed representation or niche.
130pub enum Stable {}
131
132/// Marker for a representation or niche that is not compiler-guaranteed.
133pub enum Unstable {}
134
135/// Marker for a zero-sized type.
136pub enum Zero {}
137
138/// Marker for a statically sized type greater than the given threshold.
139pub struct Gt<T>(core::marker::PhantomData<T>);
140
141/// Marker for ABI alignment one.
142pub enum One {}
143
144/// Type-level maximum used to combine alignment categories.
145pub trait Max<Rhs> {
146    type Output;
147}
148
149impl<Rhs> Max<Rhs> for One {
150    type Output = Rhs;
151}
152impl<Rhs> Max<Rhs> for Gt<One> {
153    type Output = Gt<One>;
154}
155
156trait WithoutOrUnstableNiche {}
157
158impl WithoutOrUnstableNiche for WithoutNiche {}
159impl WithoutOrUnstableNiche for WithNiche<Stable> {}
160
161/// Opaque, lifetime-indexed field axes emitted by `RustSpec` derives for
162/// projections whose prerequisites are supplied by higher-ranked bounds.
163#[doc(hidden)]
164pub trait __HrtbAxes<const FIELD: usize> {
165    type Layout<'a>;
166    type Size<'a>;
167    type Alignment<'a>;
168    type Trap<'a>;
169    type Niche<'a>;
170    type Drop<'a>;
171    type Mutability<'a>;
172    type __IndirectTrap<'a>;
173}
174
175disjoint_impls! {
176    /// Joined Rust-spec classification of a type.
177    ///
178    /// This is the canonical surface for Rust-specified properties used by
179    /// conversion.
180    ///
181    /// # Safety
182    ///
183    /// Implementors must classify `Self` truthfully according to each axis's documentation.
184    pub unsafe trait RustSpec {
185        /// Representation-stability classification; see [`layout`].
186        type Layout;
187
188        /// Statically known, metadata-sized, or extern-type-like size classification; see [`size`].
189        type Size;
190
191        /// ABI alignment classification; see the [crate root](crate) for [`One`] and [`Gt`].
192        type Alignment;
193
194        /// Trap-representation classification; see [`layout`].
195        type Trap;
196
197        /// Niche availability classification; see [`niche`].
198        type Niche;
199
200        /// Whether `Self` declares `Drop`, has inner drop glue, or has no drop glue; see [`drop`](mod@drop).
201        type Drop;
202
203        /// Shared-access mutability classification; see [`mutability`].
204        #[doc(hidden)]
205        type Mutability;
206
207        /// Trap classification reachable through one or more supported pointer indirections; see [`layout`].
208        #[doc(hidden)]
209        type __IndirectTrap;
210    }
211
212    unsafe impl<R: ?Sized> RustSpec for &R
213    where
214        R: RustSpec<Size: size::Thin>,
215    {
216        type Layout = R::Layout;
217        type Size = size::Sized<Gt<Zero>>;
218        type Alignment = <usize as RustSpec>::Alignment;
219        type Trap = layout::NonRobust;
220        type Niche = WithNiche<Stable>;
221        type Drop = drop::NoDrop;
222        type Mutability = R::Mutability;
223        type __IndirectTrap = R::Trap;
224    }
225    unsafe impl<R: ?Sized, U: MetadataKind> RustSpec for &R
226    where
227        R: RustSpec<Size = size::MetaSized<U>>,
228    {
229        type Layout = Unstable;
230        type Size = size::Sized<Gt<Zero>>;
231        type Alignment = <usize as RustSpec>::Alignment;
232        type Trap = layout::NonRobust;
233        type Niche = WithNiche<Unstable>;
234        type Drop = drop::NoDrop;
235        type Mutability = R::Mutability;
236        type __IndirectTrap = R::Trap;
237    }
238    unsafe impl<R: ?Sized> RustSpec for &R
239    where
240        R: RustSpec<Size = size::NulTerminated>,
241    {
242        type Layout = R::Layout;
243        type Size = size::Sized<Gt<Zero>>;
244        type Alignment = <usize as RustSpec>::Alignment;
245        type Trap = layout::NonRobust;
246        type Niche = WithNiche<Unstable>;
247        type Drop = drop::NoDrop;
248        type Mutability = R::Mutability;
249        type __IndirectTrap = R::Trap;
250    }
251
252    unsafe impl<R: ?Sized> RustSpec for &mut R
253    where
254        R: RustSpec<Size: size::Thin>,
255    {
256        type Layout = R::Layout;
257        type Size = size::Sized<Gt<Zero>>;
258        type Alignment = <usize as RustSpec>::Alignment;
259        type Trap = layout::NonRobust;
260        type Niche = WithNiche<Stable>;
261        type Drop = drop::NoDrop;
262        type Mutability = R::Mutability;
263        type __IndirectTrap = R::Trap;
264    }
265    unsafe impl<R: ?Sized, U: MetadataKind> RustSpec for &mut R
266    where
267        R: RustSpec<Size = size::MetaSized<U>>,
268    {
269        type Layout = Unstable;
270        type Size = size::Sized<Gt<Zero>>;
271        type Alignment = <usize as RustSpec>::Alignment;
272        type Trap = layout::NonRobust;
273        type Niche = WithNiche<Unstable>;
274        type Drop = drop::NoDrop;
275        type Mutability = R::Mutability;
276        type __IndirectTrap = R::Trap;
277    }
278    unsafe impl<R: ?Sized> RustSpec for &mut R
279    where
280        R: RustSpec<Size = size::NulTerminated>,
281    {
282        type Layout = R::Layout;
283        type Size = size::Sized<Gt<Zero>>;
284        type Alignment = <usize as RustSpec>::Alignment;
285        type Trap = layout::NonRobust;
286        type Niche = WithNiche<Unstable>;
287        type Drop = drop::NoDrop;
288        type Mutability = R::Mutability;
289        type __IndirectTrap = R::Trap;
290    }
291
292    #[cfg(feature = "alloc")]
293    unsafe impl<R, S: SizedKind> RustSpec for Box<R>
294    where
295        R: RustSpec<Size = size::Sized<S>>,
296        CustomDrop<NoDrop>: Add<<R as RustSpec>::Drop>,
297        <R as RustSpec>::Drop: Sized,
298    {
299        type Layout = R::Layout;
300        type Size = size::Sized<Gt<Zero>>;
301        type Alignment = <usize as RustSpec>::Alignment;
302        type Trap = layout::NonRobust;
303        type Niche = WithNiche<Stable>;
304        type Drop = <CustomDrop<NoDrop> as Add<R::Drop>>::Output;
305        type Mutability = R::Mutability;
306        type __IndirectTrap = R::Trap;
307    }
308    #[cfg(feature = "alloc")]
309    unsafe impl<R: ?Sized, U: MetadataKind> RustSpec for Box<R>
310    where
311        R: RustSpec<Size = size::MetaSized<U>>,
312        CustomDrop<NoDrop>: Add<<R as RustSpec>::Drop>,
313        <R as RustSpec>::Drop: Sized,
314    {
315        type Layout = Unstable;
316        type Size = size::Sized<Gt<Zero>>;
317        type Alignment = <usize as RustSpec>::Alignment;
318        type Trap = layout::NonRobust;
319        type Niche = WithNiche<Unstable>;
320        type Drop = <CustomDrop<NoDrop> as Add<R::Drop>>::Output;
321        type Mutability = mutability::Exclusive;
322        type __IndirectTrap = R::Trap;
323    }
324    #[cfg(feature = "alloc")]
325    unsafe impl<R: ?Sized> RustSpec for Box<R>
326    where
327        R: RustSpec<Size = size::NulTerminated>,
328        CustomDrop<NoDrop>: Add<<R as RustSpec>::Drop>,
329        <R as RustSpec>::Drop: Sized,
330    {
331        type Layout = R::Layout;
332        type Size = size::Sized<Gt<Zero>>;
333        type Alignment = <usize as RustSpec>::Alignment;
334        type Trap = layout::NonRobust;
335        type Niche = WithNiche<Unstable>;
336        type Drop = <CustomDrop<NoDrop> as Add<R::Drop>>::Output;
337        type Mutability = mutability::Exclusive;
338        type __IndirectTrap = R::Trap;
339    }
340
341    unsafe impl<R> RustSpec for Option<R>
342    where
343        R: RustSpec<Niche = WithoutNiche>,
344        NoDrop: Add<<R as RustSpec>::Drop>,
345        <R as RustSpec>::Drop: Sized,
346    {
347        type Layout = Unstable;
348        type Size = size::Sized<Gt<Zero>>;
349        type Alignment = R::Alignment;
350        type Trap = layout::NonRobust;
351        type Niche = WithNiche<Unstable>;
352        type Drop = <NoDrop as Add<R::Drop>>::Output;
353        type Mutability = mutability::Exclusive;
354        type __IndirectTrap = R::__IndirectTrap;
355    }
356    unsafe impl<R> RustSpec for Option<R>
357    where
358        R: RustSpec<Niche = WithNiche<Unstable>>,
359        NoDrop: Add<<R as RustSpec>::Drop>,
360        <R as RustSpec>::Drop: Sized,
361    {
362        type Layout = Unstable;
363        // FIXME: This can be Robust but we have to track
364        // the number of available custom/unstable niches.
365        // The same thing happens for all other enums
366        type Size = size::Sized<Gt<Zero>>;
367        type Alignment = R::Alignment;
368        type Trap = layout::NonRobust;
369        type Niche = WithNiche<Unstable>;
370        type Drop = <NoDrop as Add<R::Drop>>::Output;
371        type Mutability = mutability::Exclusive;
372        type __IndirectTrap = R::__IndirectTrap;
373    }
374    unsafe impl<R> RustSpec for Option<R>
375    where
376        R: RustSpec<Niche = WithNiche<Stable>>,
377        NoDrop: Add<<R as RustSpec>::Drop>,
378        <R as RustSpec>::Drop: Sized,
379    {
380        type Layout = R::Layout;
381        type Size = size::Sized<Gt<Zero>>;
382        type Alignment = R::Alignment;
383        type Trap = R::__IndirectTrap;
384        type Niche = WithoutNiche;
385        type Drop = <NoDrop as Add<R::Drop>>::Output;
386        type Mutability = mutability::Exclusive;
387        type __IndirectTrap = R::__IndirectTrap;
388    }
389
390    unsafe impl<R, E, K: SizedKind> RustSpec for Result<R, E>
391    where
392        R: RustSpec<Size = size::Sized<K>>,
393        E: RustSpec<Size = size::Sized<K>>,
394        <R as RustSpec>::Niche: WithoutOrUnstableNiche,
395        <E as RustSpec>::Niche: WithoutOrUnstableNiche,
396        <R as RustSpec>::__IndirectTrap: Add<<E as RustSpec>::__IndirectTrap>,
397        <E as RustSpec>::Alignment: Sized,
398        <R as RustSpec>::Alignment: Max<<E as RustSpec>::Alignment>,
399        <R as RustSpec>::Drop: Sized + Add<<E as RustSpec>::Drop>,
400        <E as RustSpec>::Drop: Sized,
401    {
402        type Layout = Unstable;
403        type Size = size::Sized<Gt<Zero>>;
404        type Alignment = <R::Alignment as Max<E::Alignment>>::Output;
405        type Trap = layout::NonRobust;
406        type Niche = WithNiche<Unstable>;
407        type Drop = <R::Drop as Add<E::Drop>>::Output;
408        type Mutability = mutability::Exclusive;
409        type __IndirectTrap = <R::__IndirectTrap as Add<E::__IndirectTrap>>::Output;
410    }
411
412    // TODO: The next 3 impls are the same
413    unsafe impl<R, E> RustSpec for Result<R, E>
414    where
415        R: RustSpec<Size = size::Sized<Gt<Zero>>, Niche = WithoutNiche>,
416        E: RustSpec<Size = size::Sized<Zero>>,
417        <R as RustSpec>::Alignment: Max<<E as RustSpec>::Alignment>,
418        <R as RustSpec>::Drop: Sized + Add<<E as RustSpec>::Drop>,
419        <E as RustSpec>::Alignment: Sized,
420        <E as RustSpec>::Drop: Sized,
421    {
422        type Layout = Unstable;
423        type Size = size::Sized<Gt<Zero>>;
424        type Alignment = <R::Alignment as Max<E::Alignment>>::Output;
425        type Trap = layout::NonRobust;
426        type Niche = WithNiche<Unstable>;
427        type Drop = <R::Drop as Add<E::Drop>>::Output;
428        type Mutability = mutability::Exclusive;
429        type __IndirectTrap = R::__IndirectTrap;
430    }
431    unsafe impl<R, E> RustSpec for Result<R, E>
432    where
433        R: RustSpec<Size = size::Sized<Gt<Zero>>, Niche = WithNiche<Unstable>>,
434        E: RustSpec<Size = size::Sized<Zero>>,
435        <R as RustSpec>::Alignment: Max<<E as RustSpec>::Alignment>,
436        <R as RustSpec>::Drop: Sized + Add<<E as RustSpec>::Drop>,
437        <E as RustSpec>::Alignment: Sized,
438        <E as RustSpec>::Drop: Sized,
439    {
440        type Layout = Unstable;
441        type Size = size::Sized<Gt<Zero>>;
442        type Alignment = <R::Alignment as Max<E::Alignment>>::Output;
443        type Trap = layout::NonRobust;
444        type Niche = WithNiche<Unstable>;
445        type Drop = <R::Drop as Add<E::Drop>>::Output;
446        type Mutability = mutability::Exclusive;
447        type __IndirectTrap = R::__IndirectTrap;
448    }
449    unsafe impl<R, E> RustSpec for Result<R, E>
450    where
451        R: RustSpec<Size = size::Sized<Gt<Zero>>, Niche = WithNiche<Stable>>,
452        E: RustSpec<Size = size::Sized<Zero>, Alignment = Gt<One>>,
453        <E as RustSpec>::Alignment: Sized,
454        <R as RustSpec>::Alignment: Max<<E as RustSpec>::Alignment>,
455        <R as RustSpec>::Drop: Sized + Add<<E as RustSpec>::Drop>,
456        <E as RustSpec>::Drop: Sized,
457    {
458        type Layout = Unstable;
459        type Size = size::Sized<Gt<Zero>>;
460        type Alignment = <R::Alignment as Max<E::Alignment>>::Output;
461        type Trap = layout::NonRobust;
462        type Niche = WithNiche<Unstable>;
463        type Drop = <R::Drop as Add<E::Drop>>::Output;
464        type Mutability = mutability::Exclusive;
465        type __IndirectTrap = R::__IndirectTrap;
466    }
467    unsafe impl<R, E> RustSpec for Result<R, E>
468    where
469        R: RustSpec<Size = size::Sized<Gt<Zero>>, Niche = WithNiche<Stable>>,
470        E: RustSpec<Size = size::Sized<Zero>, Alignment = One>,
471        <R as RustSpec>::Alignment: Max<<E as RustSpec>::Alignment>,
472        <R as RustSpec>::Drop: Sized + Add<<E as RustSpec>::Drop>,
473        <E as RustSpec>::Alignment: Sized,
474        <E as RustSpec>::Drop: Sized,
475    {
476        type Layout = R::Layout;
477        type Size = size::Sized<Gt<Zero>>;
478        type Alignment = <R::Alignment as Max<E::Alignment>>::Output;
479        type Trap = R::__IndirectTrap;
480        type Niche = WithoutNiche;
481        type Drop = <R::Drop as Add<E::Drop>>::Output;
482        type Mutability = mutability::Exclusive;
483        type __IndirectTrap = R::__IndirectTrap;
484    }
485
486    // TODO: The next 3 impls are the same
487    unsafe impl<R, E> RustSpec for Result<R, E>
488    where
489        R: RustSpec<Size = size::Sized<Zero>>,
490        E: RustSpec<Size = size::Sized<Gt<Zero>>, Niche = WithoutNiche>,
491        <R as RustSpec>::Alignment: Sized + Max<<E as RustSpec>::Alignment>,
492        <R as RustSpec>::Drop: Sized + Add<<E as RustSpec>::Drop>,
493        <E as RustSpec>::Alignment: Sized,
494        <E as RustSpec>::Drop: Sized,
495    {
496        type Layout = Unstable;
497        type Size = size::Sized<Gt<Zero>>;
498        type Alignment = <R::Alignment as Max<E::Alignment>>::Output;
499        type Trap = layout::NonRobust;
500        type Niche = WithNiche<Unstable>;
501        type Drop = <R::Drop as Add<E::Drop>>::Output;
502        type Mutability = mutability::Exclusive;
503        type __IndirectTrap = E::__IndirectTrap;
504    }
505    unsafe impl<R, E> RustSpec for Result<R, E>
506    where
507        R: RustSpec<Size = size::Sized<Zero>, Niche: WithoutOrUnstableNiche>,
508        E: RustSpec<Size = size::Sized<Gt<Zero>>, Niche = WithNiche<Unstable>>,
509        <R as RustSpec>::Alignment: Sized + Max<<E as RustSpec>::Alignment>,
510        <R as RustSpec>::Drop: Sized + Add<<E as RustSpec>::Drop>,
511        <E as RustSpec>::Alignment: Sized,
512        <E as RustSpec>::Drop: Sized,
513    {
514        type Layout = Unstable;
515        type Size = size::Sized<Gt<Zero>>;
516        type Alignment = <R::Alignment as Max<E::Alignment>>::Output;
517        type Trap = layout::NonRobust;
518        type Niche = WithNiche<Unstable>;
519        type Drop = <R::Drop as Add<E::Drop>>::Output;
520        type Mutability = mutability::Exclusive;
521        type __IndirectTrap = E::__IndirectTrap;
522    }
523    unsafe impl<R, E> RustSpec for Result<R, E>
524    where
525        R: RustSpec<Size = size::Sized<Zero>, Alignment = Gt<One>>,
526        E: RustSpec<Size = size::Sized<Gt<Zero>>, Niche = WithNiche<Stable>>,
527        <R as RustSpec>::Alignment: Sized + Max<<E as RustSpec>::Alignment>,
528        <R as RustSpec>::Drop: Sized + Add<<E as RustSpec>::Drop>,
529        <E as RustSpec>::Alignment: Sized,
530        <E as RustSpec>::Drop: Sized,
531    {
532        type Layout = Unstable;
533        type Size = size::Sized<Gt<Zero>>;
534        type Alignment = <R::Alignment as Max<E::Alignment>>::Output;
535        type Trap = layout::NonRobust;
536        type Niche = WithNiche<Unstable>;
537        type Drop = <R::Drop as Add<E::Drop>>::Output;
538        type Mutability = mutability::Exclusive;
539        type __IndirectTrap = E::__IndirectTrap;
540    }
541    unsafe impl<R, E> RustSpec for Result<R, E>
542    where
543        R: RustSpec<Size = size::Sized<Zero>, Alignment = One>,
544        E: RustSpec<Size = size::Sized<Gt<Zero>>, Niche = WithNiche<Stable>>,
545        <R as RustSpec>::Alignment: Sized + Max<<E as RustSpec>::Alignment>,
546        <R as RustSpec>::Drop: Sized + Add<<E as RustSpec>::Drop>,
547        <E as RustSpec>::Alignment: Sized,
548        <E as RustSpec>::Drop: Sized,
549    {
550        type Layout = E::Layout;
551        type Size = size::Sized<Gt<Zero>>;
552        type Alignment = <R::Alignment as Max<E::Alignment>>::Output;
553        type Trap = E::__IndirectTrap;
554        type Niche = WithoutNiche;
555        type Drop = <R::Drop as Add<E::Drop>>::Output;
556        type Mutability = mutability::Exclusive;
557        type __IndirectTrap = E::__IndirectTrap;
558    }
559}
560
561#[cfg(test)]
562mod tests {
563    #[cfg(feature = "alloc")]
564    use alloc::vec::Vec;
565
566    use static_assertions::assert_impl_all;
567
568    use super::*;
569    use {
570        layout::{NonRobust, Robust},
571        mutability::Exclusive,
572        niche::{WithNiche, WithoutNiche},
573        size::{Gt, Sized as Co3Sized},
574    };
575
576    #[test]
577    fn indirect_trap_follows_supported_pointers_only() {
578        assert_impl_all!(&u8: RustSpec<__IndirectTrap = Robust>);
579        assert_impl_all!(&bool: RustSpec<__IndirectTrap = NonRobust>);
580        assert_impl_all!(&&u8: RustSpec<__IndirectTrap = NonRobust>);
581        assert_impl_all!(Option<&u8>: RustSpec<__IndirectTrap = Robust>);
582        assert_impl_all!(*const bool: RustSpec<__IndirectTrap = Robust>);
583    }
584
585    #[test]
586    fn transparent_type() {
587        assert_impl_all!(bool:
588            RustSpec<
589                Layout = Stable,
590                Size = Co3Sized<Gt<Zero>>,
591                Alignment = One,
592                Trap = NonRobust,
593                Niche = WithNiche<Unstable>,
594                Mutability = Exclusive,
595                __IndirectTrap = Robust,
596            >,
597        );
598        assert_impl_all!(&bool:
599            RustSpec<
600                Layout = Stable,
601                Size = Co3Sized<Gt<Zero>>,
602                Alignment = <usize as RustSpec>::Alignment,
603                Trap = NonRobust,
604                Niche = WithNiche<Stable>,
605                Mutability = Exclusive,
606                __IndirectTrap = NonRobust,
607            >,
608        );
609        assert_impl_all!(&mut bool:
610            RustSpec<
611                Layout = Stable,
612                Size = Co3Sized<Gt<Zero>>,
613                Alignment = <usize as RustSpec>::Alignment,
614                Trap = NonRobust,
615                Niche = WithNiche<Stable>,
616                Mutability = Exclusive,
617                __IndirectTrap = NonRobust,
618            >,
619        );
620        #[cfg(feature = "alloc")]
621        assert_impl_all!(Box<bool>:
622            RustSpec<
623                Layout = Stable,
624                Size = Co3Sized<Gt<Zero>>,
625                Alignment = <usize as RustSpec>::Alignment,
626                Trap = NonRobust,
627                Niche = WithNiche<Stable>,
628                Mutability = Exclusive,
629                __IndirectTrap = NonRobust,
630            >,
631        );
632        assert_impl_all!(&[bool]:
633            RustSpec<
634                Layout = Unstable,
635                Size = Co3Sized<Gt<Zero>>,
636                Alignment = <usize as RustSpec>::Alignment,
637                Trap = NonRobust,
638                Niche = WithNiche<Unstable>,
639                Mutability = Exclusive,
640                __IndirectTrap = NonRobust,
641            >,
642        );
643        #[cfg(feature = "alloc")]
644        assert_impl_all!(&mut [bool]:
645            RustSpec<
646                Layout = Unstable,
647                Size = Co3Sized<Gt<Zero>>,
648                Alignment = <usize as RustSpec>::Alignment,
649                Trap = NonRobust,
650                Niche = WithNiche<Unstable>,
651                Mutability = Exclusive,
652                __IndirectTrap = NonRobust,
653            >,
654        );
655        #[cfg(feature = "alloc")]
656        assert_impl_all!(Box<[bool]>:
657            RustSpec<
658                Layout = Unstable,
659                Size = Co3Sized<Gt<Zero>>,
660                Alignment = <usize as RustSpec>::Alignment,
661                Trap = NonRobust,
662                Niche = WithNiche<Unstable>,
663                Mutability = Exclusive,
664                __IndirectTrap = NonRobust,
665            >,
666        );
667        #[cfg(feature = "alloc")]
668        assert_impl_all!(Vec<bool>:
669            RustSpec<
670                Layout = Unstable,
671                Size = Co3Sized<Gt<Zero>>,
672                Alignment = <usize as RustSpec>::Alignment,
673                Trap = NonRobust,
674                Niche = WithNiche<Unstable>,
675                Mutability = Exclusive,
676                __IndirectTrap = NonRobust,
677            >,
678        );
679        assert_impl_all!([bool; 2]:
680            RustSpec<
681                Layout = Stable,
682                Size = Co3Sized<Gt<Zero>>,
683                Alignment = One,
684                Trap = NonRobust,
685                Niche = WithNiche<Unstable>,
686                Mutability = Exclusive,
687                __IndirectTrap = Robust,
688            >,
689        );
690        // FIXME:
691        //assert_impl_all!(Option<bool>:
692        //    RustSpec<
693        //        Layout = Unstable,
694        //        Size = Co3Sized<Gt<Zero>>,
695        //        Trap = NonRobust,
696        //        Niche = WithNiche<Unstable>,
697        //        Mutability = Exclusive,
698        //    >,
699        //);
700    }
701
702    #[test]
703    fn option_stable_niche_layout() {
704        use core::num::NonZeroU8;
705
706        assert_impl_all!(Option<NonZeroU8>:
707            RustSpec<
708                Layout = Stable,
709                Size = Co3Sized<Gt<Zero>>,
710                Alignment = One,
711                Trap = Robust,
712                Niche = WithoutNiche,
713                Mutability = Exclusive,
714                __IndirectTrap = Robust,
715            >,
716        );
717        assert_impl_all!(Option<&u8>:
718            RustSpec<
719                Layout = Stable,
720                Size = Co3Sized<Gt<Zero>>,
721                Alignment = <usize as RustSpec>::Alignment,
722                Trap = Robust,
723                Niche = WithoutNiche,
724                Mutability = Exclusive,
725                __IndirectTrap = Robust,
726            >,
727        );
728        assert_impl_all!(Option<&(u8, u8, u8)>:
729            RustSpec<
730                Layout = Unstable,
731                Size = Co3Sized<Gt<Zero>>,
732                Alignment = <usize as RustSpec>::Alignment,
733                Trap = Robust,
734                Niche = WithoutNiche,
735                Mutability = Exclusive,
736                __IndirectTrap = Robust,
737            >,
738        );
739        assert_impl_all!(Option<&NonZeroU8>:
740            RustSpec<
741                Layout = Stable,
742                Size = Co3Sized<Gt<Zero>>,
743                Alignment = <usize as RustSpec>::Alignment,
744                Trap = NonRobust,
745                Niche = WithoutNiche,
746                Mutability = Exclusive,
747                __IndirectTrap = NonRobust,
748            >,
749        );
750    }
751
752    #[test]
753    fn result_stable_niche_layout() {
754        use core::num::NonZeroU8;
755
756        assert_impl_all!(Result<NonZeroU8, ()>:
757            RustSpec<
758                Layout = Stable,
759                Size = Co3Sized<Gt<Zero>>,
760                Alignment = One,
761                Trap = Robust,
762                Niche = WithoutNiche,
763                Mutability = Exclusive,
764                __IndirectTrap = Robust,
765            >,
766        );
767        assert_impl_all!(Result<&u8, ()>:
768            RustSpec<
769                Layout = Stable,
770                Size = Co3Sized<Gt<Zero>>,
771                Alignment = <usize as RustSpec>::Alignment,
772                Trap = Robust,
773                Niche = WithoutNiche,
774                Mutability = Exclusive,
775                __IndirectTrap = Robust,
776            >,
777        );
778        assert_impl_all!(Result<&NonZeroU8, ()>:
779            RustSpec<
780                Layout = Stable,
781                Size = Co3Sized<Gt<Zero>>,
782                Alignment = <usize as RustSpec>::Alignment,
783                Trap = NonRobust,
784                Niche = WithoutNiche,
785                Mutability = Exclusive,
786                __IndirectTrap = NonRobust,
787            >,
788        );
789        assert_impl_all!(Result<(), NonZeroU8>:
790            RustSpec<
791                Layout = Stable,
792                Size = Co3Sized<Gt<Zero>>,
793                Alignment = One,
794                Trap = Robust,
795                Niche = WithoutNiche,
796                Mutability = Exclusive,
797                __IndirectTrap = Robust,
798            >,
799        );
800        assert_impl_all!(Result<&mut u8, ()>:
801            RustSpec<
802                Layout = Stable,
803                Size = Co3Sized<Gt<Zero>>,
804                Alignment = <usize as RustSpec>::Alignment,
805                Trap = Robust,
806                Niche = WithoutNiche,
807                Mutability = Exclusive,
808                __IndirectTrap = Robust,
809            >,
810        );
811    }
812
813    #[test]
814    fn robust_ref() {
815        assert_impl_all!(&&u8:
816            RustSpec<
817                Layout = Stable,
818                Size = Co3Sized<Gt<Zero>>,
819                Alignment = <usize as RustSpec>::Alignment,
820                Trap = NonRobust,
821                Niche = WithNiche<Stable>,
822                Mutability = Exclusive,
823                __IndirectTrap = NonRobust,
824            >,
825        );
826        assert_impl_all!(&mut &u8:
827            RustSpec<
828                Layout = Stable,
829                Size = Co3Sized<Gt<Zero>>,
830                Alignment = <usize as RustSpec>::Alignment,
831                Trap = NonRobust,
832                Niche = WithNiche<Stable>,
833                Mutability = Exclusive,
834                __IndirectTrap = NonRobust,
835            >,
836        );
837        #[cfg(feature = "alloc")]
838        assert_impl_all!(Box<&bool>:
839            RustSpec<
840                Layout = Stable,
841                Size = Co3Sized<Gt<Zero>>,
842                Alignment = <usize as RustSpec>::Alignment,
843                Trap = NonRobust,
844                Niche = WithNiche<Stable>,
845                Mutability = Exclusive,
846                __IndirectTrap = NonRobust,
847            >,
848        );
849        assert_impl_all!(&[&u8]:
850            RustSpec<
851                Layout = Unstable,
852                Size = Co3Sized<Gt<Zero>>,
853                Alignment = <usize as RustSpec>::Alignment,
854                Trap = NonRobust,
855                Niche = WithNiche<Unstable>,
856                Mutability = Exclusive,
857                __IndirectTrap = NonRobust,
858            >,
859        );
860        assert_impl_all!(&mut [&u8]:
861            RustSpec<
862                Layout = Unstable,
863                Size = Co3Sized<Gt<Zero>>,
864                Alignment = <usize as RustSpec>::Alignment,
865                Trap = NonRobust,
866                Niche = WithNiche<Unstable>,
867                Mutability = Exclusive,
868                __IndirectTrap = NonRobust,
869            >,
870        );
871        #[cfg(feature = "alloc")]
872        assert_impl_all!(Box<[&u8]>:
873            RustSpec<
874                Layout = Unstable,
875                Size = Co3Sized<Gt<Zero>>,
876                Alignment = <usize as RustSpec>::Alignment,
877                Trap = NonRobust,
878                Niche = WithNiche<Unstable>,
879                Mutability = Exclusive,
880                __IndirectTrap = NonRobust,
881            >,
882        );
883        #[cfg(feature = "alloc")]
884        assert_impl_all!(Vec<&u8>:
885            RustSpec<
886                Layout = Unstable,
887                Size = Co3Sized<Gt<Zero>>,
888                Alignment = <usize as RustSpec>::Alignment,
889                Trap = NonRobust,
890                Niche = WithNiche<Unstable>,
891                Mutability = Exclusive,
892                __IndirectTrap = NonRobust,
893            >,
894        );
895        assert_impl_all!([&u8; 2]:
896            RustSpec<
897                Layout = Stable,
898                Size = Co3Sized<Gt<Zero>>,
899                Alignment = <usize as RustSpec>::Alignment,
900                Trap = NonRobust,
901                Niche = WithNiche<Unstable>,
902                Mutability = Exclusive,
903                __IndirectTrap = Robust,
904            >,
905        );
906        assert_impl_all!(Option<&u8>:
907            RustSpec<
908                Layout = Stable,
909                Size = Co3Sized<Gt<Zero>>,
910                Alignment = <usize as RustSpec>::Alignment,
911                Trap = Robust,
912                Niche = WithoutNiche,
913                Mutability = Exclusive,
914                __IndirectTrap = Robust,
915            >,
916        );
917    }
918
919    #[test]
920    fn transparent_ref() {
921        assert_impl_all!(&&bool:
922            RustSpec<
923                Layout = Stable,
924                Size = Co3Sized<Gt<Zero>>,
925                Alignment = <usize as RustSpec>::Alignment,
926                Trap = NonRobust,
927                Niche = WithNiche<Stable>,
928                Mutability = Exclusive,
929                __IndirectTrap = NonRobust,
930            >,
931        );
932        assert_impl_all!(&mut &bool:
933            RustSpec<
934                Layout = Stable,
935                Size = Co3Sized<Gt<Zero>>,
936                Alignment = <usize as RustSpec>::Alignment,
937                Trap = NonRobust,
938                Niche = WithNiche<Stable>,
939                Mutability = Exclusive,
940                __IndirectTrap = NonRobust,
941            >,
942        );
943        #[cfg(feature = "alloc")]
944        assert_impl_all!(Box<&bool>:
945            RustSpec<
946                Layout = Stable,
947                Size = Co3Sized<Gt<Zero>>,
948                Alignment = <usize as RustSpec>::Alignment,
949                Trap = NonRobust,
950                Niche = WithNiche<Stable>,
951                Mutability = Exclusive,
952                __IndirectTrap = NonRobust,
953            >,
954        );
955        assert_impl_all!(&[&bool]:
956            RustSpec<
957                Layout = Unstable,
958                Size = Co3Sized<Gt<Zero>>,
959                Alignment = <usize as RustSpec>::Alignment,
960                Trap = NonRobust,
961                Niche = WithNiche<Unstable>,
962                Mutability = Exclusive,
963                __IndirectTrap = NonRobust,
964            >,
965        );
966        #[cfg(feature = "alloc")]
967        assert_impl_all!(&mut [&bool]:
968            RustSpec<
969                Layout = Unstable,
970                Size = Co3Sized<Gt<Zero>>,
971                Alignment = <usize as RustSpec>::Alignment,
972                Trap = NonRobust,
973                Niche = WithNiche<Unstable>,
974                Mutability = Exclusive,
975                __IndirectTrap = NonRobust,
976            >,
977        );
978        #[cfg(feature = "alloc")]
979        assert_impl_all!(Box<[&bool]>:
980            RustSpec<
981                Layout = Unstable,
982                Size = Co3Sized<Gt<Zero>>,
983                Alignment = <usize as RustSpec>::Alignment,
984                Trap = NonRobust,
985                Niche = WithNiche<Unstable>,
986                Mutability = Exclusive,
987                __IndirectTrap = NonRobust,
988            >,
989        );
990        #[cfg(feature = "alloc")]
991        assert_impl_all!(Vec<&bool>:
992            RustSpec<
993                Layout = Unstable,
994                Size = Co3Sized<Gt<Zero>>,
995                Alignment = <usize as RustSpec>::Alignment,
996                Trap = NonRobust,
997                Niche = WithNiche<Unstable>,
998                Mutability = Exclusive,
999                __IndirectTrap = NonRobust,
1000            >,
1001        );
1002        assert_impl_all!([&bool; 2]:
1003            RustSpec<
1004                Layout = Stable,
1005                Size = Co3Sized<Gt<Zero>>,
1006                Alignment = <usize as RustSpec>::Alignment,
1007                Trap = NonRobust,
1008                Niche = WithNiche<Unstable>,
1009                Mutability = Exclusive,
1010                __IndirectTrap = NonRobust,
1011            >,
1012        );
1013        assert_impl_all!(Option<&bool>:
1014            RustSpec<
1015                Layout = Stable,
1016                Size = Co3Sized<Gt<Zero>>,
1017                Alignment = <usize as RustSpec>::Alignment,
1018                Trap = NonRobust,
1019                Niche = WithoutNiche,
1020                Mutability = Exclusive,
1021                __IndirectTrap = NonRobust,
1022            >,
1023        );
1024    }
1025
1026    #[test]
1027    fn robust_ref_mut() {
1028        assert_impl_all!(&&mut u8:
1029            RustSpec<
1030                Layout = Stable,
1031                Size = Co3Sized<Gt<Zero>>,
1032                Alignment = <usize as RustSpec>::Alignment,
1033                Trap = NonRobust,
1034                Niche = WithNiche<Stable>,
1035                Mutability = Exclusive,
1036                __IndirectTrap = NonRobust,
1037            >,
1038        );
1039        assert_impl_all!(&mut &mut u8:
1040            RustSpec<
1041                Layout = Stable,
1042                Size = Co3Sized<Gt<Zero>>,
1043                Alignment = <usize as RustSpec>::Alignment,
1044                Trap = NonRobust,
1045                Niche = WithNiche<Stable>,
1046                Mutability = Exclusive,
1047                __IndirectTrap = NonRobust,
1048            >,
1049        );
1050        #[cfg(feature = "alloc")]
1051        assert_impl_all!(Box<&mut u8>:
1052            RustSpec<
1053                Layout = Stable,
1054                Size = Co3Sized<Gt<Zero>>,
1055                Alignment = <usize as RustSpec>::Alignment,
1056                Trap = NonRobust,
1057                Niche = WithNiche<Stable>,
1058                Mutability = Exclusive,
1059                __IndirectTrap = NonRobust,
1060            >,
1061        );
1062        assert_impl_all!(&[&mut u8]:
1063            RustSpec<
1064                Layout = Unstable,
1065                Size = Co3Sized<Gt<Zero>>,
1066                Alignment = <usize as RustSpec>::Alignment,
1067                Trap = NonRobust,
1068                Niche = WithNiche<Unstable>,
1069                Mutability = Exclusive,
1070                __IndirectTrap = NonRobust,
1071            >,
1072        );
1073        assert_impl_all!(&mut [&mut u8]:
1074            RustSpec<
1075                Layout = Unstable,
1076                Size = Co3Sized<Gt<Zero>>,
1077                Alignment = <usize as RustSpec>::Alignment,
1078                Trap = NonRobust,
1079                Niche = WithNiche<Unstable>,
1080                Mutability = Exclusive,
1081                __IndirectTrap = NonRobust,
1082            >,
1083        );
1084        #[cfg(feature = "alloc")]
1085        assert_impl_all!(Box<[&mut u8]>:
1086            RustSpec<
1087                Layout = Unstable,
1088                Size = Co3Sized<Gt<Zero>>,
1089                Alignment = <usize as RustSpec>::Alignment,
1090                Trap = NonRobust,
1091                Niche = WithNiche<Unstable>,
1092                Mutability = Exclusive,
1093                __IndirectTrap = NonRobust,
1094            >,
1095        );
1096        #[cfg(feature = "alloc")]
1097        assert_impl_all!(Vec<&mut u8>:
1098            RustSpec<
1099                Layout = Unstable,
1100                Size = Co3Sized<Gt<Zero>>,
1101                Alignment = <usize as RustSpec>::Alignment,
1102                Trap = NonRobust,
1103                Niche = WithNiche<Unstable>,
1104                Mutability = Exclusive,
1105                __IndirectTrap = NonRobust,
1106            >,
1107        );
1108        assert_impl_all!([&mut u8; 2]:
1109            RustSpec<
1110                Layout = Stable,
1111                Size = Co3Sized<Gt<Zero>>,
1112                Alignment = <usize as RustSpec>::Alignment,
1113                Trap = NonRobust,
1114                Niche = WithNiche<Unstable>,
1115                Mutability = Exclusive,
1116                __IndirectTrap = Robust,
1117            >,
1118        );
1119        assert_impl_all!(Option<&mut u8>:
1120            RustSpec<
1121                Layout = Stable,
1122                Size = Co3Sized<Gt<Zero>>,
1123                Alignment = <usize as RustSpec>::Alignment,
1124                Trap = Robust,
1125                Niche = WithoutNiche,
1126                Mutability = Exclusive,
1127                __IndirectTrap = Robust,
1128            >,
1129        );
1130    }
1131
1132    #[test]
1133    fn transparent_ref_mut() {
1134        assert_impl_all!(&&mut bool:
1135            RustSpec<
1136                Layout = Stable,
1137                Size = Co3Sized<Gt<Zero>>,
1138                Alignment = <usize as RustSpec>::Alignment,
1139                Trap = NonRobust,
1140                Niche = WithNiche<Stable>,
1141                Mutability = Exclusive,
1142                __IndirectTrap = NonRobust,
1143            >,
1144        );
1145        assert_impl_all!(&mut &mut bool:
1146            RustSpec<
1147                Layout = Stable,
1148                Size = Co3Sized<Gt<Zero>>,
1149                Alignment = <usize as RustSpec>::Alignment,
1150                Trap = NonRobust,
1151                Niche = WithNiche<Stable>,
1152                Mutability = Exclusive,
1153                __IndirectTrap = NonRobust,
1154            >,
1155        );
1156        #[cfg(feature = "alloc")]
1157        assert_impl_all!(Box<&mut bool>:
1158            RustSpec<
1159                Layout = Stable,
1160                Size = Co3Sized<Gt<Zero>>,
1161                Alignment = <usize as RustSpec>::Alignment,
1162                Trap = NonRobust,
1163                Niche = WithNiche<Stable>,
1164                Mutability = Exclusive,
1165                __IndirectTrap = NonRobust,
1166            >,
1167        );
1168        assert_impl_all!(&[&mut bool]:
1169            RustSpec<
1170                Layout = Unstable,
1171                Size = Co3Sized<Gt<Zero>>,
1172                Alignment = <usize as RustSpec>::Alignment,
1173                Trap = NonRobust,
1174                Niche = WithNiche<Unstable>,
1175                Mutability = Exclusive,
1176                __IndirectTrap = NonRobust,
1177            >,
1178        );
1179        assert_impl_all!(&mut [&mut bool]:
1180            RustSpec<
1181                Layout = Unstable,
1182                Size = Co3Sized<Gt<Zero>>,
1183                Alignment = <usize as RustSpec>::Alignment,
1184                Trap = NonRobust,
1185                Niche = WithNiche<Unstable>,
1186                Mutability = Exclusive,
1187                __IndirectTrap = NonRobust,
1188            >,
1189        );
1190        #[cfg(feature = "alloc")]
1191        assert_impl_all!(Box<[&mut bool]>:
1192            RustSpec<
1193                Layout = Unstable,
1194                Size = Co3Sized<Gt<Zero>>,
1195                Alignment = <usize as RustSpec>::Alignment,
1196                Trap = NonRobust,
1197                Niche = WithNiche<Unstable>,
1198                Mutability = Exclusive,
1199                __IndirectTrap = NonRobust,
1200            >,
1201        );
1202        #[cfg(feature = "alloc")]
1203        assert_impl_all!(Vec<&mut bool>:
1204            RustSpec<
1205                Layout = Unstable,
1206                Size = Co3Sized<Gt<Zero>>,
1207                Alignment = <usize as RustSpec>::Alignment,
1208                Trap = NonRobust,
1209                Niche = WithNiche<Unstable>,
1210                Mutability = Exclusive,
1211                __IndirectTrap = NonRobust,
1212            >,
1213        );
1214        assert_impl_all!([&mut bool; 2]:
1215            RustSpec<
1216                Layout = Stable,
1217                Size = Co3Sized<Gt<Zero>>,
1218                Alignment = <usize as RustSpec>::Alignment,
1219                Trap = NonRobust,
1220                Niche = WithNiche<Unstable>,
1221                Mutability = Exclusive,
1222                __IndirectTrap = NonRobust,
1223            >,
1224        );
1225        assert_impl_all!(Option<&mut bool>:
1226            RustSpec<
1227                Layout = Stable,
1228                Size = Co3Sized<Gt<Zero>>,
1229                Alignment = <usize as RustSpec>::Alignment,
1230                Trap = NonRobust,
1231                Niche = WithoutNiche,
1232                Mutability = Exclusive,
1233                __IndirectTrap = NonRobust,
1234            >,
1235        );
1236    }
1237}