Skip to main content

rust_spec/
size.rs

1use core::{convert::Infallible, ops::Add};
2
3pub use crate::{Gt, Zero};
4use crate::{Stable, Unstable, layout::LayoutKind};
5
6#[sealed::sealed]
7pub trait SizedKind {}
8
9#[sealed::sealed]
10pub trait MetadataKind {}
11
12/// Marker for types with a constant size known at compile time.
13///
14/// See [`core::marker::Sized`].
15pub struct Sized<K: SizedKind>(core::marker::PhantomData<K>, Infallible);
16
17/// Marker for types with a size that can be determined from pointer metadata.
18///
19/// Type parameter can be set to either [`SliceLike`] or [`DynTraitLike`] only.
20///
21/// See [`core::marker::MetaSized`]
22pub struct MetaSized<K: MetadataKind>(core::marker::PhantomData<K>, Infallible);
23
24/// Marker for [Slices](https://doc.rust-lang.org/core/primitive.slice.html) or DSTs whose last field is a slice.
25///
26/// See [`core::slice`].
27pub enum SliceLike {}
28
29/// Marker for [Trait objects](https://doc.rust-lang.org/reference/types/trait-object.html) or DSTs whose last field is a trait object.
30pub enum DynTraitLike {}
31
32/// Marker for [Extern types](https://rust-lang.github.io/rfcs/1861-extern-types.html) and DSTs whose last field is an extern type.
33///
34/// Pointers to extern types are thin.
35pub enum ExternTypeLike {}
36
37/// Unsized data whose length can be found from a nul terminator.
38pub enum NulTerminated {}
39
40#[sealed::sealed]
41impl SizedKind for Zero {}
42
43#[sealed::sealed]
44impl SizedKind for crate::Gt<crate::Zero> {}
45
46#[sealed::sealed]
47impl MetadataKind for SliceLike {}
48
49#[sealed::sealed]
50impl MetadataKind for DynTraitLike {}
51
52/// Pointer layout stability determined by the pointee's size category.
53///
54/// Combine the layout contribution with the pointee's layout using `Add`.
55#[sealed::sealed]
56pub trait PointerLayout {
57    type Output: LayoutKind;
58}
59
60#[sealed::sealed]
61impl<K: SizedKind> PointerLayout for Sized<K> {
62    type Output = Stable;
63}
64
65#[sealed::sealed]
66impl<K: MetadataKind> PointerLayout for MetaSized<K> {
67    type Output = Unstable;
68}
69
70#[sealed::sealed]
71impl PointerLayout for ExternTypeLike {
72    type Output = Stable;
73}
74
75#[sealed::sealed]
76impl PointerLayout for NulTerminated {
77    type Output = Unstable;
78}
79
80pub(crate) trait Dst {}
81impl Dst for ExternTypeLike {}
82impl Dst for NulTerminated {}
83impl<K: MetadataKind> Dst for MetaSized<K> {}
84
85impl<K: SizedKind> Add<Sized<K>> for Sized<Zero> {
86    type Output = Sized<K>;
87
88    fn add(self, _: Sized<K>) -> Self::Output {
89        unreachable!()
90    }
91}
92
93impl<K: SizedKind> Add<Sized<K>> for Sized<crate::Gt<crate::Zero>> {
94    type Output = Self;
95
96    fn add(self, _: Sized<K>) -> Self::Output {
97        unreachable!()
98    }
99}
100
101impl<K: Dst, U: SizedKind> Add<K> for Sized<U> {
102    type Output = K;
103
104    fn add(self, _: K) -> Self::Output {
105        unreachable!()
106    }
107}
108
109impl<K: MetadataKind, U: SizedKind> Add<Sized<U>> for MetaSized<K> {
110    type Output = Self;
111
112    fn add(self, _: Sized<U>) -> Self::Output {
113        unreachable!()
114    }
115}
116
117impl<U: SizedKind> Add<Sized<U>> for ExternTypeLike {
118    type Output = Self;
119
120    fn add(self, _: Sized<U>) -> Self::Output {
121        unreachable!()
122    }
123}
124
125impl<U: SizedKind> Add<Sized<U>> for NulTerminated {
126    type Output = Self;
127
128    fn add(self, _: Sized<U>) -> Self::Output {
129        unreachable!()
130    }
131}