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