temp_inst/
lib.rs

1//! This crate provides safe lifetime-erased representations for objects with lifetime parameters.
2//! Safety is achieved by making the lifetime-erased objects accessible only via short-lived
3//! references.
4//!
5//! The main use case is to convert multiple (shared or mutable) references into a single reference
6//! to a lifetime-erased object, which can then be passed to an API that only accepts a single
7//! reference.
8//!
9//! A lifetime-erased object can be obtained by creating one of [`TempInst`], [`TempInstMut`], or
10//! [`TempInstPin`], and dereferencing it. (In the case of [`TempInstMut`], the
11//! [`TempInstMut::call_with`] method should be used because [`TempInstMut::new`] is unsafe.)
12//!
13//! To find out which types currently have a corresponding temporary representation, see the
14//! implementations of the [`TempRepr`] trait. It is possible to add temporary representations for
15//! custom types, preferably via [`mapped::HasTempRepr`].
16//!
17//! # Examples
18//!
19//! ```
20//! # use crate::temp_inst::*;
21//! #
22//! // We want to implement this example trait for a specific type `Bar`, in order
23//! // to call `run_twice` below.
24//! pub trait Foo {
25//!     type Arg;
26//!
27//!     fn run(arg: &mut Self::Arg);
28//! }
29//!
30//! pub fn run_twice<F: Foo>(arg: &mut F::Arg) {
31//!     F::run(arg);
32//!     F::run(arg);
33//! }
34//!
35//! struct Bar;
36//!
37//! impl Foo for Bar {
38//!     // We actually want to use _two_ mutable references as the argument type.
39//!     // However, the associated type `Arg` does not have any lifetime parameter.
40//!     // If we can add a lifetime parameter `'a` to `Bar`, then
41//!     // `type Arg = (&'a mut i32, &'a mut i32)` will work. If we can't or don't
42//!     // want to do that, a pair of `TempRefMut` will do the trick.
43//!     type Arg = (TempRefMut<i32>, TempRefMut<i32>);
44//!
45//!     fn run(arg: &mut Self::Arg) {
46//!         // The mutable `TempRefMut` references can be dereferenced to obtain
47//!         // the mutable references that we passed to `call_with` below.
48//!         let (a_ref, b_ref) = arg;
49//!         **a_ref += **b_ref;
50//!         **b_ref += 1;
51//!     }
52//! }
53//!
54//! let mut a = 42;
55//! let mut b = 23;
56//!
57//! // Now we can convert the pair `(&mut a, &mut b)` to `&mut Foo::Arg`, and pass
58//! // that to `run_twice`.
59//! TempInstMut::call_with((&mut a, &mut b), run_twice::<Bar>);
60//!
61//! assert_eq!(a, 42 + 23 + 1 + 23);
62//! assert_eq!(b, 23 + 1 + 1);
63//! ```
64//!
65//! For shared or pinned mutable references, there is a slightly simpler API:
66//!
67//! ```
68//! # use crate::temp_inst::*;
69//! #
70//! pub trait Foo {
71//!     type Arg;
72//!
73//!     fn run(arg: &Self::Arg) -> i32;
74//! }
75//!
76//! fn run_twice_and_add<F: Foo>(arg: &F::Arg) -> i32 {
77//!     F::run(arg) + F::run(arg)
78//! }
79//!
80//! struct Bar;
81//!
82//! impl Foo for Bar {
83//!     type Arg = (TempRef<i32>, TempRef<i32>);
84//!
85//!     fn run(arg: &Self::Arg) -> i32 {
86//!         let (a_ref, b_ref) = arg;
87//!         **a_ref * **b_ref
88//!     }
89//! }
90//!
91//! let inst = TempInst::new((&42, &23));
92//! let sum_of_products = run_twice_and_add::<Bar>(&inst);
93//!
94//! assert_eq!(sum_of_products, 42 * 23 + 42 * 23);
95//! ```
96//!
97//! For another use case, see the `temp_stack` crate.
98
99#![no_std]
100
101use core::{
102    cmp::Ordering,
103    fmt::{self, Debug, Display},
104    hash::{Hash, Hasher},
105    marker::PhantomData,
106    ops::{Deref, DerefMut, Range, RangeFrom, RangeFull, RangeTo},
107    pin::{pin, Pin},
108    ptr::NonNull,
109    slice,
110    str::Chars,
111};
112
113#[cfg(feature = "alloc")]
114extern crate alloc;
115
116#[cfg(feature = "std")]
117extern crate std;
118
119#[cfg(feature = "derive")]
120pub use temp_inst_derive::{TempRepr, TempReprMut, TempReprMutChk};
121
122use mapped::*;
123
124/// A wrapper around an instance of `T` which implements [`TempRepr`], i.e. is a temporary
125/// representation of a type `T::Shared<'a>`.
126///
127/// [`TempInst`] itself has a lifetime parameter `'a` and borrows the object passed to
128/// [`TempInst::new`] for that lifetime; therefore it is logically equivalent to `T::Shared<'a>`.
129/// However, it can hand out references to the lifetime-less type `T` via its [`Deref`]
130/// implementation.
131///
132/// See the module documentation for usage examples.
133#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
134pub struct TempInst<'a, T: TempRepr + 'a>(T, PhantomData<T::Shared<'a>>);
135
136impl<'a, T: TempRepr> TempInst<'a, T> {
137    /// Creates a [`TempInst`] from an instance of `T::Shared`. Note that `T::Shared` is always the
138    /// non-mutable variant of `T`; e.g. even if `T` is [`TempRefMut<X>`], `T::Shared` is `&X`, not
139    /// `&mut X`.
140    ///
141    /// A shared reference to `T` can be obtained from the result via [`Deref`].
142    #[must_use]
143    pub fn new(obj: T::Shared<'a>) -> Self {
144        // SAFETY: `obj` is borrowed for `'a`, which outlives the returned instance.
145        unsafe { TempInst(T::new_temp(obj), PhantomData) }
146    }
147
148    /// Calls `f` with a shared reference to `T` which is constructed from `obj`, and returns the
149    /// value returned by `f`.
150    ///
151    /// This method exists for consistency (with respect to [`TempInstMut::call_with`]), but is
152    /// actually just a trivial application of [`Self::new`] and [`Deref::deref`].
153    pub fn call_with<R>(obj: T::Shared<'a>, f: impl FnOnce(&T) -> R) -> R {
154        let inst = Self::new(obj);
155        f(&inst)
156    }
157}
158
159impl<T: TempRepr> Deref for TempInst<'_, T> {
160    type Target = T;
161
162    fn deref(&self) -> &Self::Target {
163        &self.0
164    }
165}
166
167impl<'a, T: TempRepr<Shared<'a>: Default>> Default for TempInst<'a, T> {
168    fn default() -> Self {
169        TempInst::new(Default::default())
170    }
171}
172
173impl<T: TempRepr + Debug> Debug for TempInst<'_, T> {
174    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
175        self.0.fmt(f)
176    }
177}
178
179impl<T: TempRepr + Display> Display for TempInst<'_, T> {
180    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
181        self.0.fmt(f)
182    }
183}
184
185/// A wrapper around an instance of `T` which implements [`TempReprMut`], i.e. is a temporary
186/// representation of a type `T::Mutable<'a>`.
187///
188/// [`TempInstPin`] itself has a lifetime parameter `'a` and borrows the object passed to
189/// [`TempInstPin::new`] for that lifetime; therefore it is logically equivalent to
190/// `T::Mutable<'a>`. However, it can hand out references to the lifetime-less type `T` via
191/// [`TempInstPin::deref_pin`]. The references have type `Pin<&mut T>`; use the slightly less
192/// efficient [`TempInstMut`] wrapper if `&mut T` is required instead.
193#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
194pub struct TempInstPin<'a, T: TempReprMut + 'a>(T, PhantomData<T::Mutable<'a>>);
195
196impl<'a, T: TempReprMut> TempInstPin<'a, T> {
197    /// Creates a [`TempInstPin`] from an instance of `T::Mutable`.
198    ///
199    /// A pinned mutable reference to `T` can be obtained from the result via [`Self::deref_pin`].
200    /// As `deref_pin` expects `self` to be pinned, use the [`core::pin::pin!`] macro to pin the
201    /// result of [`Self::new`] on the stack.
202    ///
203    /// Note that only the [`TempInstPin`] reference will be pinned; this is completely independent
204    /// of whether `T::Mutable` is a pinned reference. E.g. `T` can be [`TempRefMut`] or
205    /// [`TempRefPin`], and then `T::get_mut_pinned` will return a mutable or pinned mutable
206    /// reference accordingly.
207    ///
208    /// # Remarks
209    ///
210    /// For many types, including [`TempRef`], `T::Mutable` is actually the same as `T::Shared`.
211    /// This can be useful when combining mutable and shared references in a tuple. E.g.
212    /// `T = (TempRefMut<U>, TempRef<V>)` represents `(&mut U, &V)`, and this is preserved by
213    /// [`TempInstPin::new`], whereas [`TempInst::new`] treats it as `(&U, &V)`.
214    #[must_use]
215    pub fn new(obj: T::Mutable<'a>) -> Self {
216        // SAFETY: `obj` is borrowed for `'a`, which outlives the returned instance.
217        unsafe { TempInstPin(T::new_temp_mut(obj), PhantomData) }
218    }
219
220    /// Dereferences a pinned mutable [`TempInstMut`] reference to obtain a pinned mutable reference
221    /// to `T`. From that reference, the original object can be obtained via
222    /// [`TempReprMut::get_mut_pinned`].
223    #[must_use]
224    pub fn deref_pin(self: Pin<&mut Self>) -> Pin<&mut T> {
225        unsafe { self.map_unchecked_mut(|inst| &mut inst.0) }
226    }
227
228    /// Calls `f` with a pinned mutable reference to `T` which is constructed from `obj`, and
229    /// returns the value returned by `f`.
230    ///
231    /// This method exists for consistency (with respect to [`TempInstMut::call_with`]), but is
232    /// actually just a trivial application of [`Self::new`] and [`Self::deref_pin`].
233    pub fn call_with<R>(obj: T::Mutable<'a>, f: impl FnOnce(Pin<&mut T>) -> R) -> R {
234        let inst = pin!(Self::new(obj));
235        f(inst.deref_pin())
236    }
237}
238
239impl<T: TempReprMut> Deref for TempInstPin<'_, T> {
240    type Target = T;
241
242    fn deref(&self) -> &Self::Target {
243        &self.0
244    }
245}
246
247impl<'a, T: TempReprMut<Mutable<'a>: Default>> Default for TempInstPin<'a, T> {
248    fn default() -> Self {
249        TempInstPin::new(Default::default())
250    }
251}
252
253impl<T: TempReprMut + Debug> Debug for TempInstPin<'_, T> {
254    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
255        self.0.fmt(f)
256    }
257}
258
259impl<T: TempReprMut + Display> Display for TempInstPin<'_, T> {
260    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
261        self.0.fmt(f)
262    }
263}
264
265/// A wrapper around an instance of `T` which implements [`TempReprMut`], i.e. is a temporary
266/// representation of a type `T::Mutable<'a>`.
267///
268/// [`TempInstMut`] itself has a lifetime parameter `'a` and borrows the object passed to
269/// [`TempInstMut::new`] for that lifetime; therefore it is logically equivalent to
270/// `T::Mutable<'a>`. However, it can hand out references to the lifetime-less type `T` via its
271/// [`DerefMut`] implementation.
272#[derive(Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
273pub struct TempInstMut<'a, T: TempReprMutChk + 'a>(T, T::SwapChkData, PhantomData<T::Mutable<'a>>);
274
275impl<'a, T: TempReprMutChk> TempInstMut<'a, T> {
276    /// Creates a [`TempInstMut`] from an instance of `T::Mutable`.
277    ///
278    /// A mutable reference to `T` can be obtained from the result via [`DerefMut`].
279    ///
280    /// As this method is unsafe, using one of the safe alternatives is strongly recommended:
281    /// * [`TempInstPin::new`] if a pinned mutable reference to `T` is sufficient.
282    /// * [`TempInstMut::call_with`] if the use of the mutable `T` reference can be confined to a
283    ///   closure.
284    ///
285    /// [`TempInstMut::new`] potentially has a slight overhead compared to [`TempInstPin::new`], in
286    /// terms of both time and space, though there is a good chance that the compiler will optimize
287    /// both away if it can analyze how the instance is used.
288    ///
289    /// # Safety
290    ///
291    /// The caller must ensure at least one of the following two conditions.
292    /// * The [`Drop`] implementation of [`TempInstMut`] is called whenever the returned instance
293    ///   goes out of scope.
294    ///   (In particular, the instance must not be passed to [`core::mem::forget`].)
295    /// * The state of the instance when it goes out of scope is the same as when it was created.
296    ///   (This condition can be violated by calling [`core::mem::swap`] or a related function on
297    ///   the [`TempInstMut`] instance. When the instance goes out of scope after passing it to
298    ///   [`core::mem::swap`], the _other_ [`TempInstMut`] instance that it was swapped with can
299    ///   become dangling. Note that passing the result of [`Self::deref_mut`] to
300    ///   [`core::mem::swap`] is not unsafe, however.)
301    /// * `'a` is `'static`. (A [`TempInstMut`] instance with static lifetimes cannot become
302    ///   dangling.)
303    ///
304    /// # Panics
305    ///
306    /// The [`Drop`] implementation of the returned instance calls [`std::process::abort`] (after
307    /// calling the standard panic handler) if the instance has been modified, which is not possible
308    /// via its API but can be achieved by swapping it with another instance, e.g. using
309    /// [`core::mem::swap`].
310    ///
311    /// Unfortunately, a regular panic is insufficient in this case because it can be caught with
312    /// [`std::panic::catch_unwind`], and a dangling [`TempInstMut`] reference can then be obtained
313    /// from the closure passed to [`std::panic::catch_unwind`] (safely, because unfortunately
314    /// [`std::panic::UnwindSafe`] is not an `unsafe` trait -- why?!!).
315    ///
316    /// The panic behavior can be changed via [`set_modification_panic_fn`].
317    ///
318    /// # Remarks
319    ///
320    /// For many types, including [`TempRef`], `T::Mutable` is actually the same as `T::Shared`.
321    /// This can be useful when combining mutable and shared references in a tuple. E.g.
322    /// `T = (TempRefMut<U>, TempRef<V>)` represents `(&mut U, &V)`, and this is preserved by
323    /// [`TempInstMut::new`], whereas [`TempInst::new`] treats it as `(&U, &V)`.
324    #[must_use]
325    pub unsafe fn new(obj: T::Mutable<'a>) -> Self {
326        // SAFETY: `obj` is borrowed for `'a`, which outlives the returned instance.
327        let temp = T::new_temp_mut(obj);
328        let chk_data = temp.swap_chk_data();
329        TempInstMut(temp, chk_data, PhantomData)
330    }
331
332    /// Calls `f` with a mutable reference to `T` constructed from `obj`, and returns the value
333    /// returned by `f`.
334    ///
335    /// This method is a simple (but safe) wrapper around [`Self::new`], which potentially has a
336    /// slight overhead. If possible, use [`TempInstPin::new`] (or [`TempInstPin::call_with`])
337    /// instead.
338    ///
339    /// # Panics
340    ///
341    /// Calls [`std::process::abort`] if `f` modifies the internal state of the object that was
342    /// passed to it. See [`Self::new`] for more information.
343    pub fn call_with<R>(obj: T::Mutable<'a>, f: impl FnOnce(&mut T) -> R) -> R {
344        // SAFETY: Trivial because the scope of `inst` ends at the end of this function.
345        let mut inst = unsafe { Self::new(obj) };
346        f(&mut inst)
347    }
348}
349
350impl<T: TempReprMutChk> Deref for TempInstMut<'_, T> {
351    type Target = T;
352
353    fn deref(&self) -> &Self::Target {
354        &self.0
355    }
356}
357
358impl<T: TempReprMutChk> DerefMut for TempInstMut<'_, T> {
359    fn deref_mut(&mut self) -> &mut Self::Target {
360        &mut self.0
361    }
362}
363
364impl<T: TempReprMutChk<Mutable<'static>: Default>> Default for TempInstMut<'static, T> {
365    fn default() -> Self {
366        // SAFETY: Creating a `TempInstMut` instance with a `'static` lifetime is explicitly
367        // declared as safe.
368        unsafe { TempInstMut::new(Default::default()) }
369    }
370}
371
372impl<T: TempReprMutChk + Debug> Debug for TempInstMut<'_, T> {
373    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
374        self.0.fmt(f)
375    }
376}
377
378impl<T: TempReprMutChk + Display> Display for TempInstMut<'_, T> {
379    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
380        self.0.fmt(f)
381    }
382}
383
384impl<T: TempReprMutChk> Drop for TempInstMut<'_, T> {
385    fn drop(&mut self) {
386        if self.0.swap_chk_data() != self.1 {
387            modification_panic();
388        }
389    }
390}
391
392#[cfg(feature = "std")]
393fn modification_panic_fn() {
394    // Note: Can be replaced with `std::panic::always_abort` once that is stabilized.
395    let orig_hook = std::panic::take_hook();
396    std::panic::set_hook(std::boxed::Box::new(move |panic_info| {
397        orig_hook(panic_info);
398        std::process::abort()
399    }));
400    panic!("TempInstMut instance was modified; this is not allowed because it violates safety guarantees");
401}
402
403#[cfg(not(feature = "std"))]
404fn modification_panic_fn() {
405    // In the nostd case, we don't have `std::process::abort()`, so entering an endless loop
406    // seems to be the best we can do.
407    loop {}
408}
409
410static mut MODIFICATION_PANIC_FN: fn() = modification_panic_fn;
411
412/// Sets an alternative function to be called by the [`Drop`] implementation of [`TempInstMut`]
413/// when it encounters an illegal modification.
414///
415/// # Safety
416///
417/// * Changing the panic function is only allowed when no other thread is able to interact with
418///   this crate.
419///
420/// * The panic function must not return unless [`std::thread::panicking`] returns `true`.
421///
422/// * If the panic function causes an unwinding panic, the caller of
423///   [`set_modification_panic_fn`] assumes the responsibility that no instance or reference of
424///   [`TempInstMut`] is used across (i.e. captured in) [`std::panic::catch_unwind`].
425pub unsafe fn set_modification_panic_fn(panic_fn: fn()) {
426    MODIFICATION_PANIC_FN = panic_fn;
427}
428
429fn modification_panic() {
430    // SAFETY: The safety conditions of `set_modification_panic_fn` guarantee that no other
431    // thread is concurrently modifying the static variable.
432    unsafe { MODIFICATION_PANIC_FN() }
433}
434
435/// A trait that specifies that a type is a "temporary representation" of another type, where that
436/// other type can depend on a lifetime (via GATs). The standard example is that a raw pointer can
437/// be regarded as a temporary representation of a reference. The trait implementation for tuples
438/// generalizes this to combinations of more than one pointer/reference, the trait implementation
439/// for [`Option`] extends it to optional references, etc.
440///
441/// Every type implementing [`TempRepr`] can be used in [`TempInst`], which provides a safe API
442/// around the temporary representation.
443///
444/// Rather than implementing this trait directly, it is recommended to do so by defining a mapping
445/// to and from built-in types, using the safe trait [`mapped::HasTempRepr`].
446///
447/// # Safety
448///
449/// * The implementation of the trait must ensure that `new_temp<'a>` followed by `get<'b>` cannot
450///   cause undefined behavior when `'a: 'b`. (This essentially restricts `Shared<'a>` to types that
451///   are covariant in `'a`.)
452///
453/// * The above must also hold if a (legal) cast was applied to the result of `new_temp`.
454pub unsafe trait TempRepr {
455    /// The type that `Self` is a temporary representation of. May contain shared references of
456    /// lifetime `'a`.
457    type Shared<'a>
458    where
459        Self: 'a;
460
461    /// Converts the given object to its temporary representation.
462    ///
463    /// # Safety
464    ///
465    /// The caller must ensure that the returned object does not outlive the lifetime argument of
466    /// `obj`, and that [`TempReprMut::get_mut`] or [`TempReprMut::get_mut_pinned`] is never called
467    /// on the result.
468    ///
469    /// (Exception: see the caveat in the safety rules of [`TempReprMutChk`].)
470    unsafe fn new_temp(obj: Self::Shared<'_>) -> Self;
471
472    /// Converts from a shared temporary reference back to the original type with a
473    /// suitably-restricted lifetime.
474    fn get(&self) -> Self::Shared<'_>;
475}
476
477/// An extension of [`TempRepr`] that adds support for mutable references.
478///
479/// If the represented type has no special "mutable" variant, the [`AlwaysShared`] marker trait can
480/// be used to implement [`TempReprMut`] identically to [`TempRepr`].
481///
482/// # Safety
483///
484/// In addition to the requirements of [`TempRepr`], the implementation needs to ensure the
485/// following properties.
486///
487/// * `new_temp_mut<'a>` followed by `get_mut<'b>` or `get_mut_pinned<'b>` must not cause undefined
488///   behavior when `'a: 'b` and `'b` does not overlap with any other lifetime passed to `get` or
489///   `get_mut` or `get_mut_pinned`.
490///
491/// * `new_temp_mut<'a>` followed by `get<'b>` must not cause undefined behavior when `'a: 'b` and
492///   `'b` does not overlap with any lifetime passed to `get_mut` or `get_mut_pinned`.
493///
494/// * The pinning projections that are implemented as part of `get_mut_pinned` in this crate, e.g.
495///   for tuples, must be safe when the type is the target of such a projection. (This is usually
496///   trivial, and e.g. [`Option::as_pin_mut`] already exists in the standard library, but
497///   technically it is not automatically the case for tuples at the moment.)
498///
499/// * The above must also hold if a (legal) cast was applied to the result of `new_temp_mut`.
500pub unsafe trait TempReprMut: TempRepr {
501    /// The type that `Self` is a temporary representation of. May contain mutable references of
502    /// lifetime `'a`.
503    type Mutable<'a>
504    where
505        Self: 'a;
506
507    /// Converts the given object to a temporary representation without a lifetime parameter.
508    ///
509    /// # Safety
510    ///
511    /// The caller must ensure that the returned object does not outlive the lifetime argument of
512    /// `obj`.
513    ///
514    /// (Exception: see the caveat in the safety rules of [`TempReprMutChk`].)
515    unsafe fn new_temp_mut(obj: Self::Mutable<'_>) -> Self;
516
517    /// Converts from a mutable reference to the temporary representation back to the original type,
518    /// with a restricted lifetime.
519    fn get_mut(&mut self) -> Self::Mutable<'_>;
520
521    /// Like [`TempReprMut::get_mut`], but takes a pinned mutable reference to `Self`.
522    fn get_mut_pinned(self: Pin<&mut Self>) -> Self::Mutable<'_>;
523}
524
525/// An extension of [`TempReprMut`] that allows non-pinned mutable references to be passed to safe
526/// client code.
527///
528/// # Safety
529///
530/// [`TempReprMutChk::swap_chk_data`] must be implemented in such a way that a call to
531/// [`core::mem::swap`] is either detectable by calling `swap_chk_data` before and after and
532/// comparing the result via the [`PartialEq`] implementation, or is harmless, in the following
533/// sense:
534///
535/// Whenever a swapping operation is not detected by comparing the result of `swap_chk_data`,
536/// the swapped instances must be interchangeable in terms of all safety conditions of [`TempRepr`]
537/// and [`TempReprMut`].
538/// In particular, in all specific points, undefined behavior must also be avoided when the
539/// condition "`'a: 'b`" is weakened to "`'c: 'b` for some `'c` where the result of
540/// `swap_chk_data` was equal.
541pub unsafe trait TempReprMutChk: TempReprMut {
542    type SwapChkData: PartialEq;
543
544    /// Obtains an object (usually a copy of the internal state of `self`) that can be used to check
545    /// whether `self` was swapped with another instance of `Self` in such a way that the safety
546    /// rules of [`TempReprMutChk`] are violated.
547    fn swap_chk_data(&self) -> Self::SwapChkData;
548}
549
550/// A marker trait that causes [`TempReprMut`] to be implemented identically to [`TempRepr`].
551pub trait AlwaysShared: TempRepr {}
552
553// SAFETY: The additional conditions of `TempReprMut` are trivially satisfied if the references
554// returned by `get_mut`/`get_mut_pinned` are actually shared references.
555unsafe impl<T: AlwaysShared> TempReprMut for T {
556    type Mutable<'a> = Self::Shared<'a> where Self: 'a;
557
558    unsafe fn new_temp_mut(obj: Self::Mutable<'_>) -> Self {
559        Self::new_temp(obj)
560    }
561
562    fn get_mut(&mut self) -> Self::Mutable<'_> {
563        self.get()
564    }
565
566    fn get_mut_pinned(self: Pin<&mut Self>) -> Self::Mutable<'_> {
567        self.into_ref().get_ref().get()
568    }
569}
570
571/*******************
572 * SelfRepr<T> [T] *
573 *******************/
574
575/// A wrapper type that trivially implements [`TempRepr`]/[`TempReprMut`] for any `T: Clone` in such
576/// a way that no lifetimes are erased.
577#[derive(Clone, Copy, Default, PartialEq, Eq, PartialOrd, Ord, Hash, Debug)]
578pub struct SelfRepr<T: Clone>(T);
579
580// SAFETY: All conditions are trivially satisfied because the `get` implementation isn't
581// actually unsafe.
582unsafe impl<T: Clone> TempRepr for SelfRepr<T> {
583    type Shared<'a> = T where Self: 'a;
584
585    unsafe fn new_temp(obj: T) -> Self {
586        SelfRepr(obj)
587    }
588
589    fn get(&self) -> T {
590        self.0.clone()
591    }
592}
593
594impl<T: Clone> AlwaysShared for SelfRepr<T> {}
595
596// SAFETY: Trivially satisfied because the `get` implementation isn't actually unsafe.
597unsafe impl<T: Clone> TempReprMutChk for SelfRepr<T> {
598    type SwapChkData = ();
599
600    fn swap_chk_data(&self) -> Self::SwapChkData {}
601}
602
603/*******************
604 * TempRef<T> [&T] *
605 *******************/
606
607/// The canonical implementation of [`TempRepr`], representing a single shared reference.
608///
609/// This is not necessarily very useful on its own, but forms the basis of composition via tuples.
610pub struct TempRef<T: ?Sized>(NonNull<T>);
611
612// SAFETY: The safety rules of `TempRepr` are canonically satisfied by conversions between
613// shared references and pointers.
614unsafe impl<T: ?Sized> TempRepr for TempRef<T> {
615    type Shared<'a> = &'a T where Self: 'a;
616
617    unsafe fn new_temp(obj: Self::Shared<'_>) -> Self {
618        TempRef(obj.into())
619    }
620
621    fn get(&self) -> Self::Shared<'_> {
622        // SAFETY: The safety rules of `new_temp` and `new_temp_mut` ensure that this call is valid.
623        unsafe { self.0.as_ref() }
624    }
625}
626
627impl<T: ?Sized> AlwaysShared for TempRef<T> {}
628
629// SAFETY: Equal pointers to the same type must point to the same object, unless the object is
630// zero-size.
631unsafe impl<T: ?Sized> TempReprMutChk for TempRef<T> {
632    type SwapChkData = NonNull<T>;
633
634    fn swap_chk_data(&self) -> Self::SwapChkData {
635        self.0
636    }
637}
638
639impl<T: ?Sized> Deref for TempRef<T> {
640    type Target = T;
641
642    fn deref(&self) -> &Self::Target {
643        self.get()
644    }
645}
646
647impl<T: ?Sized + PartialEq> PartialEq for TempRef<T> {
648    fn eq(&self, other: &Self) -> bool {
649        self.get() == other.get()
650    }
651}
652
653impl<T: ?Sized + Eq> Eq for TempRef<T> {}
654
655impl<T: ?Sized + PartialOrd> PartialOrd for TempRef<T> {
656    fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
657        self.get().partial_cmp(other.get())
658    }
659
660    fn lt(&self, other: &Self) -> bool {
661        self.get() < other.get()
662    }
663
664    fn le(&self, other: &Self) -> bool {
665        self.get() <= other.get()
666    }
667
668    fn gt(&self, other: &Self) -> bool {
669        self.get() > other.get()
670    }
671
672    fn ge(&self, other: &Self) -> bool {
673        self.get() >= other.get()
674    }
675}
676
677impl<T: ?Sized + Ord> Ord for TempRef<T> {
678    fn cmp(&self, other: &Self) -> Ordering {
679        self.get().cmp(other.get())
680    }
681}
682
683impl<T: ?Sized + Hash> Hash for TempRef<T> {
684    fn hash<H: Hasher>(&self, state: &mut H) {
685        self.get().hash(state);
686    }
687}
688
689impl<T: ?Sized + Debug> Debug for TempRef<T> {
690    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
691        self.get().fmt(f)
692    }
693}
694
695impl<T: ?Sized + Display> Display for TempRef<T> {
696    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
697        self.get().fmt(f)
698    }
699}
700
701// SAFETY: `TempRef<T>` follows the same rules as `&T` regarding thread safety.
702unsafe impl<T: ?Sized + Sync> Send for TempRef<T> {}
703unsafe impl<T: ?Sized + Sync> Sync for TempRef<T> {}
704
705/**************************
706 * TempRefMut<T> [&mut T] *
707 **************************/
708
709/// The canonical implementation of [`TempReprMut`], representing a single mutable reference.
710///
711/// This is not necessarily very useful on its own, but forms the basis of composition via tuples.
712#[derive(PartialEq, Eq, PartialOrd, Ord, Hash)]
713pub struct TempRefMut<T: ?Sized>(TempRef<T>, PhantomData<*mut T>);
714
715// SAFETY: The safety rules of `TempRepr` are canonically satisfied by conversions between
716// shared references and pointers.
717unsafe impl<T: ?Sized> TempRepr for TempRefMut<T> {
718    type Shared<'a> = &'a T where Self: 'a;
719
720    unsafe fn new_temp(obj: Self::Shared<'_>) -> Self {
721        TempRefMut(TempRef::new_temp(obj), PhantomData)
722    }
723
724    fn get(&self) -> Self::Shared<'_> {
725        self.0.get()
726    }
727}
728
729// SAFETY: The safety rules of `TempReprMut` are canonically satisfied by conversions between
730// mutable references and pointers.
731//
732// The `PhantomData` field guarantees that a `TempRefMut` instance cannot be cast in a covariant
733// way, which `NonNull` would allow but violates the safety rules of `TempReprMut`.
734unsafe impl<T: ?Sized> TempReprMut for TempRefMut<T> {
735    type Mutable<'a> = &'a mut T where Self: 'a;
736
737    unsafe fn new_temp_mut(obj: Self::Mutable<'_>) -> Self {
738        TempRefMut(TempRef(obj.into()), PhantomData)
739    }
740
741    fn get_mut(&mut self) -> Self::Mutable<'_> {
742        // SAFETY: The safety rules of `new_temp` and `new_temp_mut` ensure that this call is valid.
743        unsafe { self.0 .0.as_mut() }
744    }
745
746    fn get_mut_pinned(mut self: Pin<&mut Self>) -> Self::Mutable<'_> {
747        // SAFETY: The safety rules of `new_temp` and `new_temp_mut` ensure that this call is valid.
748        unsafe { self.0 .0.as_mut() }
749    }
750}
751
752// SAFETY: Equal pointers to the same type must point to the same object, unless the object is
753// zero-size.
754unsafe impl<T: ?Sized> TempReprMutChk for TempRefMut<T> {
755    type SwapChkData = NonNull<T>;
756
757    fn swap_chk_data(&self) -> Self::SwapChkData {
758        self.0.swap_chk_data()
759    }
760}
761
762impl<T: ?Sized> Deref for TempRefMut<T> {
763    type Target = T;
764
765    fn deref(&self) -> &Self::Target {
766        self.get()
767    }
768}
769
770impl<T: ?Sized> DerefMut for TempRefMut<T> {
771    fn deref_mut(&mut self) -> &mut Self::Target {
772        self.get_mut()
773    }
774}
775
776impl<T: ?Sized + Debug> Debug for TempRefMut<T> {
777    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
778        self.get().fmt(f)
779    }
780}
781
782impl<T: ?Sized + Display> Display for TempRefMut<T> {
783    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
784        self.get().fmt(f)
785    }
786}
787
788// SAFETY: `TempRefMut<T>` follows the same rules as `&mut T` regarding thread safety.
789unsafe impl<T: ?Sized + Send> Send for TempRefMut<T> {}
790unsafe impl<T: ?Sized + Sync> Sync for TempRefMut<T> {}
791
792/*******************************
793 * TempRefPin<T> [Pin<&mut T>] *
794 *******************************/
795
796/// Similar to [`TempRefMut`], but represents a pinned mutable reference.
797#[derive(PartialEq, Eq, PartialOrd, Ord, Hash)]
798pub struct TempRefPin<T: ?Sized>(TempRefMut<T>);
799
800// SAFETY: The safety rules of `TempRepr` are canonically satisfied by conversions between
801// shared references and pointers.
802unsafe impl<T: ?Sized> TempRepr for TempRefPin<T> {
803    type Shared<'a> = &'a T where Self: 'a;
804
805    unsafe fn new_temp(obj: Self::Shared<'_>) -> Self {
806        TempRefPin(TempRefMut::new_temp(obj))
807    }
808
809    fn get(&self) -> Self::Shared<'_> {
810        self.0.get()
811    }
812}
813
814// SAFETY: The safety rules of `TempReprMut` are canonically satisfied by conversions between
815// mutable references and pointers, and `Pin<Ptr>` is covariant in `Ptr`.
816//
817// The `PhantomData` field in `TempRefMut` guarantees that a `TempRefPin` instance cannot be cast in
818// a covariant way, which `NonNull` would allow but violates the safety rules of `TempReprMut`.
819unsafe impl<T: ?Sized> TempReprMut for TempRefPin<T> {
820    type Mutable<'a> = Pin<&'a mut T> where Self: 'a;
821
822    unsafe fn new_temp_mut(obj: Self::Mutable<'_>) -> Self {
823        // SAFETY: Converting a pinned reference to a pointer is unproblematic as long as we only
824        // convert it back to a pinned or shared reference.
825        TempRefPin(TempRefMut::new_temp_mut(obj.get_unchecked_mut()))
826    }
827
828    fn get_mut(&mut self) -> Self::Mutable<'_> {
829        // SAFETY: The safety rules of `new_temp` and `new_temp_mut` ensure that this call is valid.
830        unsafe { Pin::new_unchecked(self.0.get_mut()) }
831    }
832
833    fn get_mut_pinned(self: Pin<&mut Self>) -> Self::Mutable<'_> {
834        // SAFETY: The safety rules of `new_temp` and `new_temp_mut` ensure that this call is valid.
835        unsafe { Pin::new_unchecked(self.map_unchecked_mut(|temp| &mut temp.0).get_mut_pinned()) }
836    }
837}
838
839// SAFETY: Equal pointers to the same type must point to the same object, unless the object is
840// zero-size.
841unsafe impl<T: ?Sized> TempReprMutChk for TempRefPin<T> {
842    type SwapChkData = NonNull<T>;
843
844    fn swap_chk_data(&self) -> Self::SwapChkData {
845        self.0.swap_chk_data()
846    }
847}
848
849impl<T: ?Sized> Deref for TempRefPin<T> {
850    type Target = T;
851
852    fn deref(&self) -> &Self::Target {
853        self.get()
854    }
855}
856
857impl<T: ?Sized + Debug> Debug for TempRefPin<T> {
858    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
859        self.get().fmt(f)
860    }
861}
862
863impl<T: ?Sized + Display> Display for TempRefPin<T> {
864    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
865        self.get().fmt(f)
866    }
867}
868
869/***********************
870 * TempCow<T> [Cow<T>] *
871 ***********************/
872
873/// A temporary representation of [`alloc::borrow::Cow`].
874#[cfg(feature = "alloc")]
875pub enum TempCow<T: ?Sized + alloc::borrow::ToOwned> {
876    Borrowed(TempRef<T>),
877    Owned(T::Owned),
878}
879
880#[cfg(feature = "alloc")]
881unsafe impl<T: ?Sized + alloc::borrow::ToOwned<Owned: Clone>> TempRepr for TempCow<T> {
882    type Shared<'a> = alloc::borrow::Cow<'a, T> where Self: 'a;
883
884    unsafe fn new_temp(obj: Self::Shared<'_>) -> Self {
885        match obj {
886            alloc::borrow::Cow::Borrowed(obj) => TempCow::Borrowed(TempRef::new_temp(obj)),
887            alloc::borrow::Cow::Owned(obj) => TempCow::Owned(obj),
888        }
889    }
890
891    fn get(&self) -> Self::Shared<'_> {
892        match self {
893            TempCow::Borrowed(temp) => alloc::borrow::Cow::Borrowed(temp.get()),
894            TempCow::Owned(temp) => alloc::borrow::Cow::Owned(temp.clone()),
895        }
896    }
897}
898
899#[cfg(feature = "alloc")]
900impl<T: ?Sized + alloc::borrow::ToOwned<Owned: Clone>> AlwaysShared for TempCow<T> {}
901
902// SAFETY: Note that we only care about the case where both instances are borrowed. In particular,
903// `eq` never returns `true` when one instance is borrowed and the other is owned.
904#[cfg(feature = "alloc")]
905unsafe impl<T: ?Sized + alloc::borrow::ToOwned<Owned: Clone>> TempReprMutChk for TempCow<T> {
906    type SwapChkData = Option<NonNull<T>>;
907
908    fn swap_chk_data(&self) -> Self::SwapChkData {
909        match self {
910            TempCow::Borrowed(temp) => Some(temp.swap_chk_data()),
911            TempCow::Owned(_) => None,
912        }
913    }
914}
915
916/*************
917 * Option<T> *
918 *************/
919
920unsafe impl<T: TempRepr> TempRepr for Option<T> {
921    type Shared<'a> = Option<T::Shared<'a>> where Self: 'a;
922
923    unsafe fn new_temp(obj: Self::Shared<'_>) -> Self {
924        Some(T::new_temp(obj?))
925    }
926
927    fn get(&self) -> Self::Shared<'_> {
928        Some(self.as_ref()?.get())
929    }
930}
931
932unsafe impl<T: TempReprMut> TempReprMut for Option<T> {
933    type Mutable<'a> = Option<T::Mutable<'a>> where Self: 'a;
934
935    unsafe fn new_temp_mut(obj: Self::Mutable<'_>) -> Self {
936        Some(T::new_temp_mut(obj?))
937    }
938
939    fn get_mut(&mut self) -> Self::Mutable<'_> {
940        Some(self.as_mut()?.get_mut())
941    }
942
943    fn get_mut_pinned(self: Pin<&mut Self>) -> Self::Mutable<'_> {
944        Some(self.as_pin_mut()?.get_mut_pinned())
945    }
946}
947
948unsafe impl<T: TempReprMutChk> TempReprMutChk for Option<T> {
949    type SwapChkData = Option<T::SwapChkData>;
950
951    fn swap_chk_data(&self) -> Self::SwapChkData {
952        self.as_ref().map(T::swap_chk_data)
953    }
954}
955
956/*****************
957 * (T0, T1, ...) *
958 *****************/
959
960macro_rules! impl_temp_repr_tuple {
961    ($($idx:tt $T:ident),*) => {
962        #[allow(clippy::unused_unit)]
963        unsafe impl<$($T: TempRepr),*> TempRepr for ($($T,)*) {
964            type Shared<'a> = ($($T::Shared<'a>,)*) where Self: 'a;
965
966            #[allow(unused_variables)]
967            unsafe fn new_temp(obj: Self::Shared<'_>) -> Self {
968                ($($T::new_temp(obj.$idx),)*)
969            }
970
971            fn get(&self) -> Self::Shared<'_> {
972                ($(self.$idx.get(),)*)
973            }
974        }
975
976        #[allow(clippy::unused_unit)]
977        unsafe impl<$($T: TempReprMut),*> TempReprMut for ($($T,)*) {
978            type Mutable<'a> = ($($T::Mutable<'a>,)*) where Self: 'a;
979
980            #[allow(unused_variables)]
981            unsafe fn new_temp_mut(obj: Self::Mutable<'_>) -> Self {
982                ($($T::new_temp_mut(obj.$idx),)*)
983            }
984
985            fn get_mut(&mut self) -> Self::Mutable<'_> {
986                ($(self.$idx.get_mut(),)*)
987            }
988
989            #[allow(unused_variables)]
990            fn get_mut_pinned(self: Pin<&mut Self>) -> Self::Mutable<'_> {
991                unsafe {
992                    let temp = self.get_unchecked_mut();
993                    ($(Pin::new_unchecked(&mut temp.$idx).get_mut_pinned(),)*)
994                }
995            }
996        }
997
998        #[allow(clippy::unused_unit)]
999        unsafe impl<$($T: TempReprMutChk),*> TempReprMutChk for ($($T,)*) {
1000            type SwapChkData = ($($T::SwapChkData,)*);
1001
1002            fn swap_chk_data(&self) -> Self::SwapChkData {
1003                ($(self.$idx.swap_chk_data(),)*)
1004            }
1005        }
1006    };
1007}
1008
1009impl_temp_repr_tuple!();
1010impl_temp_repr_tuple!(0 T0);
1011impl_temp_repr_tuple!(0 T0, 1 T1);
1012impl_temp_repr_tuple!(0 T0, 1 T1, 2 T2);
1013impl_temp_repr_tuple!(0 T0, 1 T1, 2 T2, 3 T3);
1014impl_temp_repr_tuple!(0 T0, 1 T1, 2 T2, 3 T3, 4 T4);
1015impl_temp_repr_tuple!(0 T0, 1 T1, 2 T2, 3 T3, 4 T4, 5 T5);
1016impl_temp_repr_tuple!(0 T0, 1 T1, 2 T2, 3 T3, 4 T4, 5 T5, 6 T6);
1017impl_temp_repr_tuple!(0 T0, 1 T1, 2 T2, 3 T3, 4 T4, 5 T5, 6 T6, 7 T7);
1018impl_temp_repr_tuple!(0 T0, 1 T1, 2 T2, 3 T3, 4 T4, 5 T5, 6 T6, 7 T7, 8 T8);
1019impl_temp_repr_tuple!(0 T0, 1 T1, 2 T2, 3 T3, 4 T4, 5 T5, 6 T6, 7 T7, 8 T8, 9 T9);
1020impl_temp_repr_tuple!(0 T0, 1 T1, 2 T2, 3 T3, 4 T4, 5 T5, 6 T6, 7 T7, 8 T8, 9 T9, 10 T10);
1021impl_temp_repr_tuple!(0 T0, 1 T1, 2 T2, 3 T3, 4 T4, 5 T5, 6 T6, 7 T7, 8 T8, 9 T9, 10 T10, 11 T11);
1022
1023/******************
1024 * Either<T0, T1> *
1025 ******************/
1026
1027#[cfg(feature = "either")]
1028unsafe impl<T0: TempRepr, T1: TempRepr> TempRepr for either::Either<T0, T1> {
1029    type Shared<'a> = either::Either<T0::Shared<'a>, T1::Shared<'a>> where Self: 'a;
1030
1031    unsafe fn new_temp(obj: Self::Shared<'_>) -> Self {
1032        match obj {
1033            either::Either::Left(obj0) => either::Either::Left(T0::new_temp(obj0)),
1034            either::Either::Right(obj1) => either::Either::Right(T1::new_temp(obj1)),
1035        }
1036    }
1037
1038    fn get(&self) -> Self::Shared<'_> {
1039        match self {
1040            either::Either::Left(self0) => either::Either::Left(self0.get()),
1041            either::Either::Right(self1) => either::Either::Right(self1.get()),
1042        }
1043    }
1044}
1045
1046#[cfg(feature = "either")]
1047unsafe impl<T0: TempReprMut, T1: TempReprMut> TempReprMut for either::Either<T0, T1> {
1048    type Mutable<'a> = either::Either<T0::Mutable<'a>, T1::Mutable<'a>> where Self: 'a;
1049
1050    unsafe fn new_temp_mut(obj: Self::Mutable<'_>) -> Self {
1051        match obj {
1052            either::Either::Left(obj0) => either::Either::Left(T0::new_temp_mut(obj0)),
1053            either::Either::Right(obj1) => either::Either::Right(T1::new_temp_mut(obj1)),
1054        }
1055    }
1056
1057    fn get_mut(&mut self) -> Self::Mutable<'_> {
1058        match self {
1059            either::Either::Left(self0) => either::Either::Left(self0.get_mut()),
1060            either::Either::Right(self1) => either::Either::Right(self1.get_mut()),
1061        }
1062    }
1063
1064    fn get_mut_pinned(self: Pin<&mut Self>) -> Self::Mutable<'_> {
1065        match self.as_pin_mut() {
1066            either::Either::Left(self0) => either::Either::Left(self0.get_mut_pinned()),
1067            either::Either::Right(self1) => either::Either::Right(self1.get_mut_pinned()),
1068        }
1069    }
1070}
1071
1072#[cfg(feature = "either")]
1073unsafe impl<T0: TempReprMutChk, T1: TempReprMutChk> TempReprMutChk for either::Either<T0, T1> {
1074    type SwapChkData = either::Either<T0::SwapChkData, T1::SwapChkData>;
1075
1076    fn swap_chk_data(&self) -> Self::SwapChkData {
1077        match self {
1078            either::Either::Left(self0) => either::Either::Left(self0.swap_chk_data()),
1079            either::Either::Right(self1) => either::Either::Right(self1.swap_chk_data()),
1080        }
1081    }
1082}
1083
1084/************
1085 * Range<T> *
1086 ************/
1087
1088unsafe impl<T: TempRepr> TempRepr for Range<T> {
1089    type Shared<'a> = Range<T::Shared<'a>> where Self: 'a;
1090
1091    unsafe fn new_temp(obj: Self::Shared<'_>) -> Self {
1092        T::new_temp(obj.start)..T::new_temp(obj.end)
1093    }
1094
1095    fn get(&self) -> Self::Shared<'_> {
1096        self.start.get()..self.end.get()
1097    }
1098}
1099
1100unsafe impl<T: TempReprMut> TempReprMut for Range<T> {
1101    type Mutable<'a> = Range<T::Mutable<'a>> where Self: 'a;
1102
1103    unsafe fn new_temp_mut(obj: Self::Mutable<'_>) -> Self {
1104        T::new_temp_mut(obj.start)..T::new_temp_mut(obj.end)
1105    }
1106
1107    fn get_mut(&mut self) -> Self::Mutable<'_> {
1108        self.start.get_mut()..self.end.get_mut()
1109    }
1110
1111    fn get_mut_pinned(self: Pin<&mut Self>) -> Self::Mutable<'_> {
1112        unsafe {
1113            let temp = self.get_unchecked_mut();
1114            let start = Pin::new_unchecked(&mut temp.start);
1115            let end = Pin::new_unchecked(&mut temp.end);
1116            start.get_mut_pinned()..end.get_mut_pinned()
1117        }
1118    }
1119}
1120
1121unsafe impl<T: TempReprMutChk> TempReprMutChk for Range<T> {
1122    type SwapChkData = Range<T::SwapChkData>;
1123
1124    fn swap_chk_data(&self) -> Self::SwapChkData {
1125        self.start.swap_chk_data()..self.end.swap_chk_data()
1126    }
1127}
1128
1129/****************
1130 * RangeFrom<T> *
1131 ****************/
1132
1133unsafe impl<T: TempRepr> TempRepr for RangeFrom<T> {
1134    type Shared<'a> = RangeFrom<T::Shared<'a>> where Self: 'a;
1135
1136    unsafe fn new_temp(obj: Self::Shared<'_>) -> Self {
1137        T::new_temp(obj.start)..
1138    }
1139
1140    fn get(&self) -> Self::Shared<'_> {
1141        self.start.get()..
1142    }
1143}
1144
1145unsafe impl<T: TempReprMut> TempReprMut for RangeFrom<T> {
1146    type Mutable<'a> = RangeFrom<T::Mutable<'a>> where Self: 'a;
1147
1148    unsafe fn new_temp_mut(obj: Self::Mutable<'_>) -> Self {
1149        T::new_temp_mut(obj.start)..
1150    }
1151
1152    fn get_mut(&mut self) -> Self::Mutable<'_> {
1153        self.start.get_mut()..
1154    }
1155
1156    fn get_mut_pinned(self: Pin<&mut Self>) -> Self::Mutable<'_> {
1157        unsafe {
1158            self.map_unchecked_mut(|temp| &mut temp.start)
1159                .get_mut_pinned()..
1160        }
1161    }
1162}
1163
1164unsafe impl<T: TempReprMutChk> TempReprMutChk for RangeFrom<T> {
1165    type SwapChkData = RangeFrom<T::SwapChkData>;
1166
1167    fn swap_chk_data(&self) -> Self::SwapChkData {
1168        self.start.swap_chk_data()..
1169    }
1170}
1171
1172/**************
1173 * RangeTo<T> *
1174 **************/
1175
1176unsafe impl<T: TempRepr> TempRepr for RangeTo<T> {
1177    type Shared<'a> = RangeTo<T::Shared<'a>> where Self: 'a;
1178
1179    unsafe fn new_temp(obj: Self::Shared<'_>) -> Self {
1180        ..T::new_temp(obj.end)
1181    }
1182
1183    fn get(&self) -> Self::Shared<'_> {
1184        ..self.end.get()
1185    }
1186}
1187
1188unsafe impl<T: TempReprMut> TempReprMut for RangeTo<T> {
1189    type Mutable<'a> = RangeTo<T::Mutable<'a>> where Self: 'a;
1190
1191    unsafe fn new_temp_mut(obj: Self::Mutable<'_>) -> Self {
1192        ..T::new_temp_mut(obj.end)
1193    }
1194
1195    fn get_mut(&mut self) -> Self::Mutable<'_> {
1196        ..self.end.get_mut()
1197    }
1198
1199    fn get_mut_pinned(self: Pin<&mut Self>) -> Self::Mutable<'_> {
1200        unsafe {
1201            ..self
1202                .map_unchecked_mut(|temp| &mut temp.end)
1203                .get_mut_pinned()
1204        }
1205    }
1206}
1207
1208unsafe impl<T: TempReprMutChk> TempReprMutChk for RangeTo<T> {
1209    type SwapChkData = RangeTo<T::SwapChkData>;
1210
1211    fn swap_chk_data(&self) -> Self::SwapChkData {
1212        ..self.end.swap_chk_data()
1213    }
1214}
1215
1216/*************
1217 * RangeFull *
1218 *************/
1219
1220unsafe impl TempRepr for RangeFull {
1221    type Shared<'a> = RangeFull where Self: 'a;
1222
1223    unsafe fn new_temp(_obj: RangeFull) -> Self {
1224        ..
1225    }
1226
1227    fn get(&self) -> RangeFull {
1228        ..
1229    }
1230}
1231
1232impl AlwaysShared for RangeFull {}
1233
1234unsafe impl TempReprMutChk for RangeFull {
1235    type SwapChkData = RangeFull;
1236
1237    fn swap_chk_data(&self) -> Self::SwapChkData {
1238        ..
1239    }
1240}
1241
1242/****************
1243 * Mapped types *
1244 ****************/
1245
1246/// Contains a trait [`HasTempRepr`] to implement [`TempRepr`] and [`TempReprMut`] by mapping to
1247/// and from built-in types.
1248pub mod mapped {
1249    use super::*;
1250
1251    /// A safe helper trait for implementing the unsafe [`TempRepr`] and [`TempReprMut`] traits for
1252    /// a type, by mapping between the type and one with a temporary representation.
1253    ///
1254    /// The trait must be implemented on some arbitrary type `T`; by convention this should be the
1255    /// same as `Self::Mutable<'static>`. Then [`MappedTempRepr<T>`] can be used as the argument of
1256    /// [`TempInst`].
1257    pub trait HasTempRepr {
1258        type Temp: TempRepr;
1259
1260        type Shared<'a>
1261        where
1262            Self: 'a;
1263
1264        fn shared_to_mapped(obj: Self::Shared<'_>) -> <Self::Temp as TempRepr>::Shared<'_>;
1265
1266        fn mapped_to_shared(mapped: <Self::Temp as TempRepr>::Shared<'_>) -> Self::Shared<'_>;
1267    }
1268
1269    pub trait HasTempReprMut: HasTempRepr<Temp: TempReprMut> {
1270        type Mutable<'a>
1271        where
1272            Self: 'a;
1273
1274        fn mut_to_mapped(obj: Self::Mutable<'_>) -> <Self::Temp as TempReprMut>::Mutable<'_>;
1275
1276        fn mapped_to_mut(mapped: <Self::Temp as TempReprMut>::Mutable<'_>) -> Self::Mutable<'_>;
1277    }
1278
1279    pub trait IsAlwaysShared: HasTempRepr<Temp: AlwaysShared> {}
1280
1281    impl<T: IsAlwaysShared> HasTempReprMut for T {
1282        type Mutable<'a> = Self::Shared<'a> where Self: 'a;
1283
1284        fn mut_to_mapped(obj: Self::Mutable<'_>) -> <Self::Temp as TempReprMut>::Mutable<'_> {
1285            Self::shared_to_mapped(obj)
1286        }
1287
1288        fn mapped_to_mut(mapped: <Self::Temp as TempReprMut>::Mutable<'_>) -> Self::Mutable<'_> {
1289            Self::mapped_to_shared(mapped)
1290        }
1291    }
1292
1293    /// See [`HasTempRepr`].
1294    pub struct MappedTempRepr<T: HasTempRepr>(T::Temp);
1295
1296    unsafe impl<T: HasTempRepr> TempRepr for MappedTempRepr<T> {
1297        type Shared<'a> = T::Shared<'a> where Self: 'a;
1298
1299        unsafe fn new_temp(obj: Self::Shared<'_>) -> Self {
1300            MappedTempRepr(T::Temp::new_temp(T::shared_to_mapped(obj)))
1301        }
1302
1303        fn get(&self) -> Self::Shared<'_> {
1304            T::mapped_to_shared(self.0.get())
1305        }
1306    }
1307
1308    unsafe impl<T: HasTempReprMut> TempReprMut for MappedTempRepr<T> {
1309        type Mutable<'a> = T::Mutable<'a> where Self: 'a;
1310
1311        unsafe fn new_temp_mut(obj: Self::Mutable<'_>) -> Self {
1312            MappedTempRepr(T::Temp::new_temp_mut(T::mut_to_mapped(obj)))
1313        }
1314
1315        fn get_mut(&mut self) -> Self::Mutable<'_> {
1316            T::mapped_to_mut(self.0.get_mut())
1317        }
1318
1319        fn get_mut_pinned(self: Pin<&mut Self>) -> Self::Mutable<'_> {
1320            // SAFETY: Just a standard pin projection.
1321            let temp = unsafe { self.map_unchecked_mut(|temp| &mut temp.0) };
1322            T::mapped_to_mut(temp.get_mut_pinned())
1323        }
1324    }
1325
1326    unsafe impl<T: HasTempReprMut<Temp: TempReprMutChk>> TempReprMutChk for MappedTempRepr<T> {
1327        type SwapChkData = <T::Temp as TempReprMutChk>::SwapChkData;
1328
1329        fn swap_chk_data(&self) -> Self::SwapChkData {
1330            self.0.swap_chk_data()
1331        }
1332    }
1333
1334    impl<T: HasTempRepr> PartialEq for MappedTempRepr<T>
1335    where
1336        for<'a> T::Shared<'a>: PartialEq,
1337    {
1338        fn eq(&self, other: &Self) -> bool {
1339            self.get() == other.get()
1340        }
1341    }
1342
1343    impl<T: HasTempRepr> Eq for MappedTempRepr<T> where for<'a> T::Shared<'a>: Eq {}
1344
1345    impl<T: HasTempRepr> PartialOrd for MappedTempRepr<T>
1346    where
1347        for<'a> T::Shared<'a>: PartialOrd,
1348    {
1349        fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
1350            self.get().partial_cmp(&other.get())
1351        }
1352
1353        fn lt(&self, other: &Self) -> bool {
1354            self.get() < other.get()
1355        }
1356
1357        fn le(&self, other: &Self) -> bool {
1358            self.get() <= other.get()
1359        }
1360
1361        fn gt(&self, other: &Self) -> bool {
1362            self.get() > other.get()
1363        }
1364
1365        fn ge(&self, other: &Self) -> bool {
1366            self.get() >= other.get()
1367        }
1368    }
1369
1370    impl<T: HasTempRepr> Ord for MappedTempRepr<T>
1371    where
1372        for<'a> T::Shared<'a>: Ord,
1373    {
1374        fn cmp(&self, other: &Self) -> Ordering {
1375            self.get().cmp(&other.get())
1376        }
1377    }
1378
1379    impl<T: HasTempRepr> Hash for MappedTempRepr<T>
1380    where
1381        for<'a> T::Shared<'a>: Hash,
1382    {
1383        fn hash<H: Hasher>(&self, state: &mut H) {
1384            self.get().hash(state);
1385        }
1386    }
1387
1388    impl<T: HasTempRepr> Debug for MappedTempRepr<T>
1389    where
1390        for<'a> T::Shared<'a>: Debug,
1391    {
1392        fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1393            self.get().fmt(f)
1394        }
1395    }
1396
1397    impl<T: HasTempRepr> Display for MappedTempRepr<T>
1398    where
1399        for<'a> T::Shared<'a>: Display,
1400    {
1401        fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1402            self.get().fmt(f)
1403        }
1404    }
1405
1406    impl<T> HasTempRepr for slice::Iter<'static, T> {
1407        type Temp = TempRef<[T]>;
1408
1409        type Shared<'a> = slice::Iter<'a, T> where Self: 'a;
1410
1411        fn shared_to_mapped(obj: Self::Shared<'_>) -> <Self::Temp as TempRepr>::Shared<'_> {
1412            obj.as_slice()
1413        }
1414
1415        fn mapped_to_shared(mapped: <Self::Temp as TempRepr>::Shared<'_>) -> Self::Shared<'_> {
1416            mapped.iter()
1417        }
1418    }
1419
1420    impl<T> IsAlwaysShared for slice::Iter<'static, T> {}
1421
1422    impl<T> HasTempRepr for slice::IterMut<'static, T> {
1423        type Temp = TempRefMut<[T]>;
1424
1425        type Shared<'a> = slice::Iter<'a, T> where Self: 'a;
1426
1427        fn shared_to_mapped(obj: Self::Shared<'_>) -> <Self::Temp as TempRepr>::Shared<'_> {
1428            obj.as_slice()
1429        }
1430
1431        fn mapped_to_shared(mapped: <Self::Temp as TempRepr>::Shared<'_>) -> Self::Shared<'_> {
1432            mapped.iter()
1433        }
1434    }
1435
1436    impl<T> HasTempReprMut for slice::IterMut<'static, T> {
1437        type Mutable<'a> = slice::IterMut<'a, T> where Self: 'a;
1438
1439        fn mut_to_mapped(obj: Self::Mutable<'_>) -> <Self::Temp as TempReprMut>::Mutable<'_> {
1440            obj.into_slice()
1441        }
1442
1443        fn mapped_to_mut(mapped: <Self::Temp as TempReprMut>::Mutable<'_>) -> Self::Mutable<'_> {
1444            mapped.iter_mut()
1445        }
1446    }
1447
1448    impl HasTempRepr for Chars<'static> {
1449        type Temp = TempRef<str>;
1450
1451        type Shared<'a> = Chars<'a> where Self: 'a;
1452
1453        fn shared_to_mapped(obj: Self::Shared<'_>) -> <Self::Temp as TempRepr>::Shared<'_> {
1454            obj.as_str()
1455        }
1456
1457        fn mapped_to_shared(mapped: <Self::Temp as TempRepr>::Shared<'_>) -> Self::Shared<'_> {
1458            mapped.chars()
1459        }
1460    }
1461
1462    impl IsAlwaysShared for Chars<'static> {}
1463}
1464
1465pub type TempSliceIter<T> = MappedTempRepr<slice::Iter<'static, T>>;
1466pub type TempSliceIterMut<T> = MappedTempRepr<slice::IterMut<'static, T>>;
1467
1468pub type TempChars = MappedTempRepr<Chars<'static>>;
1469
1470#[cfg(test)]
1471mod tests {
1472    use core::mem::swap;
1473
1474    use super::*;
1475
1476    #[cfg(feature = "std")]
1477    fn init_tests() {
1478        // Set up a non-aborting panic handler so we can test the panicking code.
1479        // We need to make sure `set_modification_panic_fn` is called before any other test code,
1480        // to satisfy its safety requirement.
1481        static INIT: std::sync::LazyLock<()> = std::sync::LazyLock::new(|| unsafe {
1482            set_modification_panic_fn(|| {
1483                if !std::thread::panicking() {
1484                    panic!("TempInstMut instance was modified");
1485                }
1486            })
1487        });
1488        *INIT
1489    }
1490
1491    #[cfg(not(feature = "std"))]
1492    fn init_tests() {}
1493
1494    #[test]
1495    fn temp_ref() {
1496        init_tests();
1497        let mut a = 42;
1498        let a_inst = TempInst::<TempRef<i32>>::new(&a);
1499        let a_ref = a_inst.get();
1500        assert_eq!(*a_ref, 42);
1501        let double = 2 * *a_ref;
1502        assert_eq!(a, 42);
1503        a += 1; // Important: fails to compile if `a_inst` or `a_ref` are used afterwards.
1504        assert_eq!(a, 43);
1505        assert_eq!(double, 2 * 42);
1506    }
1507
1508    #[test]
1509    fn temp_ref_call() {
1510        init_tests();
1511        let a = 42;
1512        let double = TempInst::<TempRef<i32>>::call_with(&a, |a_inst| {
1513            let a_ref = a_inst.get();
1514            assert_eq!(*a_ref, 42);
1515            2 * *a_ref
1516        });
1517        assert_eq!(a, 42);
1518        assert_eq!(double, 2 * 42);
1519    }
1520
1521    #[test]
1522    fn temp_ref_call_pair() {
1523        init_tests();
1524        let a = 42;
1525        let b = 23;
1526        let sum = TempInst::<(TempRef<i32>, TempRef<i32>)>::call_with((&a, &b), |a_b_inst| {
1527            let (a_ref, b_ref) = a_b_inst.get();
1528            assert_eq!(*a_ref, 42);
1529            assert_eq!(*b_ref, 23);
1530            *a_ref + *b_ref
1531        });
1532        assert_eq!(a, 42);
1533        assert_eq!(b, 23);
1534        assert_eq!(sum, 42 + 23);
1535    }
1536
1537    #[test]
1538    fn temp_ref_call_mut() {
1539        init_tests();
1540        let mut a = 42;
1541        let double = TempInstMut::<TempRefMut<i32>>::call_with(&mut a, |a_inst| {
1542            let a_ref = a_inst.get_mut();
1543            assert_eq!(*a_ref, 42);
1544            *a_ref += 1;
1545            2 * *a_ref
1546        });
1547        assert_eq!(a, 43);
1548        assert_eq!(double, 2 * 43);
1549    }
1550
1551    #[test]
1552    fn temp_ref_call_pair_mut() {
1553        init_tests();
1554        let mut a = 42;
1555        let mut b = 23;
1556        let sum = TempInstMut::<(TempRefMut<i32>, TempRefMut<i32>)>::call_with(
1557            (&mut a, &mut b),
1558            |a_b_inst| {
1559                let (a_ref, b_ref) = a_b_inst.get_mut();
1560                assert_eq!(*a_ref, 42);
1561                assert_eq!(*b_ref, 23);
1562                *a_ref += 1;
1563                *b_ref -= 2;
1564                *a_ref + *b_ref
1565            },
1566        );
1567        assert_eq!(a, 43);
1568        assert_eq!(b, 21);
1569        assert_eq!(sum, 43 + 21);
1570    }
1571
1572    #[test]
1573    fn temp_ref_call_pair_half_mut() {
1574        init_tests();
1575        let mut a = 42;
1576        let b = 23;
1577        let sum =
1578            TempInstMut::<(TempRefMut<i32>, TempRef<i32>)>::call_with((&mut a, &b), |a_b_inst| {
1579                let (a_ref, b_ref) = a_b_inst.get_mut();
1580                assert_eq!(*a_ref, 42);
1581                assert_eq!(*b_ref, 23);
1582                *a_ref += 1;
1583                *a_ref + *b_ref
1584            });
1585        assert_eq!(a, 43);
1586        assert_eq!(b, 23);
1587        assert_eq!(sum, 43 + 23);
1588    }
1589
1590    #[test]
1591    fn temp_ref_mut_pin() {
1592        init_tests();
1593        let mut a = 42;
1594        let a_inst = pin!(TempInstPin::<TempRefMut<i32>>::new(&mut a));
1595        let a_ref = a_inst.deref_pin().get_mut_pinned();
1596        assert_eq!(*a_ref, 42);
1597        *a_ref += 1;
1598        let double = 2 * *a_ref;
1599        assert_eq!(a, 43);
1600        assert_eq!(double, 2 * 43);
1601    }
1602
1603    #[test]
1604    fn temp_ref_mut_call_pin() {
1605        init_tests();
1606        let mut a = 42;
1607        let double = TempInstPin::<TempRefMut<i32>>::call_with(&mut a, |a_inst| {
1608            let a_ref = a_inst.get_mut_pinned();
1609            assert_eq!(*a_ref, 42);
1610            *a_ref += 1;
1611            2 * *a_ref
1612        });
1613        assert_eq!(a, 43);
1614        assert_eq!(double, 2 * 43);
1615    }
1616
1617    #[test]
1618    fn temp_ref_pin_call_pin() {
1619        init_tests();
1620        let mut a = pin!(42);
1621        let double = TempInstPin::<TempRefPin<i32>>::call_with(Pin::as_mut(&mut a), |a_inst| {
1622            let a_ref = a_inst.get_mut_pinned().get_mut();
1623            assert_eq!(*a_ref, 42);
1624            *a_ref += 1;
1625            2 * *a_ref
1626        });
1627        assert_eq!(*a, 43);
1628        assert_eq!(double, 2 * 43);
1629    }
1630
1631    #[cfg(feature = "std")]
1632    #[test]
1633    #[should_panic(expected = "TempInstMut instance was modified")]
1634    fn temp_ref_call_mut_illegal_swap() {
1635        init_tests();
1636        let mut a = 42;
1637        TempInstMut::<TempRefMut<i32>>::call_with(&mut a, |a_inst| {
1638            let mut b = 43;
1639            TempInstMut::<TempRefMut<i32>>::call_with(&mut b, |b_inst| {
1640                swap(a_inst, b_inst);
1641            });
1642            // This would cause undefined behavior due to swapping, if undetected.
1643            let b_ref = a_inst.get_mut();
1644            assert_ne!(*b_ref, 43);
1645        });
1646    }
1647
1648    #[test]
1649    fn temp_ref_call_mut_swap_zero_size() {
1650        // The zero-size case is special because both halves of each pair have the same address in
1651        // memory, so the `swap` operation is undetectable. This is hopefully not a problem because
1652        // we can consider it as a no-op then. In particular, we can hopefully assume that both
1653        // lifetimes end at the same time, and that the references are completely interchangeable
1654        // until then.
1655        init_tests();
1656        let mut a = ((), ());
1657        TempInstMut::<TempRefMut<()>>::call_with(&mut a.0, |a0_inst| {
1658            TempInstMut::<TempRefMut<()>>::call_with(&mut a.1, |a1_inst| {
1659                swap(a0_inst, a1_inst);
1660            });
1661            // This produces multiple mutable references to a.1, which could potentially be
1662            // regarded as causing undefined behavior. Miri is OK with it, though.
1663            let a1_ref = &mut a.1;
1664            let a1_ref_2 = a0_inst.get_mut();
1665            *a1_ref = ();
1666            *a1_ref_2 = ();
1667        });
1668    }
1669
1670    #[cfg(feature = "std")]
1671    #[test]
1672    fn temp_ref_send() {
1673        init_tests();
1674        let a = 42;
1675        let a_inst = TempInst::<TempRef<i32>>::new(&a);
1676        std::thread::scope(|scope| {
1677            let thread = scope.spawn(move || **a_inst);
1678            let result = thread.join().unwrap();
1679            assert_eq!(result, 42);
1680        });
1681    }
1682
1683    #[cfg(feature = "std")]
1684    #[test]
1685    fn temp_ref_sync() {
1686        init_tests();
1687        let a = 42;
1688        let a_inst = TempInst::<TempRef<i32>>::new(&a);
1689        std::thread::scope(|scope| {
1690            let thread = scope.spawn(|| **a_inst);
1691            let result = thread.join().unwrap();
1692            assert_eq!(result, 42);
1693        });
1694    }
1695
1696    #[cfg(feature = "std")]
1697    #[test]
1698    fn temp_ref_pin_send() {
1699        init_tests();
1700        let a = pin!(42);
1701        let a_inst = TempInstPin::<TempRefPin<i32>>::new(a);
1702        std::thread::scope(|scope| {
1703            let thread = scope.spawn(move || **a_inst);
1704            let result = thread.join().unwrap();
1705            assert_eq!(result, 42);
1706        });
1707    }
1708
1709    #[cfg(feature = "std")]
1710    #[test]
1711    fn temp_ref_pin_sync() {
1712        init_tests();
1713        let a = pin!(42);
1714        let a_inst = TempInstPin::<TempRefPin<i32>>::new(a);
1715        std::thread::scope(|scope| {
1716            let thread = scope.spawn(|| **a_inst);
1717            let result = thread.join().unwrap();
1718            assert_eq!(result, 42);
1719        });
1720    }
1721
1722    #[cfg(feature = "std")]
1723    #[test]
1724    fn temp_ref_call_mut_send() {
1725        init_tests();
1726        let mut a = 42;
1727        TempInstMut::<TempRefMut<i32>>::call_with(&mut a, |a_inst| {
1728            std::thread::scope(|scope| {
1729                let thread = scope.spawn(move || **a_inst += 1);
1730                thread.join().unwrap();
1731            })
1732        });
1733        assert_eq!(a, 43);
1734    }
1735
1736    #[cfg(feature = "std")]
1737    #[test]
1738    fn temp_ref_call_mut_sync() {
1739        init_tests();
1740        let mut a = 42;
1741        TempInstMut::<TempRefMut<i32>>::call_with(&mut a, |a_inst| {
1742            std::thread::scope(|scope| {
1743                let thread = scope.spawn(|| **a_inst += 1);
1744                thread.join().unwrap();
1745            })
1746        });
1747        assert_eq!(a, 43);
1748    }
1749}