1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
//! Guidance and tools for ***sound*** transmutation.
//!
//! A transmutation is ***sound*** if the mere act of transmutation is
//! guaranteed to not violate Rust's memory model.
//!
//! [`unsafe_transmute`]: crate::unsafe_transmute
//! [`TransmuteInto<U>`]: crate::TransmuteInto
//!
//! ## When is a transmutation sound?
//! [`NonZeroU8`]: core::num::NonZeroU8
//!
//! A transmutation is only sound if it occurs between types with [well-defined
//! representations](#well-defined-representation), and does not violate Rust's
//! memory model. See [*Transmutations Between Owned Values*][transmute-owned],
//! and [*Transmutations Between References*][transmute-references]. These rules
//! are automatically enforced by [`unsafe_transmute`] and [`TransmuteInto<U>`].
//!
//! ### Well-Defined Representation
//! [`u8`]: core::u8
//! [`f32`]: core::f32
//!
//! Transmutation is ***always unsound*** if it occurs between types with
//! unspecified representations. Most of Rust's primitive types have specified
//! representations. That is, the layout characteristics of [`u8`], [`f32`] and
//! others are guaranteed to be stable across compiler versions.
//!
//! In contrast, most `struct` and `enum` types defined without an explicit
//! `#[repr(C)]` or `#[repr(transparent)]` attribute do ***not*** have
//! well-specified layout characteristics.
//!
//! To ensure that types you've define are soundly transmutable, you usually
//! must mark them with the `#[repr(C)]` attribute.
//!
//! ### Transmuting Owned Values
//! [transmute-owned]: #transmuting-owned-values
//!
//! Transmutations involving owned values must adhere to two rules to be sound.
//! They must:
//! * [preserve or broaden the bit validity][owned-validity], and
//! * [preserve or shrink the size][owned-size].
//!
//! #### Preserve or Broaden Bit Validity
//! [owned-validity]: #preserve-or-broaden-bit-validity
//!
//! For each _i<sup>th</sup>_ of the destination type, all possible
//! instantiations of the _i<sup>th</sup>_ byte of the source type must be a
//! bit-valid instance of the _i<sup>th</sup>_ byte of the destination type.
//!
//! For example, we are permitted us to transmute a [`NonZeroU8`] into a [`u8`]:
//! ```rust
//! # use typic::docs::prelude::*;
//! let _ : u8 = NonZeroU8::new(1).unwrap().transmute_into();
//! ```
//! ...because all possible instances of [`NonZeroU8`] are also valid instances
//! of [`u8`]. However, transmuting a [`u8`] into a [`NonZeroU8`] is forbidden:
//! ```compile_fail
//! # use typic::docs::prelude::*;
//! let _ : NonZeroU8 = u8::default().transmute_into(); // Compile Error!
//! ```
//! ...because not all instances of [`u8`] are valid instances of [`NonZeroU8`].
//!
//! Another example: While laying out certain types, rust may insert padding
//! bytes between the layouts of fields. In the below example `Padded` has two
//! padding bytes, while `Packed` has none:
//! ```rust
//! # use typic::docs::prelude::*;
//! #[typic::repr(C)]
//! #[derive(Default, StableABI)]
//! struct Padded(pub u8, pub u16, pub u8);
//!
//! #[typic::repr(C)]
//! #[derive(Default, StableABI)]
//! struct Packed(pub u16, pub u16, pub u16);
//!
//! assert_eq!(mem::size_of::<Packed>(), mem::size_of::<Padded>());
//! ```
//!
//! We may safely transmute from `Packed` to `Padded`:
//! ```rust
//! # use typic::docs::prelude::*;
//! let _ : Padded = Packed::default().transmute_into();
//! ```
//! ...but not from `Padded` to `Packed`:
//! ```compile_fail
//! # use typic::docs::prelude::*;
//! let _ : Packed = Padded::default().transmute_into(); // Compile Error!
//! ```
//! ...because doing so would expose two uninitialized padding bytes in `Padded`
//! as if they were initialized bytes in `Packed`.
//!
//! #### Preserve or Shrink Size
//! [owned-size]: #preserve-or-shrink-size
//!
//! It's completely safe to transmute into a type with fewer bytes than the
//! destination type; e.g.:
//! ```rust
//! # use typic::docs::prelude::*;
//! let _ : u8 = u64::default().transmute_into();
//! ```
//! This transmute truncates away the final three bytes of the `u64` value.
//!
//! A value may ***not*** be transmuted into a type of greater size:
//! ```compile_fail
//! # use typic::docs::prelude::*;
//! let _ : u64 = u8::default().transmute_into(); // Compile Error!
//! ```
//!
//! ### Transmuting References
//! [transmute-references]: #transmuting-references
//!
//! The [restrictions above that to transmuting owned values][transmute-owned],
//! also apply to transmuting references. However, references carry a few
//! additional restrictions. A [sound transmutation](#sound-transmutation) must:
//! - [preserve or relax alignment][reference-alignment],
//! - [preserve or shrink lifetimes][reference-lifetimes],
//! - [preserve or shrink mutability][reference-mutability], and
//! - [preserve validity][reference-validity].
//!
//! #### Preserve or Relax Alignment
//! [reference-alignment]: #preserve-or-relax-alignment
//!
//! You may transmute a reference into reference of more relaxed alignment:
//! ```rust
//! # use typic::docs::prelude::*;
//! let _: &[u8; 0] = (&[0u16; 0]).transmute_into();
//! ```
//!
//! However, you may **not** transmute a reference into a reference of stricter
//! alignment:
//! ```compile_fail
//! # use typic::docs::prelude::*;
//! let _: &[u16; 0] = (&[0u8; 0]).transmute_into(); // Compile Error!
//! ```
//!
//! #### Preserve or Shrink Lifetimes
//! [reference-lifetimes]: #preserve-or-shrink-lifetimes
//!
//! You may transmute a reference into reference of lesser lifetime:
//! ```rust
//! # use typic::docs::prelude::*;
//! fn shrink<'a>() -> &'a u8 {
//! static long : &'static u8 = &16;
//! long
//! }
//! ```
//!
//! However, you may **not** transmute a reference into a reference of greater
//! lifetime:
//! ```compile_fail
//! # use typic::docs::prelude::*;
//! fn extend<'a>(short: &'a u8) -> &'static u8 {
//! static long : &'static u8 = &16;
//! short.transmute_into()
//! }
//! ```
//!
//! #### Preserve or Shrink Mutability
//! [reference-mutability]: #preserve-or-shrink-mutability
//!
//! You may preserve or decrease the mutability of a reference through
//! transmutation:
//! ```rust
//! # use typic::docs::prelude::*;
//! let _: &u8 = (&42u8).transmute_into();
//! let _: &u8 = (&mut 42u8).transmute_into();
//! ```
//!
//! However, you may **not** transmute an immutable reference into a mutable
//! reference:
//! ```compile_fail
//! # use typic::docs::prelude::*;
//! let _: &mut u8 = (&42u8).transmute_into(); // Compile Error!
//! ```
//!
//! #### Preserve Validity
//! [reference-validity]: #preserve-validity
//!
//! Unlike transmutations of owned values, the transmutation of a reference may
//! also not expand the bit-validity of the referenced type. For instance:
//!
//! ```compile_fail
//! # use typic::docs::prelude::*;
//! let mut x = NonZeroU8::new(42).unwrap();
//! {
//! let y : &mut u8 = (&mut x).transmute_into(); // Compile Error!
//! *y = 0;
//! }
//!
//! let z : NonZeroU8 = x;
//! ```
//! If this example did not produce a compile error, the value of `z` would not
//! be a bit-valid instance of its type.
pub use crate;
/// Configuration options for ***sound*** transmutations.