blob: 2ae39edaef36ddcd2dea599092deb021293b46b4 [file] [log] [blame]
Devin Jeanpierre3dd5f4d2022-03-31 02:18:36 -07001// Part of the Crubit project, under the Apache License v2.0 with LLVM
2// Exceptions. See /LICENSE for license information.
3// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
4#![feature(negative_impls, vec_into_raw_parts, extern_types)]
Lukasz Anforowiczbdc54be2022-06-30 10:47:21 -07005//! This crate provides facilities for safely casting across multiple Rust types
6//! that represent the same C++ type. This is needed because:
7//!
8//! - In C++ one can interchangably use references to a forward-declared
9//! `struct` and references to the complete definition of the `struct`, but
10//! Rust bindings represent them using separate types (see `Incomplete<Name,
11//! Declarer>`).
12//!
13//! - In C++ one can interchangably use multiple independent C++ class template
14//! instantiations, but Rust bindings may represent them using separate types.
15//! This happens when the same class template is instantiated with the same
16//! template arguments in 2 different Crubit-generated crates with C++
17//! bindings.
18//!
19//! ## Forward declarations
Devin Jeanpierre3dd5f4d2022-03-31 02:18:36 -070020//!
21//! Given this C++:
22//!
23//! ```c++
24//! namespace foo {
25//! class Foo;
26//! } // namespace foo
27//!
28//! void MyFunction(foo::Foo& foo) {
29//! // can pass Foo around, but cannot access members, copy it, delete it, etc.
30//! some_other_library::OtherFunction(foo);
31//! }
32//! ```
33//!
34//! We can translate it to this equivalent Rust:
35//!
36//! ```
Lukasz Anforowiczbdc54be2022-06-30 10:47:21 -070037//! use forward_declare::{forward_declare, CcCast};
38//!
Devin Jeanpierre3dd5f4d2022-03-31 02:18:36 -070039//! forward_declare!(pub Foo = symbol!("foo::Foo"));
40//! fn MyFunction(foo: &mut Foo) {
Lukasz Anforowiczbdc54be2022-06-30 10:47:21 -070041//! some_other_library::OtherFunction(foo.cc_cast());
Devin Jeanpierre3dd5f4d2022-03-31 02:18:36 -070042//! }
43//! ```
44//!
45//! On the reverse end, to **define** a type which may be forward-declared in
46//! other crates, use the `unsafe_define!` macro:
47//!
48//! ```
49//! pub struct Foo { ... }
Devin Jeanpierref40e26b2022-04-07 14:48:27 -070050//! unsafe_define!(symbol!("foo::Foo"), Foo);
Devin Jeanpierre3dd5f4d2022-03-31 02:18:36 -070051//! ```
52//!
Devin Jeanpierre3dd5f4d2022-03-31 02:18:36 -070053//! The C++ forward declaration of a type `class Foo;` declares the name `Foo`
54//! to be a type, but does not provide details such size and contents; such type
55//! declaration is said to be incomplete. This is used in C++ to speed up build
56//! performance (by omitting the real definition from the dependencies) and to
57//! break up dependency cycles (by having one or both sides of the cycle
58//! forward-declare pieces from the other side).
59//!
60//! In the general case, forward declarations in existing C++ code cannot be
61//! removed without substantial changes. For example, a library can
62//! forward-declare a class that is only defined in the binary. So a forward
63//! declaration might not even have a single defining type, but one for
64//! every binary that uses the library!
65//!
66//! Rust has close-enough equivalents to forward-declaration for constants and
67//! functions, but not for types. This crate can be used wherever forward
68//! declarations are used in C++, for those cases where forward declarations
69//! cannot be avoided.
70//!
Devin Jeanpierre3dd5f4d2022-03-31 02:18:36 -070071//! ## Forward Declaring
72//!
73//! To forward declare a type which supports forward declarations, use the
74//! `forward_declare` macro.
75//!
76//! ```
77//! forward_declare!(pub YourType = symbol!("foo::YourType"));
78//! ```
79//!
80//! This creates a public alias `pub YourType =
81//! Incomplete<symbol!("foo::YourType"), ???>;`, where `???` is some type unique
82//! to this scope. In particular, this means that different calls
83//! to `forward_declare` produce different (but otherwise interchangeable)
84//! types.
85//!
Lukasz Anforowiczbdc54be2022-06-30 10:47:21 -070086//! Most user code won't need to directly use the `forward_declare!` macro and
87//! can instead rely on forward declarations provided in the `..._rs_api` crates
88//! generated by `rs_bindings_from_cc`.
89//!
90//! ## Providing a full definition
91//!
92//! For each type you wish to allow to be forward declared by others, give it a
93//! globally unique name such as `"foo::YourType"`, and call
94//! `unsafe_define!(symbol!("foo::YourType"), YourType)`.
95//!
96//! Most user code won't need to directly use the `unsafe_define!` macro and can
97//! instead rely on definitions provided in the `..._rs_api` crates generated by
98//! `rs_bindings_from_cc`.
99//!
100//! ## Supported casts
101//!
102//! Casting is supported between
103//!
104//! * Two forward-declarations of the same C++ type,
105//! * A forward-declaration and a complete definition of the same C++ type,
106//! * Two complete definitions of the same C++ type (e.g. two identical class
107//! template instantiations).
108//!
109//! ### Pointers and references
110//!
111//! Casting is also supported for all of the following common pointer types
112//! (e.g. a references to a forward-declared type can be cast to a reference to
113//! a fully-defined type):
114//!
115//! * `& _`
116//! * `&mut _`
117//! * `Pin<& _>`
118//! * `Pin<&mut _>`
119//! * `* const _`
120//! * `* mut _`
121//!
122//! `Box`, `Rc`, and `Arc` are excluded, because they require knowledge of the
123//! `Drop` impl, and incomplete (e.g. forward-declared) types do not know how to
124//! drop.
125//!
126//! Additionally, references can be cast to/from a corresponding `Pin`:
127//!
128//! * `& T` <-> `Pin<&T>`
129//! * `&mut T` <-> `Pin<&mut T>` (only if `T: Unpin`).
130//!
131//! ### Containers
132//!
133//! If container's element type supports casting, then casting is also supported
134//! for the following container types (e.g. a slice of references to a
135//! forward-declared type can be cast to a slice of references to a
136//! fully-defined type):
137//!
138//! * Slices - `&[T]`
139//! * Arrays - `[T; N]`
140//! * `Vec<T>`
141//! * TODO: Add support for more containers as needed (HashSet? bindings for
142//! std::vector?)
143//!
Devin Jeanpierre3dd5f4d2022-03-31 02:18:36 -0700144//! ## Passing around values
145//!
Lukasz Anforowiczbdc54be2022-06-30 10:47:21 -0700146//! Compound data types implement the `CcCast` trait, which allows for
Devin Jeanpierre3dd5f4d2022-03-31 02:18:36 -0700147//! converting between complete and incomplete types. To convert from complete
148//! to incomplete, incomplete to complete, or incomplete to incomplete when
Lukasz Anforowiczbdc54be2022-06-30 10:47:21 -0700149//! crossing crate boundaries, use `.cc_cast()` to perform the conversion.
Devin Jeanpierre3dd5f4d2022-03-31 02:18:36 -0700150//!
151//! ```
152//! forward_declare!(pub Foo = symbol!("foo::Foo"));
153//!
154//! fn takes_incomplete(foo: &mut Foo) {
Lukasz Anforowiczbdc54be2022-06-30 10:47:21 -0700155//! some_other_library::other_function(foo.cc_cast());
Devin Jeanpierre3dd5f4d2022-03-31 02:18:36 -0700156//! }
157//!
158//! fn takes_complete(foo: &mut RealFoo) {
Lukasz Anforowiczbdc54be2022-06-30 10:47:21 -0700159//! takes_incomplete(foo.cc_cast());
Devin Jeanpierre3dd5f4d2022-03-31 02:18:36 -0700160//! }
161//! ```
162//!
163//! ## Crossing Crate Boundaries
164//!
165//! **Warning:** Users of incomplete types from other crates should not assume
166//! that currently-incomplete types stay incomplete forever; code owners should
167//! feel free to replace an incomplete type with a complete type.
168//!
169//! In Rust, unlike C++, the incomplete type and incomplete type are different
170//! types. It is in theory a backwards-incompatible change to change from
171//! incomplete to complete. Callers must try as much as possible to ease that
172//! transition, since forward declarations are expected to be removed over time.
173//!
174//! This is partially enforced by the type system: every forward declaration of
175//! a type is unique, and every crate should have its own forward declaration,
176//! not reusing the forward declaration of another crate. As a result, you must
Lukasz Anforowiczbdc54be2022-06-30 10:47:21 -0700177//! call `cc_cast()` when crossing crate boundaries, and failure to do
Devin Jeanpierre3dd5f4d2022-03-31 02:18:36 -0700178//! so is an error:
179//!
180//!
181//! ```compile_fail
182//! # mod other_crate {
183//! # forward_declare!(pub ForwardDeclared = symbol!("foo::Type"));
184//! # pub fn function(x: &ForwardDeclared) {panic!()}
185//! # }
186//!
187//! forward_declare!(pub ForwardDeclared = symbol!("foo::Type"));
188//! let x: &ForwardDeclared = unimplemented!();
189//! other_crate::function(x); // ERROR
190//! ```
191//!
192//! If that example were valid, then removing a forward declaration and
193//! replacing it with the real type would break the caller, requiring a change
Lukasz Anforowiczbdc54be2022-06-30 10:47:21 -0700194//! to call `cc_cast()`. But since we always require the caller to call`
195//! cc_cast()` *anyway*, even if it already has an incomplete
Devin Jeanpierre3dd5f4d2022-03-31 02:18:36 -0700196//! type, `other_crate::function` is free to remove the forward declaration
197//! without breaking this caller.
198//!
199//! ```no_run
200//! # mod other_crate {
201//! # forward_declare!(pub ForwardDeclared = symbol!("foo::Type"));
202//! # pub fn function(x: &ForwardDeclared) {panic!()}
203//! # }
204//! #
205//! # forward_declare!(pub ForwardDeclared = symbol!("foo::Type"));
206//! # let x: &ForwardDeclared = unimplemented!();
Lukasz Anforowiczbdc54be2022-06-30 10:47:21 -0700207//! other_crate::function(x.cc_cast()); // Works whether `function` takes incomplete or complete type.
Devin Jeanpierre3dd5f4d2022-03-31 02:18:36 -0700208//! ```
209
210pub use forward_declare_proc_macros::*;
Devin Jeanpierre3dd5f4d2022-03-31 02:18:36 -0700211
Devin Jeanpierre12dfb9a2023-01-18 14:54:41 -0800212/// Public to be exposed to macros, but otherwise for internal use only.
213pub mod internal {
214 /// `Symbol` type, equivalent to const &'static str values, but usable in
215 /// generics in stable Rust.
216 ///
217 /// Every symbol is a tuple of `C`: for example, `symbol!("xy")` is
218 /// `Symbol((C<'x'>, C<'y'>))`
219 #[repr(C)]
220 pub struct Symbol<T>(std::marker::PhantomData<T>);
Devin Jeanpierre3dd5f4d2022-03-31 02:18:36 -0700221
Devin Jeanpierre12dfb9a2023-01-18 14:54:41 -0800222 /// A character in a symbol string.
223 #[repr(C)]
224 pub struct C<const CHAR: char>;
225
226 /// Types that implement the `CcType` trait with the same `Name` can be
227 /// safely transmuted between each other, because they either provide
228 /// bindings for the same C++ type, or point/refer to the same C++ type,
229 /// or contain the same C++ type.
230 ///
231 /// Even though this trait is public, implementations of this trait should
232 /// only be provided by Crubit itself:
233 ///
234 /// - Via `forward_declare!` and `unsafe_define!` macros
235 /// - Via blanket `impl`s provided for references, pointers (e.g. see `mod
236 /// ref_transmutability` below).
Devin Jeanpierrec7035e42023-01-18 15:03:42 -0800237 ///
238 /// # Safety
239 ///
240 /// Two types implement `CcType` with the same name if and only if they can
241 /// be transmuted to one another.
Devin Jeanpierre12dfb9a2023-01-18 14:54:41 -0800242 pub unsafe trait CcType {
Devin Jeanpierrec7035e42023-01-18 15:03:42 -0800243 /// `Name` helps Rust type system to identify the given transmutability
Devin Jeanpierre12dfb9a2023-01-18 14:54:41 -0800244 /// equivalence class.
245 ///
246 /// `forward_declare!` and `unsafe_define!` macros form the `Name` using
247 /// the `symbol!` macro, based on the fully-qualified name of
248 /// the imported C++ type.
249 ///
250 /// In other scenarios, the `Name` is formed using an arbitrary
251 /// convention that is sufficient to guarantee non-overlapping
252 /// names (e.g. see the private `ref_transmutability::RefName`
253 /// type alias below).
254 type Name;
255 }
256}
257
258use internal::*;
Devin Jeanpierre3dd5f4d2022-03-31 02:18:36 -0700259
260extern "C" {
Devin Jeanpierre12dfb9a2023-01-18 14:54:41 -0800261 /// Adding an `Unsized` field to your type makes it completely unsized
262 /// (not just dynamically-sized).
Devin Jeanpierre3dd5f4d2022-03-31 02:18:36 -0700263 type Unsized;
264}
265
266/// A struct representing an "Incomplete Type" for `Name`
267///
268/// For any given name, there may be multiple "incomplete types" for that name
269/// -- for example, `Incomplete<symbol!("T"), crate_1::T1>` is a different type
270/// from `Incomplete<symbol!("T"), T2>`. This is intentional: in public
271/// interfaces, an incomplete type is allowed to be changed to the complete type
272/// without breaking callers.
273///
274/// TODO(jeanpierreda): make rust think this is ffi-safe. (PhantomData...)
Devin Jeanpierre3dd5f4d2022-03-31 02:18:36 -0700275#[repr(C)]
276pub struct Incomplete<Name, Declarer>(std::marker::PhantomData<(Name, Declarer)>, Unsized);
277
278// Ensure this is not `Unpin`, `Send`, or `Sync`. This is discussed somewhat in:
279// https://doc.rust-lang.org/nomicon/ffi.html#representing-opaque-structs
280
281/// Incomplete types can't be copied by value, because we don't know their true
282/// size.
283impl<Name, Declarer> !Unpin for Incomplete<Name, Declarer> {}
284/// Similarly, we don't know if they are Send or Sync.
285impl<Name, Declarer> !Send for Incomplete<Name, Declarer> {}
286impl<Name, Declarer> !Sync for Incomplete<Name, Declarer> {}
287
288/// Marker trait for complete types.
289///
290/// This is automatically implemented for anything `!Unpin`, but all other types
291/// need to implement it by hand. Sorry, Rust just doesn't allow the kind of
292/// negative reasoning we'd need to make this better.
293///
294/// In particular, this is *not* implemented for `Incomplete<...>`.
295pub trait Complete {}
296
297/// We know this to be true because `Incomplete<...>` is `!Unpin`.
298///
299/// Ideally we'd get a better blanket impl, but this very nearly covers
300/// everything. Most `Unpin` types are going to be wrappers around C++ types,
301/// which can auto-generate a `Complete` impl, and the rest are unlikely to
302/// matter.
303impl<T: Unpin> Complete for T {}
304
Lukasz Anforowicz511d3f82022-06-30 08:39:45 -0700305/// All forward declarations represented by `Incomplete<Name, ...>` form a
306/// transmutability equivalence class (together with the complete definition(s)
307/// - see the `unsafe_define!` macro below).
Lukasz Anforowicz79fdd2d2022-06-30 08:57:58 -0700308///
309/// # Safety notes
310///
311/// We alias references to arbitrary `T` using references to `Incomplete`. This
312/// is OK, because of the design of `Incomplete`:
313///
314/// - layout: `Incomplete` has no fields of size > 0, so it does not alias `T`
315/// incompatibly.
316///
317/// - provenance: while in general it is not valid to access memory
318/// **neighboring** that of a type (e.g. one can't use &vec[0] to access
319/// vec[1]), in this case, we are using `feature(extern_types)`, which is a
320/// DST which must grant access to the following memory or else it would be
321/// useless. (This type of access is the reason the feature exists).
Lukasz Anforowicz511d3f82022-06-30 08:39:45 -0700322unsafe impl<Name, Declarer> CcType for Incomplete<Name, Declarer> {
323 type Name = Name;
Devin Jeanpierre3dd5f4d2022-03-31 02:18:36 -0700324}
325
Lukasz Anforowicz79fdd2d2022-06-30 08:57:58 -0700326/// `unsafe_define!(symbol!("..."), T)` claims that `T` is the unique definition
327/// of the type identified by that symbol, and implements the conversions for
328/// pointers to and from the corresponding `Incomplete` pointers.
329///
330/// Safety: if more than one type claim to be the definition, then they may be
331/// transmuted into each other in safe code. The safety requirements for
332/// `std::mem::transmute` apply.
333// Each `rustfmt` invocation would indent the `type Name...` line further and further to the right.
334#[rustfmt::skip]
335#[macro_export]
336macro_rules! unsafe_define {
337 // TODO(jeanpierreda): support generic complete type (e.g. `symbol!("xyz") <-> Foo<T> where T : Bar`)
338 ($Name:ty, $Complete:ty) => {
Devin Jeanpierre12dfb9a2023-01-18 14:54:41 -0800339 unsafe impl $crate::internal::CcType for $Complete {
Lukasz Anforowicz79fdd2d2022-06-30 08:57:58 -0700340 type Name = $Name;
341 }
342 };
343}
344
Lukasz Anforowicz79fdd2d2022-06-30 08:57:58 -0700345/// If `T` can be transmuted into `U`, then one can also transmute between
Lukasz Anforowicz0e385322022-06-30 09:00:50 -0700346/// `*const T`, and `* const U`. (This are always "thin" pointers - with the
347/// same size as `usize`.)
Lukasz Anforowicz511d3f82022-06-30 08:39:45 -0700348unsafe impl<T: ?Sized> CcType for *const T
Devin Jeanpierre3dd5f4d2022-03-31 02:18:36 -0700349where
Lukasz Anforowicz511d3f82022-06-30 08:39:45 -0700350 T: CcType,
Devin Jeanpierre3dd5f4d2022-03-31 02:18:36 -0700351{
Lukasz Anforowicz79fdd2d2022-06-30 08:57:58 -0700352 type Name = (*const (), T::Name);
Lukasz Anforowicz511d3f82022-06-30 08:39:45 -0700353}
354
Lukasz Anforowicz79fdd2d2022-06-30 08:57:58 -0700355/// If `T` can be transmuted into `U`, then one can also transmute between `*mut
Lukasz Anforowicz0e385322022-06-30 09:00:50 -0700356/// T`, and `* mut U`. (This are always "thin" pointers - with the same size as
357/// `usize`.)
Lukasz Anforowicz511d3f82022-06-30 08:39:45 -0700358unsafe impl<T: ?Sized> CcType for *mut T
359where
360 T: CcType,
361{
Lukasz Anforowicz79fdd2d2022-06-30 08:57:58 -0700362 type Name = (*mut (), T::Name);
Lukasz Anforowicz511d3f82022-06-30 08:39:45 -0700363}
364
Lukasz Anforowicz0e385322022-06-30 09:00:50 -0700365/// If `T` can be transmuted into `U`, then one can also transmute between
366/// arrays `[T; N]` and `[U; N]`.
367///
368/// # Safety notes
369///
370/// If `T` and `U` are transmutable then they should have the same alignment,
371/// size, and stride. Based on "Unsafe Code Guidelines Reference" [1], this
372/// means that the arrays `[T; N]` and `[U, N]` have the same memory layout.
373///
374/// Note that `T` below has an implicit `T: Sized` constraint. This means that
375/// it is *not* possible to transmute into or out-of an array of
376/// forward-declared types. OTOH, it *is* possible to transmute between arrays
377/// of transmutable, completely-defined/sized types (e.g. between arrays of
378/// template instantiations).
379///
380/// [1]
381/// https://rust-lang.github.io/unsafe-code-guidelines/layout/arrays-and-slices.html#layout-of-rust-array-types
382unsafe impl<T, const N: usize> CcType for [T; N]
383where
384 T: CcType,
385{
386 type Name = ([(); N], T::Name);
387}
388
389/// If `T` can be transmuted into `U`, then one can also transmute between
390/// slices `[T]` and `[U]`.
391///
392/// # Safety notes
393///
394/// ## Slices
395///
396/// "Unsafe Code Guidelines Reference" [1] points out that "the layout of a
397/// slice [T] of length N is the same as that of a [T; N] array". Therefore the
398/// safety of slice tranmutability can just depend on the safety of array
399/// transmutability and we can just refer to the safety notes for the
400/// `impl ... for [T; N]`.
401///
402/// [1]
403/// https://rust-lang.github.io/unsafe-code-guidelines/layout/arrays-and-slices.html#layout-of-rust-array-types
404///
405/// ## References to slices
406///
407/// The `impl` below only covers slices `[T]`, but it seems useful to talk here
408/// about the safety of transmuting *references* to slices: `&[T]` (covered by
409/// the `impl`s in the `ref_transmutability` module below). Transmuting of such
410/// "fat" pointers is safe based on "Unsafe Code Guidelines Reference" [2]
Lukasz Anforowiczbdc54be2022-06-30 10:47:21 -0700411/// pointing out that the layout of `&[T]` is independent of T - it is expected
412/// to have the same layout as:
Lukasz Anforowicz0e385322022-06-30 09:00:50 -0700413///
414/// ```rs
415/// #[repr(C)]
416/// struct Slice<T> {
417/// ptr: *const T,
418/// len: usize,
419/// }
420/// ```
421///
422/// [2] https://rust-lang.github.io/unsafe-code-guidelines/layout/pointers.html#notes
423unsafe impl<T> CcType for [T]
424where
425 T: CcType,
426{
427 // Using somewhat icky `usize::MAX` to work around the fact that [()] is
428 // unsized.
429 type Name = ([(); usize::MAX], T::Name);
430}
431
Lukasz Anforowicz79fdd2d2022-06-30 08:57:58 -0700432/// If `T` can be transmuted into `U`, then one can also transmute between `&'a
433/// T`, `&'a U`, `Pin<&'a T>`, and `Pin<&'a U>`. The corresponding CcType uses
434/// `RefName` as the `Name` of the transmutability equivalence class.
Devin Jeanpierre3dd5f4d2022-03-31 02:18:36 -0700435///
Lukasz Anforowicz79fdd2d2022-06-30 08:57:58 -0700436/// # Safety
Devin Jeanpierre97a23792022-04-19 08:17:26 -0700437///
Lukasz Anforowicz79fdd2d2022-06-30 08:57:58 -0700438/// 1. `&T` => `&U`: Pointers to transmutable things are themselves
Lukasz Anforowicz0e385322022-06-30 09:00:50 -0700439/// transmutable. This is safe for "thin" pointers (e.g. `&i32`) as well as
440/// for "fat" pointers (e.g. `&[i32]` also stores the size of the slice).
Devin Jeanpierre3dd5f4d2022-03-31 02:18:36 -0700441///
Lukasz Anforowicz79fdd2d2022-06-30 08:57:58 -0700442/// 2. `&T` => `Pin<&T>`: `Pin` is `repr(transparent)` and `Pin::new` is
443/// safe.
444///
445/// 3. `Pin<&T>` => `&T`: `Pin` is `repr(transparent)` and `Pin::get_ref` is
446/// safe.
447///
448/// 4. `Pin<&T>` => `Pin<&U>`: This combines transmutes 3, 1, and 2.
449///
450/// 5. `&T` => `Pin<&U>`: This combines transmutes 1 and 2.
451///
452/// 6. `Pin<&T>` => `&U`: This combines transmutes 4 and 3.
453///
454/// # Transmuting to the unpinned variant
455///
456/// We allow transmuting to the unpinned variant, when known to be safe.
457///
458/// ## Motivation
459///
460/// Consider what happens if a forward declaration in C++ is removed in favor of
461/// the complete type, where the library containing that declaration was wrapped
462/// in Rust. If the type is trivially relocatable, and we automatically generate
463/// C++ bindings which do not use `Pin` except for non-trivially-relocatable
464/// types, this would be a backwards incompatible change. So, we should
465/// also support unpinning during the cast.
466///
467/// ## Limited scope of impls
Devin Jeanpierre3dd5f4d2022-03-31 02:18:36 -0700468///
Devin Jeanpierre97a23792022-04-19 08:17:26 -0700469/// Note: ideally we'd blanket impl the conversion to allow unpinning any smart
470/// pointer type, and not only mut references, but this causes coherence issues,
471/// because `Pin` itself is a smart pointer. I could not think of a workaround
472/// that did not require specialization, other than to hardcode the set of
473/// pointer types supported.
474///
475/// Since we're hardcoding a set of pointer types above *anyway*, we just need
476/// to keep the list of unpinnable types in sync with the list of "pointers to
477/// transmutable things" above.
Lukasz Anforowicz79fdd2d2022-06-30 08:57:58 -0700478mod ref_transmutability {
479 use super::CcType;
480 use std::pin::Pin;
481
482 type RefName<'a, Name> = (&'a (), Name);
483
484 /// Safety: See the doc comment for the `ref_transmutability` module.
485 unsafe impl<'a, T: ?Sized> CcType for &'a T
486 where
487 T: CcType,
488 {
489 type Name = RefName<'a, T::Name>;
490 }
491
492 /// Safety: See the doc comment for the `ref_transmutability` module.
493 unsafe impl<'a, T: ?Sized> CcType for Pin<&'a T>
494 where
495 T: CcType,
496 {
497 type Name = RefName<'a, T::Name>;
498 }
Devin Jeanpierre3dd5f4d2022-03-31 02:18:36 -0700499}
500
Lukasz Anforowicz79fdd2d2022-06-30 08:57:58 -0700501/// If `T` can be transmuted into `U`, then one can also transmute
502/// 1) between `&'a mut T` and `&'a mut U`
503/// 2) between `Pin<&'a mut T>` and `Pin<&'a mut U>`
504/// 3) from `&'a mut T` into `Pin<&'a mut T>` or into `Pin<&'a mut U>`
505///
506/// Additionally, if `T` and `U` are `Unpin`, then one can also transmute
507/// 4) from `Pin<&'a mut T>` into `&'a mut T` or into `&'a mut U`
508///
509/// The corresponding CcType uses `MutRefName` as the `Name` of the
510/// transmutability equivalence class.
511///
512/// # Safety
513///
514/// The list below is very similar to the safety notes for `RefName`, except
515/// that the 3rd item below also needs to talk about the `T: Unpin` constraint.
516///
517/// 1. `&mut T` => `&mut U`: Pointers to transmutable things are themselves
Lukasz Anforowicz0e385322022-06-30 09:00:50 -0700518/// transmutable. This is safe for "thin" pointers (e.g. `&i32`) as well as
519/// for "fat" pointers (e.g. `&[i32]` also stores the size of the slice).
Lukasz Anforowicz79fdd2d2022-06-30 08:57:58 -0700520///
521/// 2. `&mut T` => `Pin<&mut T>`: `Pin` is `repr(transparent)` and `Pin::new`
522/// is safe.
523///
524/// 3. `Pin<&mut T>` => `&mut T`: `Pin` is `repr(transparent)` and
525/// `Pin::into_inner` is safe and allowed for `T: Unpin`.
526///
527/// 4. `Pin<&mut T>` => `Pin<&mut U>`: This combines transmutes 3, 1, and 2.
528///
529/// 5. `&mut T` => `Pin<&mut U>`: This combines transmutes 1 and 2.
530///
531/// 6. `Pin<&mut T>` => `&mut U`: This combines transmutes 4 and 3.
532///
533/// # Transmuting to the unpinned variant
534///
535/// Transmuting to the unpinned variant is described in more details in the doc
536/// comment of `RefName`.
537mod mut_ref_transmutability {
538 use super::CcType;
539 use std::pin::Pin;
540
541 type MutRefName<'a, Name> = (&'a mut (), Name);
542
543 /// Safety: See the doc comment for the `mut_ref_transmutability` module.
544 unsafe impl<'a, T: ?Sized> CcType for &'a mut T
545 where
546 T: CcType,
547 T: Unpin, // See safety notes for MutRefName, item 3
548 {
549 type Name = MutRefName<'a, T::Name>;
550 }
551
552 /// Safety: See the doc comment for the `mut_ref_transmutability` module.
553 unsafe impl<'a, T: ?Sized> CcType for Pin<&'a mut T>
554 where
555 T: CcType,
556 {
557 type Name = MutRefName<'a, T::Name>;
558 }
559}
560
561/// Like `Into<T>`, but for completeness conversions.
Lukasz Anforowiczbdc54be2022-06-30 10:47:21 -0700562pub trait CcCast<T> {
563 fn cc_cast(self) -> T;
Lukasz Anforowicz79fdd2d2022-06-30 08:57:58 -0700564}
565
Lukasz Anforowiczbdc54be2022-06-30 10:47:21 -0700566impl<T, U> CcCast<U> for T
Devin Jeanpierre3dd5f4d2022-03-31 02:18:36 -0700567where
Lukasz Anforowicz511d3f82022-06-30 08:39:45 -0700568 T: CcType,
569 U: CcType<Name = T::Name>,
Devin Jeanpierre3dd5f4d2022-03-31 02:18:36 -0700570{
Lukasz Anforowiczbdc54be2022-06-30 10:47:21 -0700571 fn cc_cast(self) -> U {
Lukasz Anforowicz79fdd2d2022-06-30 08:57:58 -0700572 assert_eq!(std::mem::size_of::<T>(), std::mem::size_of::<U>());
573 let x = std::mem::ManuallyDrop::new(self);
574 unsafe { std::mem::transmute_copy(&*x) }
Devin Jeanpierre3dd5f4d2022-03-31 02:18:36 -0700575 }
576}
577
Lukasz Anforowiczbdc54be2022-06-30 10:47:21 -0700578impl<'a, T: ?Sized, U: ?Sized> CcCast<Vec<&'a U>> for Vec<&'a T>
Devin Jeanpierre3dd5f4d2022-03-31 02:18:36 -0700579where
Lukasz Anforowicz511d3f82022-06-30 08:39:45 -0700580 T: CcType,
581 U: CcType<Name = T::Name>,
Devin Jeanpierre3dd5f4d2022-03-31 02:18:36 -0700582{
Lukasz Anforowiczbdc54be2022-06-30 10:47:21 -0700583 fn cc_cast(self) -> Vec<&'a U> {
Devin Jeanpierre3dd5f4d2022-03-31 02:18:36 -0700584 let (p, len, capacity) = self.into_raw_parts();
585 unsafe { Vec::from_raw_parts(p as *mut &'a U, len, capacity) }
586 }
587}