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