blueprint_dupe/
lib.rs

1/*
2 * Copyright (c) Meta Platforms, Inc. and affiliates.
3 *
4 * This source code is dual-licensed under either the MIT license found in the
5 * LICENSE-MIT file in the root directory of this source tree or the Apache
6 * License, Version 2.0 found in the LICENSE-APACHE file in the root directory
7 * of this source tree. You may select, at your option, one of the
8 * above-listed licenses.
9 */
10
11//! A cheap version of [`Clone`].
12
13pub mod __macro_refs;
14pub(crate) mod iter;
15pub(crate) mod option;
16
17use std::cell::Cell;
18use std::mem::ManuallyDrop;
19use std::num::*;
20use std::rc::Rc;
21use std::sync::Arc;
22
23pub use blueprint_dupe_derive::Clone_;
24pub use blueprint_dupe_derive::Copy_;
25pub use blueprint_dupe_derive::Dupe;
26pub use blueprint_dupe_derive::Dupe_;
27
28pub use crate::iter::IterDupedExt;
29pub use crate::option::OptionDupedExt;
30
31/// Like [`Clone`], but should only be available if [`Clone`] is
32/// constant time and zero allocation (e.g. a few [`Arc`] bumps).
33/// The implementation of `dupe` should _always_ call `clone`.
34pub trait Dupe: Clone {
35    #[inline]
36    fn dupe(&self) -> Self {
37        self.clone()
38    }
39}
40
41// Smart pointer/wrapper types
42impl<A: ?Sized> Dupe for &A {}
43impl<A: ?Sized> Dupe for *const A {}
44impl<A: ?Sized> Dupe for *mut A {}
45impl<A: ?Sized> Dupe for Arc<A> {}
46impl<A: ?Sized> Dupe for std::sync::Weak<A> {}
47impl<A: ?Sized> Dupe for Rc<A> {}
48impl<A: ?Sized> Dupe for std::rc::Weak<A> {}
49impl<A: Copy> Dupe for Cell<A> {}
50impl<A: Dupe> Dupe for ManuallyDrop<A> {}
51
52// Small containers
53impl<A: Dupe> Dupe for Option<A> {}
54impl<T: Dupe, E: Dupe> Dupe for Result<T, E> {}
55impl<A: Dupe> Dupe for std::ops::Bound<A> {}
56impl<A: Dupe> Dupe for std::pin::Pin<A> {}
57impl<A: Dupe> Dupe for std::ptr::NonNull<A> {}
58impl<A: Dupe> Dupe for std::task::Poll<A> {}
59impl Dupe for () {}
60impl<A: Dupe> Dupe for (A,) {}
61impl<A: Dupe, B: Dupe> Dupe for (A, B) {}
62impl<A: Dupe, B: Dupe, C: Dupe> Dupe for (A, B, C) {}
63impl<A: Dupe, B: Dupe, C: Dupe, D: Dupe> Dupe for (A, B, C, D) {}
64impl<A: Dupe, B: Dupe, C: Dupe, D: Dupe, E: Dupe> Dupe for (A, B, C, D, E) {}
65impl<A: Dupe, B: Dupe, C: Dupe, D: Dupe, E: Dupe, F: Dupe> Dupe for (A, B, C, D, E, F) {}
66impl<A: Dupe, B: Dupe, C: Dupe, D: Dupe, E: Dupe, F: Dupe, G: Dupe> Dupe for (A, B, C, D, E, F, G) {}
67impl<A: Dupe, B: Dupe, C: Dupe, D: Dupe, E: Dupe, F: Dupe, G: Dupe, H: Dupe> Dupe
68    for (A, B, C, D, E, F, G, H)
69{
70}
71impl<A: Dupe, B: Dupe, C: Dupe, D: Dupe, E: Dupe, F: Dupe, G: Dupe, H: Dupe, I: Dupe> Dupe
72    for (A, B, C, D, E, F, G, H, I)
73{
74}
75impl<A: Dupe, B: Dupe, C: Dupe, D: Dupe, E: Dupe, F: Dupe, G: Dupe, H: Dupe, I: Dupe, J: Dupe> Dupe
76    for (A, B, C, D, E, F, G, H, I, J)
77{
78}
79
80impl<A: Dupe, const N: usize> Dupe for [A; N] {}
81
82// Atomic types
83impl Dupe for bool {}
84impl Dupe for char {}
85impl Dupe for u8 {}
86impl Dupe for u16 {}
87impl Dupe for u32 {}
88impl Dupe for u64 {}
89impl Dupe for u128 {}
90impl Dupe for usize {}
91impl Dupe for i8 {}
92impl Dupe for i16 {}
93impl Dupe for i32 {}
94impl Dupe for i64 {}
95impl Dupe for i128 {}
96impl Dupe for isize {}
97impl Dupe for f32 {}
98impl Dupe for f64 {}
99impl Dupe for NonZeroU8 {}
100impl Dupe for NonZeroU16 {}
101impl Dupe for NonZeroU32 {}
102impl Dupe for NonZeroU64 {}
103impl Dupe for NonZeroU128 {}
104impl Dupe for NonZeroUsize {}
105impl Dupe for NonZeroI8 {}
106impl Dupe for NonZeroI16 {}
107impl Dupe for NonZeroI32 {}
108impl Dupe for NonZeroI64 {}
109impl Dupe for NonZeroI128 {}
110impl Dupe for NonZeroIsize {}
111
112// Other std types that are Copyable
113impl Dupe for std::any::TypeId {}
114impl Dupe for std::marker::PhantomPinned {}
115impl Dupe for std::net::Ipv4Addr {}
116impl Dupe for std::net::Ipv6Addr {}
117impl Dupe for std::net::SocketAddrV4 {}
118impl Dupe for std::net::SocketAddrV6 {}
119impl Dupe for std::thread::ThreadId {}
120impl Dupe for std::time::Instant {}
121impl Dupe for std::time::SystemTime {}
122impl Dupe for std::time::Duration {}
123impl<T: ?Sized> Dupe for std::marker::PhantomData<T> {}
124
125impl<R> Dupe for fn() -> R {}
126impl<A1, R> Dupe for fn(A1) -> R {}
127impl<A1, A2, R> Dupe for fn(A1, A2) -> R {}
128impl<A1, A2, A3, R> Dupe for fn(A1, A2, A3) -> R {}
129impl<A1, A2, A3, A4, R> Dupe for fn(A1, A2, A3, A4) -> R {}
130impl<A1, A2, A3, A4, A5, R> Dupe for fn(A1, A2, A3, A4, A5) -> R {}
131impl<A1, A2, A3, A4, A5, A6, R> Dupe for fn(A1, A2, A3, A4, A5, A6) -> R {}
132impl<A1, A2, A3, A4, A5, A6, A7, R> Dupe for fn(A1, A2, A3, A4, A5, A6, A7) -> R {}
133impl<A1, A2, A3, A4, A5, A6, A7, A8, R> Dupe for fn(A1, A2, A3, A4, A5, A6, A7, A8) -> R {}
134impl<A1, A2, A3, A4, A5, A6, A7, A8, A9, R> Dupe for fn(A1, A2, A3, A4, A5, A6, A7, A8, A9) -> R {}
135impl<A1, A2, A3, A4, A5, A6, A7, A8, A9, A10, R> Dupe
136    for fn(A1, A2, A3, A4, A5, A6, A7, A8, A9, A10) -> R
137{
138}
139impl<A1, A2, A3, A4, A5, A6, A7, A8, A9, A10, A11, R> Dupe
140    for fn(A1, A2, A3, A4, A5, A6, A7, A8, A9, A10, A11) -> R
141{
142}
143impl<A1, A2, A3, A4, A5, A6, A7, A8, A9, A10, A11, A12, R> Dupe
144    for fn(A1, A2, A3, A4, A5, A6, A7, A8, A9, A10, A11, A12) -> R
145{
146}
147// Rust goes up to 12 arguments for traits, so we follow
148
149#[cfg(test)]
150mod tests {
151    use super::*;
152    #[allow(unused_imports)] // Not actually unused, this makes testing the derive macro work
153    use crate as dupe;
154
155    #[test]
156    fn test_dupe_generic() {
157        #[derive(Clone, Dupe, Debug, PartialEq, Eq)]
158        struct Foo {}
159        #[derive(Clone, Dupe, Debug, PartialEq, Eq)]
160        struct FooT<T> {
161            foo: T,
162        }
163        #[derive(Clone, Dupe, Debug, PartialEq, Eq)]
164        struct Faz;
165
166        let x = Foo {};
167        assert_eq!(x, Dupe::dupe(&x));
168
169        let x = FooT { foo: 1 };
170        assert_eq!(x, Dupe::dupe(&x));
171
172        let x = Faz;
173        assert_eq!(x, Dupe::dupe(&x));
174    }
175
176    #[test]
177    fn test_dupe_() {
178        #[derive(Debug, PartialEq, Eq)]
179        struct NoClone();
180        #[derive(Dupe_, Debug, PartialEq, Eq)]
181        struct FooT<T> {
182            foo: Arc<T>,
183        }
184
185        impl<T> Clone for FooT<T> {
186            fn clone(&self) -> Self {
187                FooT {
188                    foo: self.foo.clone(),
189                }
190            }
191        }
192
193        let x = FooT {
194            foo: Arc::new(NoClone()),
195        };
196        assert_eq!(x, Dupe::dupe(&x));
197    }
198
199    #[test]
200    fn test_dupe_enum() {
201        #[derive(Clone, Dupe, Debug, PartialEq, Eq)]
202        struct Foo();
203        #[derive(Clone, Dupe, Debug, PartialEq, Eq)]
204        struct Foo2;
205        #[derive(Clone, Dupe, Debug, PartialEq, Eq)]
206        struct Bar(i64, bool, Foo2);
207        #[derive(Clone, Dupe, Debug, PartialEq, Eq)]
208        struct Baz {
209            foo: usize,
210        }
211        #[derive(Clone, Dupe, Debug, PartialEq, Eq)]
212        enum Qux {
213            Foo(),
214            Foo2,
215            Bar(Foo, Bar),
216            Baz { foo: Foo, bar: Bar, baz: Baz },
217        }
218
219        let x = Qux::Bar(Foo(), Bar(8, true, Foo2));
220        assert_eq!(x, Dupe::dupe(&x));
221        let x = Qux::Baz {
222            foo: Foo(),
223            bar: Bar(7, false, Foo2),
224            baz: Baz { foo: 9 },
225        };
226        assert_eq!(x, Dupe::dupe(&x));
227        let x = Qux::Foo();
228        assert_eq!(x, Dupe::dupe(&x));
229        let x = Qux::Foo2;
230        assert_eq!(x, Dupe::dupe(&x));
231    }
232
233    #[test]
234    fn test_dupe_fn()
235    where
236        fn(usize): Dupe,
237        fn(String, Vec<usize>) -> bool: Dupe,
238    {
239        // Tests are in the where
240    }
241}