into_static/
lib.rs

1//! Upgrading to static lifetimes.
2//!
3//! This crate provides the [`IntoStatic`] trait, which allows upgrading all lifetimes to `'static`.
4
5#![forbid(unsafe_code)]
6#![deny(missing_docs)]
7#![cfg_attr(not(feature = "std"), no_std)]
8#![cfg_attr(docsrs, feature(doc_auto_cfg))]
9
10#[cfg(feature = "std")]
11use std::borrow::Cow;
12
13#[cfg(feature = "alloc")]
14extern crate alloc;
15
16#[cfg(all(not(feature = "std"), feature = "alloc"))]
17use alloc::{borrow::Cow, vec::Vec};
18
19/// Upgrading to `'static` lifetimes.
20pub trait IntoStatic {
21    /// The type with `'static` lifetimes.
22    type Static: IntoStatic<Static = Self::Static> + 'static;
23
24    /// Upgrades [`Self`] to [`Self::Static`].
25    fn into_static(self) -> Self::Static;
26}
27
28#[cfg(any(feature = "std", feature = "alloc"))]
29impl IntoStatic for Cow<'_, str> {
30    type Static = Cow<'static, str>;
31
32    fn into_static(self) -> Self::Static {
33        Self::Static::Owned(self.into_owned())
34    }
35}
36
37#[cfg(any(feature = "std", feature = "alloc"))]
38impl<T: Clone + IntoStatic<Static: Clone>> IntoStatic for Cow<'_, [T]> {
39    type Static = Cow<'static, [T::Static]>;
40
41    fn into_static(self) -> Self::Static {
42        Self::Static::Owned(self.into_owned().into_static())
43    }
44}
45
46impl<T: IntoStatic> IntoStatic for Option<T> {
47    type Static = Option<T::Static>;
48
49    fn into_static(self) -> Self::Static {
50        self.map(IntoStatic::into_static)
51    }
52}
53
54impl<T: IntoStatic, E: IntoStatic> IntoStatic for Result<T, E> {
55    type Static = Result<T::Static, E::Static>;
56
57    fn into_static(self) -> Self::Static {
58        self.map(IntoStatic::into_static)
59            .map_err(IntoStatic::into_static)
60    }
61}
62
63impl<T: IntoStatic, const N: usize> IntoStatic for [T; N] {
64    type Static = [T::Static; N];
65
66    fn into_static(self) -> Self::Static {
67        self.map(IntoStatic::into_static)
68    }
69}
70
71#[cfg(any(feature = "alloc", feature = "std"))]
72impl<T: IntoStatic> IntoStatic for Vec<T> {
73    type Static = Vec<T::Static>;
74
75    fn into_static(self) -> Self::Static {
76        self.into_iter().map(IntoStatic::into_static).collect()
77    }
78}
79
80macro_rules! impl_tuple {
81    ($($name: ident: $type: ident),+) => {
82        impl<$($type: $crate::IntoStatic),+> $crate::IntoStatic for ($($type,)+) {
83            type Static = ($($type::Static,)+);
84
85            fn into_static(self) -> Self::Static {
86                let ($($name,)+) = self;
87
88                ($($name.into_static(),)+)
89            }
90        }
91    }
92}
93
94impl_tuple!(a: A);
95impl_tuple!(a: A, b: B);
96impl_tuple!(a: A, b: B, c: C);
97impl_tuple!(a: A, b: B, c: C, d: D);
98impl_tuple!(a: A, b: B, c: C, d: D, e: E);
99impl_tuple!(a: A, b: B, c: C, d: D, e: E, f: F);
100impl_tuple!(a: A, b: B, c: C, d: D, e: E, f: F, g: G);
101impl_tuple!(a: A, b: B, c: C, d: D, e: E, f: F, g: G, h: H);
102impl_tuple!(a: A, b: B, c: C, d: D, e: E, f: F, g: G, h: H, i: I);
103impl_tuple!(a: A, b: B, c: C, d: D, e: E, f: F, g: G, h: H, i: I, j: J);
104impl_tuple!(a: A, b: B, c: C, d: D, e: E, f: F, g: G, h: H, i: I, j: J, k: K);
105impl_tuple!(a: A, b: B, c: C, d: D, e: E, f: F, g: G, h: H, i: I, j: J, k: K, l: L);