blob: 41a6214a7cec878057ae0079323478a69ecad4ed [file] [log] [blame]
Devin Jeanpierref643afa2022-02-23 20:50:48 +00001// 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
Googlerf8296f82023-03-03 13:55:23 -08004#![cfg_attr(not(test), no_std)]
Devin Jeanpierrec05cac52022-03-31 03:55:58 -07005#![feature(negative_impls)]
Devin Jeanpierref643afa2022-02-23 20:50:48 +00006//! Traits for memory management operations on wrapped C++ objects, based on
7//! moveit.
8//!
9//! # Comparison with moveit
10//!
11//! ## Non-destructive move
12//!
13//! Unlike moveit, C++ moves are never Rust moves.
14//!
15//! This is important because it dramatically simplifies the mental model and
16//! code involved. Everything to do with DerefMove can be removed. Furthermore,
17//! it makes it *more useful*.
18//!
19//! In particular, imagine trying to write a *Rust* implementation of the
20//! following C++ function:
21//!
22//! ```c++
23//! void Swap(CxxClass& x, CxxClass& y) {
24//! CxxClass tmp = std::move(x);
25//! x = std::move(y);
26//! y = std::move(tmp);
27//! }
28//! ```
29//!
30//! With destructive moves we're in a bind: any move from x destroys its source,
31//! leaving us with nothing to assign to. C++ moves are non-destructive. Traits
32//! modeling C++ moves, therefore, in order to be most compatible, should also
33//! be non-destructive.
34//!
35//! Here is an implementation using the traits in this file, in pure Rust:
36//!
37//! ```
38//! fn swap(mut x: Pin<&mut CxxClass>, mut y: Pin<&mut CxxClass>) {
Devin Jeanpierre8e54c2f2022-08-04 02:56:35 -070039//! emplace!{ let mut tmp = mov!(x.as_mut()); }
40//! x.assign(mov!(y.as_mut()));
41//! y.assign(mov!(tmp));
Devin Jeanpierref643afa2022-02-23 20:50:48 +000042//! }
43//! ```
44//!
45//! ## Curried `Ctor` traits
46//!
47//! Rather than `CopyCtor::copy_ctor` and `MoveCtor::move_ctor`, this crate
48//! embraces `Ctor` itself as the single unique way to initialize everything.
49//! And so copy-constructible types are not things which implement `CopyCtor`,
50//! but rather, things which implement `CtorNew<&T>`. Similarly,
51//! move-constructible things implement `CtorNew<RvalueReference<'_, T>>`.
52//!
53//! ## Blanket impls
54//!
55//! So that Rust types can be used against C++ functions (even templated ones),
56//! the copy and move traits have blanket impls for all suitable Unpin types.
57//!
58//! More significantly, we take the position that all Unpin types are their own
59//! `Ctor`. This makes `Ctor`-based initialization nearly a perfect superset of
60//! normal initialization rules: for a non-self-referential Rust type (an Unpin
61//! type), it looks the same as normal, but for C++-like !Unpin types we use
62//! custom `Ctor` values to initialize in-place.
63//!
64//! Blanket implementing based on `Unpin` means that we're treating `T : Unpin`
65//! as effectively meaning "T is safe to deal with by value", which is close to,
66//! but not quite, what it means. (There are some types which are !Unpin but
67//! would be safe to treat as normal rust types. Unfortunately, there is no way
68//! to detect them.)
69//!
70//! ## Overload trait
71//!
72//! This module also includes a prototype alternative API which more directly
73//! models overloaded constructors: `T : CtorNew<(A, B, C)>` is roughly
74//! equivalent to the C++ "T has a constructor taking arguments of type A, B,
75//! and C".
76//!
77//! ## StackBox
78//!
79//! Moveit needs a StackBox type which is comparable to Box, except stored on
80//! the stack -- in particular, which implements OuterDrop and the like.
81//!
82//! Since DerefMove is not used here, we instead are able to export only a
83//! Pin<&mut T> to users.
84//!
85//! One still needs something similar to `Slot` or `StackBox`: a `MaybeUninit`
86//! type which will run drop. This isn't exposed to users directly if they are
87//! simply storing in a local variable.
88//!
89//! ## Structs and the `ctor!` macro
90//!
91//! `ctor` adds a `ctor!` macro to make it easy to initialize a struct
92//! that contains non-trivially-relocatable fields.
Devin Jeanpierrea330af62022-06-09 17:03:45 -070093//!
94//! ## Features
95//!
96//! This library requires the following unstable features enabled in users:
97//!
98//! **negative_impls:**
99//! This is used to allow trait coherence checking for `!Unpin` types. A
100//! "blanket impl for all `Unpin` types is used to make them constructible with
101//! `ctor`, and Rust believes this may conflict with types that use
102//! `PhantomPinned`. It knows no conflict exists if, instead, types impl
103//! `!Unpin`.
Devin Jeanpierref643afa2022-02-23 20:50:48 +0000104
Googlerf8296f82023-03-03 13:55:23 -0800105extern crate alloc;
106
107use alloc::boxed::Box;
Googler7059c3a2023-04-04 04:04:37 -0700108use core::marker::{PhantomData, Unpin};
Googlerf8296f82023-03-03 13:55:23 -0800109use core::mem::{ManuallyDrop, MaybeUninit};
Googler7059c3a2023-04-04 04:04:37 -0700110use core::ops::{Deref, DerefMut};
Googlerf8296f82023-03-03 13:55:23 -0800111use core::pin::Pin;
Devin Jeanpierref643afa2022-02-23 20:50:48 +0000112
113pub use ctor_proc_macros::*;
114
115/// The string constant for #[must_use] to describe why you must use a `Ctor`.
116macro_rules! must_use_ctor {
117 () => {
118 "A Ctor is not invoked unless emplaced, using e.g. `emplace!{}`, or `Box::emplace()`."
119 };
120}
121
122/// The string constant for #[must_use] to describe why you must use a
123/// `Ctor`/`Assign` source.
124macro_rules! must_use_ctor_assign {
125 ($name:literal) => {
126 concat!(
127 $name,
128 " is not invoked unless emplaced, using e.g. `emplace!{}`, or `Box::emplace()`, or",
129 " unless assigned from, using `.assign()`."
130 )
131 };
132}
133
134// ======================
135// ~Unchanged from moveit
136// ======================
137
138#[must_use = must_use_ctor!()]
139pub trait Ctor {
140 type Output;
141 unsafe fn ctor(self, dest: Pin<&mut MaybeUninit<Self::Output>>);
142
143 /// Returns a chained Ctor, which will invoke `f` after construction.
144 ///
145 /// for example, these two snippets are equivalent:
146 ///
147 /// ```
148 /// emplace! { let x = y; }
149 /// x.mutating_method();
150 /// ```
151 ///
152 /// ```
153 /// emplace! { let x = y.ctor_then(|mut inited| inited.mutating_method()); }
154 /// ```
155 fn ctor_then<F: FnOnce(Pin<&mut Self::Output>)>(self, f: F) -> CtorThen<Self, F>
156 where
157 Self: Sized,
158 {
159 CtorThen { ctor: self, f }
160 }
161}
162
163pub trait Emplace<T>: Sized {
164 fn emplace<C: Ctor<Output = T>>(c: C) -> Pin<Self>;
165}
166
167impl<T> Emplace<T> for Box<T> {
168 fn emplace<C: Ctor<Output = T>>(ctor: C) -> Pin<Box<T>> {
169 let mut uninit = Box::new(MaybeUninit::<T>::uninit());
170 unsafe {
171 let pinned = Pin::new_unchecked(&mut *uninit);
172 ctor.ctor(pinned);
173 Pin::new_unchecked(Box::from_raw(Box::into_raw(uninit).cast::<T>()))
174 }
175 }
176}
177
178#[must_use = must_use_ctor!()]
179pub struct FnCtor<Output, F: FnOnce(Pin<&mut MaybeUninit<Output>>)>(pub F, PhantomData<fn(Output)>);
180impl<Output, F: FnOnce(Pin<&mut MaybeUninit<Output>>)> FnCtor<Output, F> {
181 pub fn new(f: F) -> Self {
182 Self(f, PhantomData)
183 }
184}
185
186impl<Output, F: FnOnce(Pin<&mut MaybeUninit<Output>>)> Ctor for FnCtor<Output, F> {
187 type Output = Output;
188
189 unsafe fn ctor(self, dest: Pin<&mut MaybeUninit<Output>>) {
190 self.0(dest);
191 }
192}
193
194/// !Unpin to override the blanket Ctor impl.
195impl<Output, F> !Unpin for FnCtor<Output, F> {}
196
197/// Copy type.
198///
199/// This creates a new `P::Target` by copying -- either copy-construction
200/// (construction from `&*P`), or copy-assignment (assignment from &*P`). It can
201/// also be used directly as a `Ctor`.
202///
203/// Note: this does not actually copy `P` until it is used.
204#[must_use = must_use_ctor_assign!("Copy")]
205pub struct Copy<P: Deref>(P);
206
207impl<Output: for<'a> CtorNew<&'a Output>, P: Deref<Target = Output>> Ctor for Copy<P> {
208 type Output = Output;
209
210 unsafe fn ctor(self, dest: Pin<&mut MaybeUninit<Output>>) {
211 Output::ctor_new(&*self.0).ctor(dest);
212 }
213}
214
215/// !Unpin to override the blanket Ctor impl.
216impl<P> !Unpin for Copy<P> {}
217
218/// Returns a `Copy` which can be used as a `CtorNew` or `Assign` source, or as
219/// a `Ctor` directly.
220///
221/// Note: this does not actually copy the parameter until it is used.
222pub fn copy<T: for<'a> CtorNew<&'a T>, P: Deref<Target = T>>(src: P) -> Copy<P> {
223 Copy(src)
224}
225
226// ================================
227// DerefMut based move construction
228// ================================
229
Devin Jeanpierre8e54c2f2022-08-04 02:56:35 -0700230/// Rvalue Reference (move-reference) type.
231///
232/// This creates a new `T` by moving -- either move-construction (construction
233/// from `RvalueReference(&*P)`), or move-assignment (assignment from
234/// `RvalueReference(&*P)`).
235///
236/// Note: this does not actually move until it is used.
237#[must_use = must_use_ctor_assign!("RvalueReference")]
Devin Jeanpierredeea7892022-03-29 02:13:31 -0700238#[repr(transparent)]
Devin Jeanpierre8e54c2f2022-08-04 02:56:35 -0700239pub struct RvalueReference<'a, T>(pub Pin<&'a mut T>);
Devin Jeanpierref643afa2022-02-23 20:50:48 +0000240
241impl<T> RvalueReference<'_, T> {
242 pub fn as_const(&self) -> ConstRvalueReference<'_, T> {
243 ConstRvalueReference(&*self.0)
244 }
245
246 pub fn as_mut(&mut self) -> Pin<&mut T> {
247 self.0.as_mut()
248 }
249
250 pub fn get_ref(&self) -> &T {
251 // It would be nice to return &'a T, but that would not be sound, and as a
252 // result Pin makes it impossible (in safe code). Consider:
253 //
254 // let my_pin: Pin<&mut T> = ...;
255 // let my_borrow = RvalueReference(my_pin.as_mut()).get_ref();
256 //
257 // The lifetime of my_borrow CANNOT be 'a, but instead MUST be scoped to the
258 // reborrowed lifetime of the pin, or else it would violate the aliasing
259 // rules by coexisting with my_pin. Thus, get_ref must return &T, not
260 // &'a T. (For the same reason, as_const returns a ConstRvalueReference
Devin Jeanpierre8e54c2f2022-08-04 02:56:35 -0700261 // whose lifetime is bound by self, not 'a.)
Devin Jeanpierref643afa2022-02-23 20:50:48 +0000262 &*self.0
263 }
264}
265
Googler0c5c99a2023-03-23 13:55:31 -0700266impl<T> Deref for RvalueReference<'_, T> {
267 type Target = T;
268 fn deref(&self) -> &Self::Target {
269 self.get_ref()
270 }
271}
272
Devin Jeanpierre8e54c2f2022-08-04 02:56:35 -0700273impl<'a, T> Ctor for RvalueReference<'a, T>
274where
275 T: CtorNew<Self>,
Devin Jeanpierref643afa2022-02-23 20:50:48 +0000276{
Devin Jeanpierre8e54c2f2022-08-04 02:56:35 -0700277 type Output = T;
Devin Jeanpierref643afa2022-02-23 20:50:48 +0000278
Devin Jeanpierre8e54c2f2022-08-04 02:56:35 -0700279 unsafe fn ctor(self, dest: Pin<&mut MaybeUninit<T>>) {
280 T::ctor_new(self).ctor(dest);
Devin Jeanpierref643afa2022-02-23 20:50:48 +0000281 }
282}
283
Googler7059c3a2023-04-04 04:04:37 -0700284/// Converts to an RvalueReference.
285///
286/// Do not use this trait directly, instead, cast to an RvalueReference using
287/// the `mov!()` macro.
288pub trait DerefRvalueReference: Deref
289where
290 Self::Target: Sized,
291{
292 fn deref_rvalue_reference(&mut self) -> RvalueReference<'_, Self::Target>;
293}
294
295impl<T> DerefRvalueReference for Pin<T>
296where
297 T: DerefMut,
298 Self::Target: Sized,
299{
300 fn deref_rvalue_reference(&mut self) -> RvalueReference<'_, Self::Target> {
301 RvalueReference(self.as_mut())
302 }
303}
304
305impl<T> DerefRvalueReference for &mut T
306where
307 T: Unpin,
308 Self::Target: Sized,
309{
310 fn deref_rvalue_reference(&mut self) -> RvalueReference<'_, Self::Target> {
311 RvalueReference(Pin::new(self))
312 }
313}
314
Devin Jeanpierre8e54c2f2022-08-04 02:56:35 -0700315/// !Unpin to override the blanket `Ctor` impl.
316impl<'a, T> !Unpin for RvalueReference<'a, T> {}
Devin Jeanpierref643afa2022-02-23 20:50:48 +0000317
Devin Jeanpierre8e54c2f2022-08-04 02:56:35 -0700318/// Const rvalue reference (move-reference) type. Usually not very helpful.
319///
320/// This implicitly converts to `T` by const-moving -- either
321/// const-move-construction (construction from `ConstRvalueReference(&x)`), or
322/// const-move-assignment (assignment from `ConstRvalueReference(&x)`).
323#[must_use = must_use_ctor_assign!("ConstRvalueReference")]
Devin Jeanpierredeea7892022-03-29 02:13:31 -0700324#[repr(transparent)]
Devin Jeanpierre8e54c2f2022-08-04 02:56:35 -0700325pub struct ConstRvalueReference<'a, T>(pub &'a T);
Devin Jeanpierref643afa2022-02-23 20:50:48 +0000326
327impl<'a, T> ConstRvalueReference<'a, T> {
328 pub fn get_ref(&mut self) -> &'a T {
329 self.0
330 }
331}
332
Googler0c5c99a2023-03-23 13:55:31 -0700333impl<T> Deref for ConstRvalueReference<'_, T> {
334 type Target = T;
335 fn deref(&self) -> &Self::Target {
336 self.0
337 }
338}
339
Devin Jeanpierre8e54c2f2022-08-04 02:56:35 -0700340impl<'a, T> Ctor for ConstRvalueReference<'a, T>
341where
342 T: CtorNew<Self>,
Devin Jeanpierref643afa2022-02-23 20:50:48 +0000343{
Devin Jeanpierre8e54c2f2022-08-04 02:56:35 -0700344 type Output = T;
Devin Jeanpierref643afa2022-02-23 20:50:48 +0000345
Devin Jeanpierre8e54c2f2022-08-04 02:56:35 -0700346 unsafe fn ctor(self, dest: Pin<&mut MaybeUninit<T>>) {
347 T::ctor_new(self).ctor(dest);
Devin Jeanpierref643afa2022-02-23 20:50:48 +0000348 }
349}
350
Devin Jeanpierre8e54c2f2022-08-04 02:56:35 -0700351/// !Unpin to override the blanket `Ctor` impl.
352impl<'a, T> !Unpin for ConstRvalueReference<'a, T> {}
Devin Jeanpierref643afa2022-02-23 20:50:48 +0000353
354/// Creates a "to-be-moved" pointer for `src`.
355///
Devin Jeanpierre8e54c2f2022-08-04 02:56:35 -0700356/// In other words, this is analogous to C++ `std::move`, except that this can
357/// directly create an `RvalueReference<T>` out of e.g. a `Pin<Box<T>>`. The
358/// resulting `RvalueReference` has the lifetime of a temporary, after which the
359/// parameter is destroyed.
Devin Jeanpierref643afa2022-02-23 20:50:48 +0000360///
Devin Jeanpierre8e54c2f2022-08-04 02:56:35 -0700361/// The resulting `RvalueReference` can be used as a `CtorNew` or `Assign`
362/// source, or as a `Ctor` directly.
Devin Jeanpierref643afa2022-02-23 20:50:48 +0000363///
364/// Note: this does not actually move the parameter until it is used.
Devin Jeanpierre8e54c2f2022-08-04 02:56:35 -0700365#[macro_export]
366macro_rules! mov {
367 ($p:expr) => {
Googler7059c3a2023-04-04 04:04:37 -0700368 $crate::DerefRvalueReference::deref_rvalue_reference(&mut { $p })
Devin Jeanpierre8e54c2f2022-08-04 02:56:35 -0700369 };
Devin Jeanpierref643afa2022-02-23 20:50:48 +0000370}
371
Devin Jeanpierre8e54c2f2022-08-04 02:56:35 -0700372#[macro_export]
373macro_rules! const_mov {
374 ($p:expr) => {
375 $crate::ConstRvalueReference(&*{ $p })
376 };
Devin Jeanpierref643afa2022-02-23 20:50:48 +0000377}
378
379// =============
380// Blanket impls
381// =============
382//
383// For interop with C++ templates that may need to take Rust types, we will want
384// blanket impls for Rust types where it is safe to do so.
385
386/// All Rust types are their own constructor, if it is known to be safe (i.e.
387/// Unpin).
388///
389/// (Note that this is an approximation: some types are safe to deal with by
390/// value, as long as they have never been pinned. In `ctor`, we assume
391/// that *anything* which is `!Unpin` is only safe to initialize via a manually
392/// provided `Ctor`.)
393///
394/// (Note: to avoid overlapping impls, every type that implements `Ctor` by hand
395/// must be `!Unpin`.)
396///
397/// This allows code to safely accept direct initialization of `Unpin` Rust
398/// values, while also accepting `Ctor`-based initialization for `!Unpin`
399/// values: use `Ctor`-based initialization for both, and as a special case,
400/// `Ctor`-based initialization looks identical to direct initialization when
401/// the value is `Unpin`. For example, the `ctor!` macro looks like direct
402/// initialization for everything `Unpin`.
403///
404/// A contrasting design might be to have a separate initialization syntax for
405/// direct vs `Ctor`-based initialization. However, that would still likely need
406/// to be restricted to `Unpin` types for safety.
407impl<T: Unpin> Ctor for T {
408 type Output = T;
409 unsafe fn ctor(self, mut dest: Pin<&mut MaybeUninit<Self>>) {
410 dest.as_mut_ptr().write(self);
411 }
412}
413
414/// Constructs via a Rust move.
415#[must_use = must_use_ctor!()]
416pub struct RustMoveCtor<T>(T);
417impl<T> !Unpin for RustMoveCtor<T> {}
418impl<T> Ctor for RustMoveCtor<T> {
419 type Output = T;
420 unsafe fn ctor(self, dest: Pin<&mut MaybeUninit<T>>) {
421 Pin::into_inner_unchecked(dest).as_mut_ptr().write(self.0);
422 }
423}
424
425/// All Rust types are C++-default-constructible if safe (i.e. Unpin + Default).
426impl<T: Unpin + Default + Sized> CtorNew<()> for T {
427 type CtorType = RustMoveCtor<Self>;
428 fn ctor_new(_: ()) -> Self::CtorType {
429 RustMoveCtor(Default::default())
430 }
431}
432
Devin Jeanpierref643afa2022-02-23 20:50:48 +0000433/// All Unpin Rust types are C++-copyable if they are Rust-cloneable.
434///
435/// (Unpin is required for safety; otherwise, this would violate the Pin
436/// guarantee.)
437impl<T: Unpin + Clone> CtorNew<&T> for T {
438 type CtorType = RustMoveCtor<Self>;
439 fn ctor_new(src: &Self) -> Self::CtorType {
440 RustMoveCtor(src.clone())
441 }
442}
443
Devin Jeanpierref643afa2022-02-23 20:50:48 +0000444// ===========
445// ctor_then()
446// ===========
447
448/// A `Ctor` which constructs using `self.ctor`, and then invokes `f` on the
449/// resulting object.
450///
451/// This struct is created by the `ctor_then` method on `Ctor`. See its
452/// documentation for more.
453#[must_use = must_use_ctor!()]
454pub struct CtorThen<C: Ctor, F: FnOnce(Pin<&mut C::Output>)> {
455 ctor: C,
456 f: F,
457}
458
459impl<C: Ctor, F: FnOnce(Pin<&mut C::Output>)> Ctor for CtorThen<C, F> {
460 type Output = C::Output;
461 unsafe fn ctor(self, mut dest: Pin<&mut MaybeUninit<Self::Output>>) {
462 self.ctor.ctor(dest.as_mut());
463 let dest = Pin::new_unchecked(Pin::into_inner_unchecked(dest).assume_init_mut());
464 (self.f)(dest)
465 }
466}
467
468impl<C: Ctor, F: FnOnce(Pin<&mut C::Output>)> !Unpin for CtorThen<C, F> {}
469
470// ========
471// emplace!
472// ========
473//
474// The emplace!{} macro is now a little simpler, as it doesn't require StackBox
475// in the public interface: it can use &mut.
476
477/// Emplace a constructor into a local or temporary.
478/// Syntax: `emplace! { let mut varname = expr() }`, where `expr()` evaluates to
479/// a `Ctor<Output=T>`. `varname` will be a `Pin<&mut T>`.
480///
481/// If the emplaced value will just be used for the duration of one statement,
482/// the `emplace!(ctor)` syntax can be used instead, to emplace the ctor into a
483/// temporary. e.g. `foo(emplace!(ctor))` to pass a pinned reference to the
484/// emplaced value to a function.
485#[macro_export]
486macro_rules! emplace {
487 ($expr:expr) => {
488 $crate::Slot::unsafe_new().unsafe_construct($expr).unsafe_as_pin_unchecked()
489 };
490 (@emplace_one let [$($mut_:tt)?] $var:ident [$($type_:tt)*]= $expr:expr;) => {
491 let mut $var = $crate::Slot::unsafe_new();
492 $var.unsafe_construct($expr);
493 let $($mut_)* $var $($type_)* = $var.unsafe_as_pin_unchecked();
494 };
495 // Base case for repeated lets: empty emplace.
496 () => {};
497 // Recursive case: let [mut] x [: T] = ...;
498 // There are four different combinations of mutability and explicit type parameter, we have to
499 // match all of them.
500 (let mut $var:ident : $t:ty = $expr:expr; $($remaining_lets:tt)*) => {
501 $crate::emplace! {@emplace_one let [mut] $var [:$t] = $expr;}
502 $crate::emplace! {$($remaining_lets)*};
503 };
504 (let mut $var:ident = $expr:expr; $($remaining_lets:tt)*) => {
505 $crate::emplace! {@emplace_one let [mut] $var []= $expr;}
506 $crate::emplace! {$($remaining_lets)*};
507 };
508 (let $var:ident : $t:ty = $expr:expr; $($remaining_lets:tt)*) => {
509 $crate::emplace! {@emplace_one let [] $var [:$t] = $expr;}
510 $crate::emplace! {$($remaining_lets)*};
511 };
512 (let $var:ident = $expr:expr; $($remaining_lets:tt)*) => {
513 $crate::emplace! {@emplace_one let [] $var [] = $expr;}
514 $crate::emplace! {$($remaining_lets)*};
515 };
516}
517
518// ====
519// Slot
520// ====
521//
522// Alternate design: we could expose without the is_initialized flag, which
523// would require that all users initialize the type before drop. We may still
524// need such a type for interop, since that can be repr(transparent). But it is
525// *exceptionally* dangerous, as it requires that all code paths will initialize
526// before drop. For example, it means that Ctor is not allowed to panic.
527//
528// Hypothesis: at least for local variables and reasoning, rustc will be able to
529// elide the bool and be equally performant, while also being substantially
530// safer.
531
532/// A pinned optional type, which can store in-place constructed objects.
533///
534/// To create a slot safely, it must be constructed in place, using (for
535/// example) the `emplace!` macro. It then can operate as a structurally pinned
536/// variant of `Option`, allowing for pinned access to the interior.
537///
538/// Examples:
539///
540/// ```
541/// // Slots can be used to implement a "slotted return value".
542/// fn slotted_return(slot: Pin<&mut Slot<u32>>) -> Pin<&mut u32> {
543/// slot.replace(42)
544/// }
545///
546/// emplace! {let slot = Slot::uninit(); }
547/// let rv = slotted_return(slot);
548/// assert_eq!(*rv, 42);
549/// ```
550///
551/// ```
552/// // Slots can also be used for plain output parameters.
553/// fn slotted_out_param(slot: Pin<&mut Slot<u32>>) {
554/// slot.replace(42);
555/// }
556///
557/// emplace! {let mut slot = Slot::uninit(); }
558/// slotted_out_param(slot.as_mut());
559/// assert_eq!(*slot.as_opt().unwrap(), 42);
560/// ```
561pub struct Slot<T> {
562 is_initialized: bool,
563 maybe_uninit: MaybeUninit<T>,
564}
565
566impl<T> Drop for Slot<T> {
567 fn drop(&mut self) {
568 unsafe { Pin::new_unchecked(self) }.clear()
569 }
570}
571
572impl<T> !Unpin for Slot<T> {}
573
574impl<T> Slot<T> {
575 pub fn uninit() -> impl Ctor<Output = Self> {
576 RustMoveCtor(Self::unsafe_new())
577 }
578
579 pub fn new(value: impl Ctor<Output = T>) -> impl Ctor<Output = Self> {
580 RustMoveCtor(Self::unsafe_new()).ctor_then(|slot| {
581 slot.replace(value);
582 })
583 }
584
585 pub fn clear(self: Pin<&mut Self>) {
586 if self.is_initialized {
587 let Self { is_initialized, maybe_uninit } = unsafe { Pin::into_inner_unchecked(self) };
588 unsafe {
Googlerf8296f82023-03-03 13:55:23 -0800589 core::ptr::drop_in_place(maybe_uninit.as_mut_ptr());
Devin Jeanpierref643afa2022-02-23 20:50:48 +0000590 }
591 *is_initialized = false;
592 }
593 }
594
595 pub fn replace(mut self: Pin<&mut Self>, value: impl Ctor<Output = T>) -> Pin<&mut T> {
596 self.as_mut().clear();
597 {
598 let Self { is_initialized, maybe_uninit } =
599 unsafe { Pin::into_inner_unchecked(self.as_mut()) };
600 unsafe {
601 value.ctor(Pin::new_unchecked(maybe_uninit));
602 }
603 *is_initialized = true;
604 }
605 self.as_opt_mut().unwrap()
606 }
607
608 pub fn as_opt_mut(self: Pin<&mut Self>) -> Option<Pin<&mut T>> {
609 if self.is_initialized {
610 Some(unsafe { Pin::into_inner_unchecked(self) }.unsafe_as_pin_unchecked())
611 } else {
612 None
613 }
614 }
615
616 pub fn as_opt(&self) -> Option<&T> {
617 if self.is_initialized {
618 Some(unsafe { self.maybe_uninit.assume_init_ref() })
619 } else {
620 None
621 }
622 }
623}
624
625// Hidden: these are only for use by safety macros.
626#[doc(hidden)]
627impl<T> Slot<T> {
628 pub fn unsafe_new() -> Self {
629 Slot { is_initialized: false, maybe_uninit: MaybeUninit::uninit() }
630 }
631
632 // The following two functions are not marked `unsafe` so that they can be
633 // called from a single expression in a macro, without an `unsafe{}` block
634 // which would also cover macro parameters.
635 //
636 // One alternative would be an immediately-invoked lambda, but this forces type
637 // inference, which leads to confusing error messages when it isn't
638 // inferrable. And, since this is a lambda, the type is not known concretely
639 // to begin with!
640 //
641 // We could instead use a generic function with `impl Ctor` and the like, but
642 // this function would be unsafe... leading back to the very original
643 // problem!
644 //
645 // So here we bite the bullet: these functions should ideally be marked
646 // "unsafe", but, seeing as they are only invoked from a macro, and that
647 // macro needs to invoke expressions in calls to these functions, they are
648 // only *named* "unsafe_foo" instead.
649
650 /// Safety: must not have already been constructed, as that would violate
651 /// the pin guarantee.
652 pub fn unsafe_construct(&mut self, ctor: impl Ctor<Output = T>) -> &mut Self {
653 unsafe { ctor.ctor(Pin::new_unchecked(&mut self.maybe_uninit)) };
654 self.is_initialized = true;
655 self
656 }
657
658 /// Safety: pin guarantee, assumes init.
659 pub fn unsafe_as_pin_unchecked(&mut self) -> Pin<&mut T> {
660 unsafe { Pin::new_unchecked(self.maybe_uninit.assume_init_mut()) }
661 }
662}
663
664#[doc(hidden)]
665pub mod macro_internal {
666 use super::*;
Googlerf8296f82023-03-03 13:55:23 -0800667 pub use core::mem::MaybeUninit;
668 pub use core::pin::Pin;
Devin Jeanpierref643afa2022-02-23 20:50:48 +0000669
Devin Jeanpierrea330af62022-06-09 17:03:45 -0700670 /// Workaround for more_qualified_paths.
671 /// Instead of `<Foo as Bar>::Assoc { ... }`, which requires that feature,
672 /// we can use `Identity<<Foo as Bar>::Assoc> { ... }`.
673 ///
674 /// See https://github.com/rust-lang/rust/issues/86935#issuecomment-1146670057
675 ///
676 /// TODO(jeanpierreda): Delete this when the feature is stabilized.
677 pub type Identity<T> = T;
678
Devin Jeanpierrebe1efd22022-05-10 16:52:07 -0700679 /// Trait which causes compilation error if a `#[recursively_pinned]` struct
680 /// impls `Drop`.
681 ///
682 /// Idea from https://docs.rs/pin-project/latest/pin_project/attr.pin_project.html#safety
683 pub trait DoNotImplDrop {}
684 #[allow(drop_bounds)]
685 impl<T: Drop> DoNotImplDrop for T {}
686
Devin Jeanpierref643afa2022-02-23 20:50:48 +0000687 /// Drops a pointer when dropped.
688 ///
689 /// Safety: this will drop the pointer, so this is only safe if no other
690 /// code will access the pointer afterwards. This includes drop: the
691 /// pointer must itself be in a ManuallyDrop.
692 pub struct UnsafeDropGuard<T>(*mut T);
693 impl<T> Drop for UnsafeDropGuard<T> {
694 fn drop(&mut self) {
Googlerf8296f82023-03-03 13:55:23 -0800695 unsafe { core::ptr::drop_in_place(self.0) };
Devin Jeanpierref643afa2022-02-23 20:50:48 +0000696 }
697 }
698
699 /// Initializes a field, and returns a drop guard which will drop that
700 /// field.
701 ///
702 /// Intended use: when initializing a struct field-by-field, each
703 /// initialized field should be guarded in case of panic. Once the
704 /// struct is completely initialized, the drop guards can be forgotten
705 /// with `std::mem::forget()`. See the `ctor!` macro, where this is used.
706 ///
707 /// Safety: the field must satisfy the Pin guarantee.
708 pub unsafe fn init_field<T>(field: *mut T, ctor: impl Ctor<Output = T>) -> impl Drop {
709 // safety: MaybeUninit<T> is the same layout as T, the caller guarantees it's
710 // pinned.
711 let maybe_uninit = field as *mut MaybeUninit<T>;
712 let pinned = Pin::new_unchecked(&mut *maybe_uninit);
713 Ctor::ctor(ctor, pinned);
714 UnsafeDropGuard(field)
715 }
716
717 pub fn require_recursively_pinned<_T: RecursivelyPinned>() {}
718}
719
Devin Jeanpierrebe1efd22022-05-10 16:52:07 -0700720// =====================
721// #[recursively_pinned]
722// =====================
Devin Jeanpierref643afa2022-02-23 20:50:48 +0000723
Devin Jeanpierrebe1efd22022-05-10 16:52:07 -0700724/// The `RecursivelyPinned` trait asserts that when the struct is pinned, every
Devin Jeanpierref643afa2022-02-23 20:50:48 +0000725/// field is also pinned.
726///
Devin Jeanpierref643afa2022-02-23 20:50:48 +0000727/// This trait is automatically implemented for any `#[recursively_pinned]`
728/// struct.
Devin Jeanpierrea330af62022-06-09 17:03:45 -0700729///
730/// ## Safety
731///
732/// Only use if you never directly access fields of a pinned object. For
733/// example, with the pin-project crate, all fields should be marked `#[pin]`.
734pub unsafe trait RecursivelyPinned {
735 /// An associated type with the same fields, minus any which are not
736 /// initialized by the `ctor!()` macro.
737 ///
738 /// For example, the following struct `CtorOnly` can be constructed by value
739 /// using `ctor!()`, but not using normal Rust initialization.
740 /// Effectively, the struct is forced into only ever existing in a
741 /// pinned state.
742 ///
743 /// ```
744 /// // (Alternatively, `#[non_exhaustive]` may be used instead of the private field.)
745 /// pub struct CtorOnly {
746 /// pub field: i32,
747 /// _must_construct_using_ctor: [(); 0],
748 /// }
749 ///
750 /// // The same struct, but without the private field.
751 /// // (Alternatively, without `#[non_exhaustive]`.)
752 /// pub struct CtorOnlyFields {
753 /// pub field: i32,
754 /// }
755 ///
756 /// unsafe impl RecursivelyPinned for CtorOnly {
757 /// type CtorInitializedFields = CtorOnlyFields;
758 /// }
759 /// ```
760 ///
761 /// By using `CtorInitializedFields` paired with a private field (or
762 /// `#[non_exhaustive]`), the following code is now invalid:
763 ///
764 /// ```ignore
765 /// # // TODO(jeanpierreda): make this tested, somehow.
766 /// // Fails to compile: did not specify _must_construct_using_ctor, and cannot,
767 /// // because it is private
768 /// let x = CtorOnly {field: 3};
769 /// ```
770 ///
771 /// While construction using `ctor!()` works fine:
772 ///
773 /// ```ignore
774 /// emplace!{let x = ctor!(CtorOnly {field: 3})}
775 /// ```
776 ///
777 /// The size and layout of `CtorInitializedFields` is ignored; it only
778 /// affects which field names are required for complete `ctor!()`
779 /// initialization. Any fields left out of the `CtorInitializedFields` type
780 /// will not be initialized, so they should generally be zero-sized.
781 type CtorInitializedFields;
782}
Devin Jeanpierref643afa2022-02-23 20:50:48 +0000783
Devin Jeanpierrebe1efd22022-05-10 16:52:07 -0700784/// The drop trait for `#[recursively_pinned(PinnedDrop)]` types.
785///
786/// It is never valid to implement `Drop` for a recursively-pinned type, as this
787/// would be unsound: the `&mut self` in `drop` would allow the pin guarantee to
788/// be violated.
789///
790/// Instead, if such a struct is to implement drop, it must pass `PinnedDrop` to
791/// `recursively_pinned`, and implement the `PinnedDrop` trait.
792///
793/// See also the [analogous `pin_project` feature](https://docs.rs/pin-project/latest/pin_project/attr.pinned_drop.html)
794pub trait PinnedDrop {
795 /// Run the drop logic for self.
796 ///
797 /// ## Safety
798 ///
799 /// If called from anywhere other than the automatically-generated
800 /// `Drop::drop`, the behavior is undefined.
801 ///
802 /// To manually drop the value, use `ManuallyDrop` or use
803 /// `std::ptr::drop_in_place` (etc.) instead.
804 unsafe fn pinned_drop(self: Pin<&mut Self>);
805}
806
807// =====
808// ctor!
809// =====
810
Devin Jeanpierref643afa2022-02-23 20:50:48 +0000811/// The `ctor!` macro evaluates to a `Ctor` for a Rust struct, with
812/// user-specified fields.
813///
814/// (This was inspired by, but takes no code from, https://crates.io/crates/project-uninit.)
815///
816/// Example use:
817///
818/// ```
819/// fn new() -> impl Ctor<Output=MyStruct> {
820/// ctor!(MyStruct {field_1: default_ctor(), field_2: 42})
821/// }
822///
823/// // Actually invoke the Ctor to create a new MyStruct:
824/// emplace! { let mut my_struct = MyStruct::new(); }
825/// ```
826#[macro_export]
827macro_rules! ctor {
828 // Note: we're using `ident (::ident)*` for the type names because neither `ident` nor `path`
829 // really work perfectly -- `ident` is great, except that `foo::bar` isn't an ident. `path` is
830 // great, except that e.g. parentheses can't follow a path. (This is not fixable: FnOnce(T) is
831 // also a path, so parens can't follow paths due to the ambiguous parse). Thus... we use ident,
832 // and manually reconstruct the path.
833 //
834 // TODO(jeanpierreda): support <X as Y> and foo<Z> in paths.
835 //
836 // tt is used for the field names, because this allows for both integer fields for tuple
837 // structs, and named fields for non-tuple structs.
838 ( $t:ident $(:: $ts:ident)* {$( $name:tt: $sub_ctor:expr ),* $(,)?} ) => {
839 {
840 use $t $(:: $ts)* as Type;
841 $crate::FnCtor::new(|x: $crate::macro_internal::Pin<&mut $crate::macro_internal::MaybeUninit<Type>>| {
Devin Jeanpierrea4394dc2022-05-09 06:10:06 -0700842 // Unused if Type is fieldless.
Googlerf8296f82023-03-03 13:55:23 -0800843 #[allow(unused_imports)] use ::core::ptr::addr_of_mut;
Devin Jeanpierrea4928262023-03-03 13:10:08 -0800844 struct DropGuard;
845 let drop_guard = DropGuard;
Devin Jeanpierref643afa2022-02-23 20:50:48 +0000846 let x_mut = unsafe{$crate::macro_internal::Pin::into_inner_unchecked(x)}.as_mut_ptr();
Devin Jeanpierrea4394dc2022-05-09 06:10:06 -0700847 let _ = &x_mut; // silence unused_variables warning if Type is fieldless.
Devin Jeanpierref643afa2022-02-23 20:50:48 +0000848
849 // Enforce that the ctor!() expression resembles a valid direct initialization
850 // expression, by using the names in a conventional literal.
851 // For structs, this fails to compile unless the names are fully exhaustive.
852 // For unions, it fails to compile unless precisely one name is used.
853 // In both cases, this ensures that we only compile when expressions corresponding
854 // to normal init are used, with unsurprising semantics.
855 let _ = |x: Type| {
Devin Jeanpierrea4394dc2022-05-09 06:10:06 -0700856 let _ = &x; // silence unused_variables warning if Type is fieldless.
Devin Jeanpierref643afa2022-02-23 20:50:48 +0000857 // If this fails to compile, not every field was specified in the ctor! invocation.
858 // The `panic!(...)` allows us to avoid moving out of x, while still pretending to
859 // fill in each field.
Devin Jeanpierrea330af62022-06-09 17:03:45 -0700860 #[allow(unreachable_code, unused_unsafe)] $crate::macro_internal::Identity::<
861 <Type as $crate::RecursivelyPinned>::CtorInitializedFields> {
862 // unsafe {} block is in case this is a *union* literal, rather than
863 // a struct literal.
864 $($name: panic!("{}", unsafe {&x.$name} as *const _ as usize),)*
865 };
Devin Jeanpierref643afa2022-02-23 20:50:48 +0000866 };
867
Devin Jeanpierrea330af62022-06-09 17:03:45 -0700868 // Enforce that the type is RecursivelyPinned.
Devin Jeanpierref643afa2022-02-23 20:50:48 +0000869 $crate::macro_internal::require_recursively_pinned::<Type>();
870
871 $(
872 let sub_ctor = $sub_ctor;
873 let field_drop = unsafe {
874 $crate::macro_internal::init_field(
875 // safety: this is almost verbatim the same as the second example at
876 // https://doc.rust-lang.org/nightly/std/ptr/macro.addr_of_mut.html
877 addr_of_mut!((*x_mut).$name),
878 sub_ctor)
879 };
880 let drop_guard = (drop_guard, field_drop);
881 )*
Googlerf8296f82023-03-03 13:55:23 -0800882 ::core::mem::forget(drop_guard);
Devin Jeanpierref643afa2022-02-23 20:50:48 +0000883 })
884 }
885 };
886
Devin Jeanpierrea4394dc2022-05-09 06:10:06 -0700887 // Unit struct ctor.
888 ($t:ident $(:: $ts:ident)*) => {$crate::ctor!($t $(:: $ts)* { })};
889
Devin Jeanpierref643afa2022-02-23 20:50:48 +0000890 // Conventional tuple struct syntax (with parens, no integer names) supported for < 8 fields.
891 // Otherwise, use MyTupleStruct{0: ..., 1: ...} syntax, which works for any number of fields.
892 // Generated as so:
893 /* python3 -c 'for i in range(8):
894 ctor_ins = ", ".join(f"$ctor_{j}:expr" for j in range(i))
895 ctor_outs = ", ".join(f"{j}: $ctor_{j}" for j in range(i))
896 print(f" ($t:ident $(:: $ts:ident)* ({ctor_ins})) => {{$crate::ctor!($t $(:: $ts)* {{ {ctor_outs} }})}};")' */
897 ($t:ident $(:: $ts:ident)* ()) => {$crate::ctor!($t $(:: $ts)* { })};
898 ($t:ident $(:: $ts:ident)* ($ctor_0:expr)) => {$crate::ctor!($t $(:: $ts)* { 0: $ctor_0 })};
899 ($t:ident $(:: $ts:ident)* ($ctor_0:expr, $ctor_1:expr)) => {$crate::ctor!($t $(:: $ts)* { 0: $ctor_0, 1: $ctor_1 })};
900 ($t:ident $(:: $ts:ident)* ($ctor_0:expr, $ctor_1:expr, $ctor_2:expr)) => {$crate::ctor!($t $(:: $ts)* { 0: $ctor_0, 1: $ctor_1, 2: $ctor_2 })};
901 ($t:ident $(:: $ts:ident)* ($ctor_0:expr, $ctor_1:expr, $ctor_2:expr, $ctor_3:expr)) => {$crate::ctor!($t $(:: $ts)* { 0: $ctor_0, 1: $ctor_1, 2: $ctor_2, 3: $ctor_3 })};
902 ($t:ident $(:: $ts:ident)* ($ctor_0:expr, $ctor_1:expr, $ctor_2:expr, $ctor_3:expr, $ctor_4:expr)) => {$crate::ctor!($t $(:: $ts)* { 0: $ctor_0, 1: $ctor_1, 2: $ctor_2, 3: $ctor_3, 4: $ctor_4 })};
903 ($t:ident $(:: $ts:ident)* ($ctor_0:expr, $ctor_1:expr, $ctor_2:expr, $ctor_3:expr, $ctor_4:expr, $ctor_5:expr)) => {$crate::ctor!($t $(:: $ts)* { 0: $ctor_0, 1: $ctor_1, 2: $ctor_2, 3: $ctor_3, 4: $ctor_4, 5: $ctor_5 })};
904 ($t:ident $(:: $ts:ident)* ($ctor_0:expr, $ctor_1:expr, $ctor_2:expr, $ctor_3:expr, $ctor_4:expr, $ctor_5:expr, $ctor_6:expr)) => {$crate::ctor!($t $(:: $ts)* { 0: $ctor_0, 1: $ctor_1, 2: $ctor_2, 3: $ctor_3, 4: $ctor_4, 5: $ctor_5, 6: $ctor_6 })};
905
906}
907
908// ==========
909// CtorNew traits
910// ==========
911//
912// Finally, we introduce some new traits for assignment.
913
Devin Jeanpierre97140a92022-03-18 17:09:35 +0000914/// Destroy-then-reconstruct. Sidesteps `operator=`, instead reconstructing
915/// in-place.
916///
917/// If the object cannot be destroyed/reconstructed in place (e.g. it is a base
918/// class subobject), the behavior is undefined.
919///
920/// If `ctor` unwinds, the process will crash.
921///
922/// This is a bit more fragile than, and a lot less common than, `operator=`,
923/// but allows for taking advantage of copy/move elision more aggressively,
924/// rather than requiring materialization into a temporary before triggering
925/// assignment.
926///
927/// That means that e.g. instead of calling `x.assign(&*emplace!(foo))`, you can
928/// directly call `x.reconstruct_unchecked(foo)` -- provided you are OK with the
929/// differing constructor/destructor ordering, and satisfy safety criteria.
930///
931/// # Safety
932///
933/// Dividing sources of UB by language ruleset:
934///
935/// **C++**: The behavior is undefined if `self` is a base class subobject
936/// or `[[no_unique_address]]` member.
937///
938/// See: http://eel.is/c++draft/basic.life#8
939///
940/// And see https://chat.google.com/room/AAAAl3r59xQ/auNOifgQa1c for discussion.
941///
942/// **Rust**: This is safe. Note that since this calls `drop()` on
943/// the pinned pointer, it satisfies the pin guarantee, and is allowed to then
944/// re-init it with something else. In effect, this is just the in-place Ctor
945/// version of the existing method `Pin<T>::set(T)`.
946pub trait ReconstructUnchecked: Sized {
947 /// # Safety
948 /// See trait documentation.
949 unsafe fn reconstruct_unchecked(self: Pin<&mut Self>, ctor: impl Ctor<Output = Self>) {
Dmitri Gribenko1752bf32022-03-21 20:29:54 +0000950 let self_ptr = Pin::into_inner_unchecked(self) as *mut _;
Googlerf8296f82023-03-03 13:55:23 -0800951 core::ptr::drop_in_place(self_ptr);
Devin Jeanpierre97140a92022-03-18 17:09:35 +0000952 abort_on_unwind(move || {
953 let maybe_uninit_self = &mut *(self_ptr as *mut MaybeUninit<Self>);
954 ctor.ctor(Pin::new_unchecked(maybe_uninit_self));
955 });
956 }
957}
958
959impl<T> ReconstructUnchecked for T {}
960
961/// Destroy-then-reconstruct. Sidesteps `operator=`, instead reconstructing
Devin Jeanpierref643afa2022-02-23 20:50:48 +0000962/// in-place.
963///
964/// If `ctor` unwinds, the process will crash.
965///
966/// This is a bit more fragile than, and a lot less common than, `operator=`,
967/// but allows for taking advantage of copy/move elision more aggressively,
968/// rather than requiring materialization into a temporary before triggering
969/// assignment.
970///
971/// That means that e.g. instead of calling `x.assign(&*emplace!(foo))`, you can
972/// directly call `x.reconstruct(foo)` -- provided you are OK with the differing
973/// constructor/destructor ordering.
974///
Devin Jeanpierre97140a92022-03-18 17:09:35 +0000975/// # Implementation safety
Devin Jeanpierref643afa2022-02-23 20:50:48 +0000976///
Devin Jeanpierre97140a92022-03-18 17:09:35 +0000977/// Implementors must ensure that it is safe to destroy and reconstruct the
978/// object. Most notably, if `Self` is a C++ class, it must not be a base class.
979/// See http://eel.is/c++draft/basic.life#8
980///
981/// # Safety
982///
983/// Note that this is not safe to call on `[[no_unique_address]]` member
984/// variables, but the interface is marked safe, because those can only be
985/// produced via unsafe means.
986pub unsafe trait Reconstruct: ReconstructUnchecked {
Devin Jeanpierref643afa2022-02-23 20:50:48 +0000987 fn reconstruct(self: Pin<&mut Self>, ctor: impl Ctor<Output = Self>) {
Devin Jeanpierre97140a92022-03-18 17:09:35 +0000988 unsafe { self.reconstruct_unchecked(ctor) };
Devin Jeanpierref643afa2022-02-23 20:50:48 +0000989 }
990}
991
Devin Jeanpierre97140a92022-03-18 17:09:35 +0000992/// Safety: anything implementing `Unpin` is Rust-assignable, and
993/// Rust-assignment is inherently destroy+reconstruct.
994unsafe impl<T: Unpin> Reconstruct for T {}
Devin Jeanpierref643afa2022-02-23 20:50:48 +0000995
996/// Run f, aborting if it unwinds.
997///
998/// Because this aborts on unwind, f is not required to be unwind-safe.
999#[inline]
1000fn abort_on_unwind<T, F: FnOnce() -> T>(f: F) -> T {
1001 // Here is another way we COULD implement abort_on_panic:
1002
1003 // let f = std::panic::AssertUnwindSafe(f);
1004 // let result = std::panic::catch_unwind(move || f.0());
1005 // if result.is_err() {
1006 // std::process::abort();
1007 // }
1008
1009 // It turns out this is a bad idea, because FFI unwinding, if/when added to
1010 // Rust, will sidestep catch_unwind, but NOT sidestep drop. So a C++
1011 // exception thrown in a Ctor might not get converted to a panic, but
1012 // instead to raw foreign unwinding, and drop impls in parent scopes
1013 // would be run. Since abort_on_unwind is intended to prevent *any* code from
1014 // executing and seeing temporarily-invalid state, this is incorrect.
1015 //
1016 // See e.g.: https://rust-lang.github.io/rfcs/2945-c-unwind-abi.html
1017 //
1018 // Instead, the only correct way to protect code from unwinding, even from
1019 // foreign unwinding, is via drop, as so:
1020
1021 /// A safety guard which panics if dropped, converting unwinds into aborts.
1022 ///
1023 /// In general, you can't, as the *author* of drop(), assume that it will be
1024 /// called: callers can just call std::mem::forget(), among other
1025 /// things. However, as the *user*, you can know that drop is called for
1026 /// unmoved values at the end of a drop scope. Drop is a defined behavior.
1027 /// So while there is ordinarily a prohibition on relying on drop for
1028 /// safety, that only occurs for API owners that are allowing values to
1029 /// be used in arbitrary ways (including forget). Here, we are API
1030 /// *users* as well, and specifically using the Bomb in a way that
1031 /// guarantees its drop will be called in a particular circumstance.
1032 ///
1033 /// See https://doc.rust-lang.org/reference/destructors.html, specifically this: "When control
1034 /// flow leaves a drop scope all variables associated to that scope are
1035 /// dropped in reverse order of declaration (for variables) or creation
1036 /// (for temporaries)."
1037 struct Bomb;
1038 impl Drop for Bomb {
1039 fn drop(&mut self) {
1040 panic!("Unwinding occurred when no safe recovery is possible.");
1041 }
1042 }
1043
1044 let bomb = Bomb;
1045 let rv = f();
Googlerf8296f82023-03-03 13:55:23 -08001046 core::mem::forget(bomb);
Devin Jeanpierref643afa2022-02-23 20:50:48 +00001047 rv
1048}
1049
1050/// Overloaded assignment operator.
1051///
1052/// Conventionally, C++ copy-assignment is Assign<&T>, and C++ move-assignment
1053/// is Assign<RvalueReference<'_, T>>.
1054pub trait Assign<From> {
1055 fn assign(self: Pin<&mut Self>, src: From);
1056}
1057
1058/// Assignment from a Copy desugars to an assignment from a &T.
1059impl<T: for<'a> Assign<&'a T>, P: Deref<Target = T>> Assign<Copy<P>> for T {
1060 fn assign(self: Pin<&mut Self>, src: Copy<P>) {
1061 self.assign(&*src.0);
1062 }
1063}
1064
Devin Jeanpierref643afa2022-02-23 20:50:48 +00001065// TODO(jeanpierreda): Make these less repetitive.
1066
1067impl<'a, T: Unpin + CtorNew<&'a T>> Assign<&'a T> for T {
1068 fn assign(mut self: Pin<&mut Self>, src: &'a Self) {
Googlerf8296f82023-03-03 13:55:23 -08001069 if core::mem::needs_drop::<Self>() {
Devin Jeanpierref643afa2022-02-23 20:50:48 +00001070 let mut constructed = MaybeUninit::uninit();
1071 unsafe {
1072 T::ctor_new(src).ctor(Pin::new(&mut constructed));
1073 *self = constructed.assume_init();
1074 }
1075 } else {
1076 self.reconstruct(T::ctor_new(src));
1077 }
1078 }
1079}
1080
1081impl<'a, T: Unpin + CtorNew<RvalueReference<'a, T>>> Assign<RvalueReference<'a, T>> for T {
1082 fn assign(mut self: Pin<&mut Self>, src: RvalueReference<'a, Self>) {
Googlerf8296f82023-03-03 13:55:23 -08001083 if core::mem::needs_drop::<Self>() {
Devin Jeanpierref643afa2022-02-23 20:50:48 +00001084 let mut constructed = MaybeUninit::uninit();
1085 unsafe {
1086 T::ctor_new(src).ctor(Pin::new(&mut constructed));
1087 *self = constructed.assume_init();
1088 }
1089 } else {
1090 self.reconstruct(T::ctor_new(src));
1091 }
1092 }
1093}
1094
1095impl<'a, T: Unpin + CtorNew<ConstRvalueReference<'a, T>>> Assign<ConstRvalueReference<'a, T>>
1096 for T
1097{
1098 fn assign(mut self: Pin<&mut Self>, src: ConstRvalueReference<'a, Self>) {
Googlerf8296f82023-03-03 13:55:23 -08001099 if core::mem::needs_drop::<Self>() {
Devin Jeanpierref643afa2022-02-23 20:50:48 +00001100 let mut constructed = MaybeUninit::uninit();
1101 unsafe {
1102 T::ctor_new(src).ctor(Pin::new(&mut constructed));
1103 *self = constructed.assume_init();
1104 }
1105 } else {
1106 self.reconstruct(T::ctor_new(src));
1107 }
1108 }
1109}
Googler7341f5e2023-01-31 14:37:12 -08001110
1111/// Overloaded assignment operator, but for Unpin types
1112/// TODO(b/219963671): use specialization instead of a distinct trait
1113pub trait UnpinAssign<From> {
1114 fn unpin_assign(&mut self, src: From);
1115}
1116
Devin Jeanpierref643afa2022-02-23 20:50:48 +00001117// =======================
1118// Constructor overloading
1119// =======================
1120//
1121// Constructors are unique among C++ functions in that overloading is common,
1122// *not avoidable*, and involves a nameless function best captured by a trait.
1123// In other words, it is the ideal choice for having a more generic trait as
1124// with From/Into.
1125//
1126// For exploration purposes, so that we can play with both approaches at the
1127// same time, this is built on *top* of the traits above.
1128
1129/// Overloaded constructor trait.
1130///
1131/// `T : CtorNew<(A, B, C)>` is roughly equivalent to the C++ "T has a
1132/// constructor taking arguments of type A, B, and C". As an obvious special
1133/// case, for singleton tuples, you may use `CtorNew<A>`.
1134pub trait CtorNew<ConstructorArgs> {
1135 type CtorType: Ctor<Output = Self>;
1136
1137 fn ctor_new(args: ConstructorArgs) -> Self::CtorType;
1138}
1139
Devin Jeanpierref643afa2022-02-23 20:50:48 +00001140// ====
1141// Misc
1142// ====
1143
1144/// A constructor for `PhantomPinned`.
1145///
1146/// ## Why doesn't `PhantomPinned` implement `Ctor<Output=Self>` ?
1147///
1148/// A self-impl, where `PhantomPinned : Ctor<Output=PhantomPinned>` would also
1149/// have been safe, even though `PhantomPinned` is `!Unpin`, because it's just a
1150/// marker. However, the trait coherence rules are not happy about this:
1151///
1152/// ```
1153/// // crate_1
1154/// #![feature(negative_impls)]
1155/// pub struct Foo;
1156/// impl !Unpin for Foo {}
1157/// ```
1158///
1159/// ```
1160/// // crate_2
1161/// trait MyTrait {}
1162/// impl<T: Unpin> MyTrait for T{}
1163/// impl MyTrait for crate_1::Foo {}
1164/// ```
1165///
1166/// (In our case, `Foo` is `std::marker::PhantomPinned`, and `MyTrait` is
1167/// `Ctor`)
1168///
1169/// Within `crate_1`, Rust understands that `Foo` is `!Unpin`. So `impl MyTrait
1170/// for Foo {}` is valid in `crate_1`. However, outside of `crate_1`, Rust
1171/// decides it doesn't know whether `Foo` implements `Unpin` or not, and so
1172/// incorrectly believes that the impls may conflict.
1173///
1174/// So while it is perfectly feasible to implement self-construction for any
1175/// type locally, we cannot give foreign impls.
1176pub struct PhantomPinnedCtor;
1177impl Ctor for PhantomPinnedCtor {
Googlerf8296f82023-03-03 13:55:23 -08001178 type Output = core::marker::PhantomPinned;
Devin Jeanpierref643afa2022-02-23 20:50:48 +00001179 unsafe fn ctor(self, dest: Pin<&mut MaybeUninit<Self::Output>>) {
Googlerf8296f82023-03-03 13:55:23 -08001180 RustMoveCtor(core::marker::PhantomPinned).ctor(dest)
Devin Jeanpierref643afa2022-02-23 20:50:48 +00001181 }
1182}
1183impl !Unpin for PhantomPinnedCtor {}
1184
1185/// A constructor for ManuallyDrop<T>, given a constructor for T.
1186///
1187/// ManuallyDrop is special as the only non-Copy type allowed in a union, so we
1188/// specifically support its use, even though it is not guaranteed to be
1189/// structurally pinned.
1190#[must_use = must_use_ctor!()]
1191pub struct ManuallyDropCtor<T: Ctor>(T);
1192
1193impl<T: Ctor> ManuallyDropCtor<T> {
1194 /// Safety: this structurally pins the contents of ManuallyDrop.
1195 /// Therefore, it is not safe to use with anything that assumes that
1196 /// ManuallyDrop is not structurally pinned.
1197 pub unsafe fn new(x: T) -> Self {
1198 ManuallyDropCtor(x)
1199 }
1200}
1201
1202impl<T: Ctor> Ctor for ManuallyDropCtor<T> {
1203 type Output = ManuallyDrop<T::Output>;
1204 unsafe fn ctor(self, dest: Pin<&mut MaybeUninit<Self::Output>>) {
1205 // Safety: ManuallyDrop<T> and T have the same layout.
1206 let dest = Pin::into_inner_unchecked(dest);
1207 let dest = &mut *(dest as *mut _ as *mut MaybeUninit<T::Output>);
1208 let dest = Pin::new_unchecked(dest);
1209 self.0.ctor(dest);
1210 }
1211}
1212
1213impl<T: Ctor> !Unpin for ManuallyDropCtor<T> {}
1214
Devin Jeanpierre83cb2dc2022-07-15 01:50:28 -07001215/// A utility trait to add lifetime bounds to an `impl Ctor`.
1216///
1217/// When returning trait impls, captures don't work as one would expect;
1218/// see https://github.com/rust-lang/rust/issues/66551
1219///
1220/// For example, this function does not compile:
1221///
1222/// ```compile_fail
1223/// fn adder<'a, 'b>(x: &'a i32, y: &'b i32) -> impl Fn() -> i32 + 'a + 'b {
1224/// move || *a + *b
1225/// }
1226/// ```
1227///
1228/// However, using Captures, we can write the following, which _does_ compile:
1229///
1230/// ```
1231/// fn adder<'a, 'b>(x: &'a i32, y: &'b i32) -> impl Fn() -> i32 + Captures<'a> + Captures<'b> {
1232/// move || *a + *b
1233/// }
1234/// ```
1235///
1236/// Since `Ctor` is a in essence glorified `impl Fn(...)`, and will often need
1237/// to retain function inputs, this helper trait is provided for such a use.
1238pub trait Captures<'a> {}
1239impl<'a, T> Captures<'a> for T {}
1240
Devin Jeanpierref643afa2022-02-23 20:50:48 +00001241#[cfg(test)]
1242mod test {
1243 use super::*;
1244 use std::cell::RefCell;
Devin Jeanpierred9a190f2023-11-28 00:56:06 -08001245 use std::pin::Pin;
Devin Jeanpierref643afa2022-02-23 20:50:48 +00001246 use std::sync::Mutex;
1247
1248 #[test]
1249 fn test_default_rust_type() {
1250 emplace! {let x = u32::ctor_new(());}
1251 assert_eq!(*x, 0);
1252 }
1253
1254 #[test]
1255 fn test_copy_rust_type() {
1256 let x: u32 = 42;
1257 let mut y = Box::emplace(copy(&x));
1258 assert_eq!(x, 42);
1259 assert_eq!(*y, 42);
1260
1261 // Can also mutate:
1262 let x = 50;
1263 y.as_mut().assign(&x);
1264 assert_eq!(x, 50);
1265 assert_eq!(*y, 50);
1266
1267 // Can also mutate:
1268 let x = 100;
1269 y.as_mut().assign(copy(&x));
1270 assert_eq!(x, 100);
1271 assert_eq!(*y, 100);
1272 }
1273
1274 #[test]
1275 fn test_copy_smart_ptr() {
1276 let x = Box::new(42_u32);
1277 emplace! {
1278 let y = copy(x);
1279 }
1280 // x is no longer in scope, as it was moved into the Copy.
1281 assert_eq!(*y, 42);
1282 }
1283
Devin Jeanpierref643afa2022-02-23 20:50:48 +00001284 /// Tests that the assigned variables have the correct type.
1285 #[test]
1286 fn test_emplace_type() {
1287 let x: u32 = 42;
1288 emplace! {
1289 let foo = copy(&x);
1290 }
1291 let _foo: Pin<&mut u32> = foo; // type checks OK
1292 }
1293
1294 #[test]
1295 fn test_emplace() {
1296 let x: u32 = 42;
1297 emplace! {
1298 let foo = copy(&x);
1299 }
1300 assert_eq!(*foo, 42);
1301 }
1302
1303 #[test]
1304 fn test_emplace_mut() {
1305 let x: u32 = 42;
1306 emplace! {
1307 let mut foo = copy(&x);
1308 }
1309 assert_eq!(*foo, 42);
1310 *foo = 0;
1311 assert_eq!(*foo, 0);
1312 }
1313
1314 #[test]
1315 fn test_emplace_multi() {
1316 let x: u32 = 42;
1317 emplace! {
1318 let foo = copy(&x);
1319 let bar = copy(&*foo);
1320 }
1321 assert_eq!(*foo, 42);
1322 assert_eq!(*bar, 42);
1323 }
1324
1325 #[test]
1326 fn test_emplace_type_syntax() {
1327 let x: u32 = 42;
1328 emplace! {
1329 let mut foo: Pin<&mut u32> = copy(&x);
1330 let bar: Pin<&mut u32> = copy(&x);
1331 }
1332 assert_eq!(*foo, 42);
1333 *foo = 0;
1334 assert_eq!(*foo, 0);
1335 assert_eq!(*bar, 42);
1336 }
1337
1338 #[test]
1339 fn test_ctor_macro() {
1340 struct MyStruct {
1341 x: u32,
1342 y: u32,
1343 }
Devin Jeanpierrea330af62022-06-09 17:03:45 -07001344 unsafe impl RecursivelyPinned for MyStruct {
1345 type CtorInitializedFields = Self;
1346 }
Devin Jeanpierref643afa2022-02-23 20:50:48 +00001347 emplace! { let my_struct = ctor!(MyStruct {
1348 x: 4,
1349 y: copy(&2)
1350 });}
1351 assert_eq!(my_struct.x, 4);
1352 assert_eq!(my_struct.y, 2);
1353
1354 // test that trailing commas compile:
1355 #[rustfmt::skip]
1356 let _ = ctor!(MyStruct {
1357 x: 0,
1358 y: 0,
1359 });
1360 }
1361
1362 #[test]
Devin Jeanpierrea4394dc2022-05-09 06:10:06 -07001363 fn test_ctor_macro_unit_struct() {
1364 struct MyStruct;
Devin Jeanpierrea330af62022-06-09 17:03:45 -07001365 unsafe impl RecursivelyPinned for MyStruct {
1366 type CtorInitializedFields = Self;
1367 }
Devin Jeanpierrea4394dc2022-05-09 06:10:06 -07001368 emplace! { let _my_struct = ctor!(MyStruct);}
1369 emplace! { let _my_struct = ctor!(MyStruct {});}
1370 }
1371
1372 #[test]
Devin Jeanpierref643afa2022-02-23 20:50:48 +00001373 fn test_ctor_macro_named_tuple_struct() {
1374 struct MyStruct(u32, u32);
Devin Jeanpierrea330af62022-06-09 17:03:45 -07001375 unsafe impl RecursivelyPinned for MyStruct {
1376 type CtorInitializedFields = Self;
1377 }
Devin Jeanpierref643afa2022-02-23 20:50:48 +00001378 emplace! { let my_struct = ctor!(MyStruct {
1379 0: 4,
1380 1: copy(&2)
1381 });}
1382 assert_eq!(my_struct.0, 4);
1383 assert_eq!(my_struct.1, 2);
1384 }
1385
1386 #[test]
1387 fn test_ctor_macro_tuple_struct() {
1388 struct MyStruct(u32, u32);
Devin Jeanpierrea330af62022-06-09 17:03:45 -07001389 unsafe impl RecursivelyPinned for MyStruct {
1390 type CtorInitializedFields = Self;
1391 }
Devin Jeanpierref643afa2022-02-23 20:50:48 +00001392 emplace! { let my_struct = ctor!(MyStruct (4, copy(&2)));}
1393 assert_eq!(my_struct.0, 4);
1394 assert_eq!(my_struct.1, 2);
1395 }
1396
1397 #[test]
1398 fn test_ctor_macro_manuallydrop_struct() {
1399 struct MyStruct {
1400 x: ManuallyDrop<Vec<u32>>,
1401 y: u64,
1402 }
Devin Jeanpierrea330af62022-06-09 17:03:45 -07001403 unsafe impl RecursivelyPinned for MyStruct {
1404 type CtorInitializedFields = Self;
1405 }
Devin Jeanpierref643afa2022-02-23 20:50:48 +00001406 emplace! {let my_struct = ctor!(MyStruct {x: unsafe {ManuallyDropCtor::new(vec![42])}, y: 0 }); }
1407 assert_eq!(&*my_struct.x, &vec![42]);
1408 assert_eq!(my_struct.y, 0);
1409 }
1410
1411 #[test]
1412 fn test_ctor_macro_union() {
1413 union MyUnion {
1414 x: ManuallyDrop<Vec<u32>>,
1415 y: u64,
1416 }
Devin Jeanpierrea330af62022-06-09 17:03:45 -07001417 unsafe impl RecursivelyPinned for MyUnion {
1418 type CtorInitializedFields = Self;
1419 }
Devin Jeanpierref643afa2022-02-23 20:50:48 +00001420 emplace! {let mut my_union = ctor!(MyUnion {x: unsafe { ManuallyDropCtor::new(vec![42])} }); }
1421 assert_eq!(unsafe { &*my_union.x }, &vec![42]);
1422
1423 // And now write to the union.
1424
1425 // First, should drop myunion.x.
1426 unsafe { ManuallyDrop::drop(&mut Pin::into_inner_unchecked(my_union.as_mut()).x) }
1427 // Second, we can overwrite.
1428 my_union.as_mut().reconstruct(ctor!(MyUnion { y: 24 }));
1429 assert_eq!(unsafe { my_union.y }, 24);
1430 }
1431
1432 #[test]
1433 fn test_ctor_macro_nested_struct() {
1434 mod nested {
1435 pub struct MyStruct {
1436 pub x: u32,
1437 pub y: u32,
1438 }
Devin Jeanpierrea330af62022-06-09 17:03:45 -07001439 unsafe impl crate::RecursivelyPinned for MyStruct {
1440 type CtorInitializedFields = Self;
1441 }
Devin Jeanpierref643afa2022-02-23 20:50:48 +00001442 }
1443 emplace! { let my_struct = ctor!(nested::MyStruct {
1444 x: 4,
1445 y: copy(&2)
1446 });}
1447 assert_eq!(my_struct.x, 4);
1448 assert_eq!(my_struct.y, 2);
1449 }
1450
1451 #[test]
1452 fn test_ctor_macro_nested_tuple_struct() {
1453 mod nested {
1454 pub struct MyStruct(pub u32, pub u32);
Devin Jeanpierrea330af62022-06-09 17:03:45 -07001455 unsafe impl crate::RecursivelyPinned for MyStruct {
1456 type CtorInitializedFields = Self;
1457 }
Devin Jeanpierref643afa2022-02-23 20:50:48 +00001458 }
1459 emplace! { let my_struct = ctor!(nested::MyStruct (4, copy(&2)));}
1460 assert_eq!(my_struct.0, 4);
1461 assert_eq!(my_struct.1, 2);
1462 }
1463
1464 /// Test that the ctor macro safety check doesn't rely on the struct not
1465 /// implementing Drop.
1466 #[test]
1467 fn test_ctor_macro_drop_struct() {
1468 struct MyStruct {
1469 x: String,
1470 }
Devin Jeanpierrea330af62022-06-09 17:03:45 -07001471 unsafe impl RecursivelyPinned for MyStruct {
1472 type CtorInitializedFields = Self;
1473 }
Devin Jeanpierref643afa2022-02-23 20:50:48 +00001474 impl Drop for MyStruct {
1475 fn drop(&mut self) {}
1476 }
1477
1478 emplace! { let _my_struct = ctor!(MyStruct {
1479 x: "".to_string()
1480 });}
1481 }
1482
1483 /// Struct which sets a bool to true when dropped.
1484 ///
1485 /// We use Mutex so as to allow for mutating state in a way Rust believes is
1486 /// unwind-safe.
1487 struct DropNotify<'a>(&'a Mutex<bool>);
1488
1489 impl Drop for DropNotify<'_> {
1490 fn drop(&mut self) {
1491 *self.0.lock().unwrap() = true;
1492 }
1493 }
1494
1495 /// Ctor which constructs a DropNotify but panics before completing
1496 /// construction.
1497 ///
1498 /// This can be used to test both that a drop occurs (for e.g. previously
1499 /// constructed DropNotify objects), as well as that one does not:
1500 /// because it in fact does fully initialize the thing it is meant to
1501 /// construct, it is not UB to then call drop on it -- even though it would
1502 /// be UB for almost any other Ctor.
1503 #[must_use = must_use_ctor!()]
1504 struct PanicCtor<'a>(DropNotify<'a>);
1505
1506 impl<'a> Ctor for PanicCtor<'a> {
1507 type Output = DropNotify<'a>;
1508 unsafe fn ctor(self, dest: Pin<&mut MaybeUninit<Self::Output>>) {
1509 self.0.ctor(dest);
1510 panic!();
1511 }
1512 }
1513
1514 impl !Unpin for PanicCtor<'_> {}
1515
1516 /// Tests that drop() is called when the Ctor doesn't panic.
1517 #[test]
1518 fn test_emplace_drop() {
1519 let is_dropped = Mutex::new(false);
1520 {
1521 emplace! { let _my_drop_notify = DropNotify(&is_dropped); }
1522 }
1523 assert!(*is_dropped.lock().unwrap());
1524 }
1525
1526 /// Tests that when a panic occurs during emplace!{}, the uninitialized
1527 /// value is not dropped.
1528 #[test]
1529 fn test_emplace_no_drop_on_panic() {
1530 let is_dropped = Mutex::new(false);
1531 let panic_result = std::panic::catch_unwind(|| {
1532 emplace! { let _my_drop_notify = PanicCtor(DropNotify(&is_dropped)); }
1533 });
1534 assert!(panic_result.is_err());
1535 assert!(!*is_dropped.lock().unwrap());
1536 }
1537
1538 /// Tests that when a panic occurs during initialization of a struct with
1539 /// ctor!, the initialized fields are dropped, and the uninitialized
1540 /// fields are not.
1541 #[test]
1542 fn test_ctor_macro_drop() {
1543 struct MyStruct<'a> {
1544 x: DropNotify<'a>,
1545 y: DropNotify<'a>,
1546 }
Devin Jeanpierrea330af62022-06-09 17:03:45 -07001547 unsafe impl RecursivelyPinned for MyStruct<'_> {
1548 type CtorInitializedFields = Self;
1549 }
Devin Jeanpierref643afa2022-02-23 20:50:48 +00001550
1551 let x_dropped = Mutex::new(false);
1552 let y_dropped = Mutex::new(false);
1553 let panic_result = std::panic::catch_unwind(|| {
1554 emplace! { let _my_struct = ctor!(MyStruct {
1555 x: DropNotify(&x_dropped),
1556 y: PanicCtor(DropNotify(&y_dropped))
1557 });}
1558 });
1559 assert!(panic_result.is_err());
1560 assert!(*x_dropped.lock().unwrap());
1561 assert!(!*y_dropped.lock().unwrap());
1562 }
1563
Devin Jeanpierrea330af62022-06-09 17:03:45 -07001564 #[test]
1565 fn test_ctor_initialized_fields_struct() {
1566 pub struct CtorOnly {
1567 pub field: i32,
1568 _must_construct_using_ctor: [(); 0],
1569 }
1570
1571 pub struct CtorOnlyPubFields {
1572 pub field: i32,
1573 }
1574
1575 unsafe impl RecursivelyPinned for CtorOnly {
1576 type CtorInitializedFields = CtorOnlyPubFields;
1577 }
1578
1579 // Fails to compile: did not specify _must_construct_using_ctor, and cannot
1580 // (outside this crate) because it is private
1581 // let x = CtorOnly {field: 3};
1582
1583 emplace! {let x = ctor!(CtorOnly {field: 3});}
1584 assert_eq!(x.field, 3);
1585 }
1586
1587 #[test]
1588 fn ctor_initialized_fields_tuple_struct() {
1589 pub struct CtorOnly(pub i32, [(); 0]);
1590 pub struct CtorOnlyPubFields(i32);
1591
1592 unsafe impl RecursivelyPinned for CtorOnly {
1593 type CtorInitializedFields = CtorOnlyPubFields;
1594 }
1595
1596 // Fails to compile: did not specify field 1, and cannot (outside this crate)
1597 // because it is private
1598 // let x = CtorOnly(3);
1599
1600 emplace! {let x = ctor!(CtorOnly(3));}
1601 assert_eq!(x.0, 3);
1602 }
1603
Devin Jeanpierref643afa2022-02-23 20:50:48 +00001604 /// logs calls to the constructors, drop.
1605 struct DropCtorLogger<'a> {
1606 log: &'a RefCell<Vec<&'static str>>,
1607 }
1608
1609 impl Drop for DropCtorLogger<'_> {
1610 fn drop(&mut self) {
1611 self.log.borrow_mut().push("drop");
1612 }
1613 }
1614
1615 struct LoggingCtor<'a> {
1616 log: &'a RefCell<Vec<&'static str>>,
1617 ctor_message: &'static str,
1618 }
1619
1620 impl<'a> Ctor for LoggingCtor<'a> {
1621 type Output = DropCtorLogger<'a>;
1622 unsafe fn ctor(self, mut dest: Pin<&mut MaybeUninit<Self::Output>>) {
1623 self.log.borrow_mut().push(self.ctor_message);
1624 dest.as_mut_ptr().write(DropCtorLogger { log: self.log });
1625 }
1626 }
1627 impl !Unpin for LoggingCtor<'_> {}
1628
1629 impl<'a> CtorNew<&DropCtorLogger<'a>> for DropCtorLogger<'a> {
1630 type CtorType = LoggingCtor<'a>;
1631 fn ctor_new(src: &DropCtorLogger<'a>) -> Self::CtorType {
1632 LoggingCtor { log: &src.log, ctor_message: "copy ctor" }
1633 }
1634 }
1635
1636 impl<'a> CtorNew<RvalueReference<'_, DropCtorLogger<'a>>> for DropCtorLogger<'a> {
1637 type CtorType = LoggingCtor<'a>;
1638 fn ctor_new(src: RvalueReference<'_, DropCtorLogger<'a>>) -> Self::CtorType {
1639 LoggingCtor { log: &src.0.log, ctor_message: "move ctor" }
1640 }
1641 }
1642
1643 /// Tests the ctor/drop order for copy-constructible Unpin types: ctor comes
1644 /// before drop.
1645 #[test]
1646 fn test_copy_ctor_drop_order() {
1647 let log = RefCell::new(vec![]);
1648 let log = &log;
1649
1650 emplace! {
1651 let notify_tester = DropCtorLogger {log};
1652 let new_value = DropCtorLogger {log};
1653 }
1654 notify_tester.assign(&*new_value);
1655 assert_eq!(*log.borrow(), vec!["copy ctor", "drop"]);
1656 }
1657
1658 /// Tests the ctor/drop order for move-constructible Unpin types: ctor comes
1659 /// before drop.
1660 #[test]
1661 fn test_move_ctor_drop_order() {
1662 let log = RefCell::new(vec![]);
1663 let log = &log;
1664
1665 emplace! {
1666 let notify_tester = DropCtorLogger {log};
1667 let new_value = DropCtorLogger {log};
1668 }
Devin Jeanpierre8e54c2f2022-08-04 02:56:35 -07001669 notify_tester.assign(mov!(new_value));
Devin Jeanpierref643afa2022-02-23 20:50:48 +00001670 assert_eq!(*log.borrow(), vec!["move ctor", "drop"]);
1671 }
1672
Googler7059c3a2023-04-04 04:04:37 -07001673 fn takes_rvalue_reference<T>(_: RvalueReference<T>) {}
Devin Jeanpierre8e54c2f2022-08-04 02:56:35 -07001674 /// Non-obvious fact: you can mov() an owned reference type! Moving anything
1675 /// also performs a rust move, but the resulting rvalue reference is
1676 /// still valid for a temporary's lifetime.
1677 #[test]
1678 fn test_mov_box() {
1679 struct S;
1680 let x: Pin<Box<S>> = Box::pin(S);
Devin Jeanpierre8e54c2f2022-08-04 02:56:35 -07001681 takes_rvalue_reference(mov!(x));
1682 // let _x = x; // fails to compile: x is moved!
1683 }
1684
Devin Jeanpierref643afa2022-02-23 20:50:48 +00001685 #[test]
Googler7059c3a2023-04-04 04:04:37 -07001686 fn test_mov_mut_ref_to_unpin() {
1687 takes_rvalue_reference(mov!(&mut 1));
1688 }
1689
1690 #[test]
1691 fn test_mov_pinned_mut_ref() {
1692 let x = &mut 2;
1693 let pinned_mut_ref = Pin::new(x);
1694 takes_rvalue_reference(mov!(pinned_mut_ref));
1695 }
1696
1697 #[test]
Devin Jeanpierref643afa2022-02-23 20:50:48 +00001698 fn test_ctor_then() {
1699 emplace! {
1700 let x = 40.ctor_then(|mut y| { *y += 2 });
1701 }
1702 assert_eq!(*x, 42);
1703 }
1704
1705 /// Test that a slot can be created in a temporary.
1706 #[test]
1707 fn test_slot_temporary() {
1708 assert_eq!(*emplace!(Slot::new(42)).as_opt().unwrap(), 42);
1709 }
1710
1711 /// Test that a slot can be created in a local.
1712 #[test]
1713 fn test_slot_local() {
1714 emplace! {let slot = Slot::new(42); }
1715 assert_eq!(*slot.as_opt().unwrap(), 42);
1716 }
1717
1718 /// Shows the use of Slot to implement a "slotted return value", similar to
1719 /// moveit.
1720 #[test]
1721 fn test_slotted_return_value() {
1722 // TODO(jeanpierreda): delete this, use doctests when doctests work.
1723 fn foo(slot: Pin<&mut Slot<u32>>) -> Pin<&mut u32> {
1724 slot.replace(42)
1725 }
1726
1727 emplace! {let slot = Slot::uninit(); }
1728 let rv = foo(slot);
1729 assert_eq!(*rv, 42);
1730 }
1731
1732 /// Shows the use of Slot to implement output parameters.
1733 #[test]
1734 fn test_slotted_output_parameter() {
1735 // TODO(jeanpierreda): delete this, use doctests when doctests work.
1736 fn foo(slot: Pin<&mut Slot<u32>>) {
1737 slot.replace(42);
1738 }
1739
1740 emplace! {let mut slot = Slot::uninit(); }
1741 foo(slot.as_mut());
1742 assert_eq!(*slot.as_opt().unwrap(), 42);
1743 }
Devin Jeanpierre83cb2dc2022-07-15 01:50:28 -07001744
1745 #[test]
1746 fn test_ctor_trait_captures() {
1747 fn adder<'a, 'b>(
1748 x: &'a i32,
1749 y: &'b i32,
1750 ) -> impl Ctor<Output = i32> + Captures<'a> + Captures<'b> {
Googlerf8296f82023-03-03 13:55:23 -08001751 FnCtor::new(|mut dest: Pin<&mut core::mem::MaybeUninit<i32>>| {
Devin Jeanpierre83cb2dc2022-07-15 01:50:28 -07001752 dest.write(*x + *y);
1753 })
1754 }
1755
1756 emplace! {
1757 let sum = adder(&40, &2);
1758 }
1759 assert_eq!(*sum, 42);
1760 }
1761
1762 // The following test is broken due to https://github.com/rust-lang/rust/issues/66551
1763 // If that bug is fixed, this test should be uncommented, and `Captures`
1764 // deprecated and removed.
1765 //
1766 // ```
1767 // #[test]
1768 // fn test_ctor_native_captures() {
1769 // fn adder<'a, 'b>(
1770 // x: &'a i32,
1771 // y: &'b i32,
1772 // ) -> impl Ctor<Output = i32> + 'a + 'b {
1773 // FnCtor::new(|mut dest: Pin<&mut std::mem::MaybeUninit<i32>>| {
1774 // dest.write(*x + *y);
1775 // })
1776 // }
1777
1778 // emplace! {
1779 // let sum = adder(&40, &2);
1780 // }
1781 // assert_eq!(*sum, 42);
1782 // }
1783 // ```
Devin Jeanpierref643afa2022-02-23 20:50:48 +00001784}