Skip to content

Commit febdc88

Browse files
committed
claim trait to allow non-fallible cloning
1 parent 80f3e20 commit febdc88

File tree

3 files changed

+59
-7
lines changed

3 files changed

+59
-7
lines changed

src/claim.rs

Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
1+
use alloc::rc::Rc;
2+
use alloc::sync::Arc;
3+
use core::convert::Infallible;
4+
use core::marker::PhantomData;
5+
6+
/// A marker trait for infallible cloneable objects.
7+
/// Only implement this for your type if you can guarantee that cloning it
8+
/// is guaranteed not to panic.
9+
///
10+
/// For details on the idea, read the [Claiming, auto and
11+
/// otherwise](https://smallcultfollowing.com/babysteps/blog/2024/06/21/claim-auto-and-otherwise/)
12+
/// blog post.
13+
pub trait Claim: Clone {}
14+
15+
// Anything which is trivially copiable is automatically infallible
16+
// We need to list these out since the compiler will not allow us to `impl <T: Copy> impl Claim {}`
17+
impl Claim for () {}
18+
impl Claim for u8 {}
19+
impl Claim for u16 {}
20+
impl Claim for u32 {}
21+
impl Claim for u64 {}
22+
impl Claim for u128 {}
23+
impl Claim for usize {}
24+
impl Claim for i8 {}
25+
impl Claim for i16 {}
26+
impl Claim for i32 {}
27+
impl Claim for i64 {}
28+
impl Claim for i128 {}
29+
impl Claim for isize {}
30+
impl Claim for f32 {}
31+
impl Claim for f64 {}
32+
impl Claim for bool {}
33+
impl Claim for char {}
34+
impl<T: ?Sized> Claim for *const T {}
35+
impl<T: ?Sized> Claim for *mut T {}
36+
impl<T: Copy, const N: usize> Claim for [T; N] {}
37+
impl<T: ?Sized> Claim for PhantomData<T> {}
38+
impl<T: ?Sized> Claim for &T {}
39+
40+
// A few other common impls, non-exhaustive
41+
impl<T> Claim for Arc<T> {}
42+
impl<T> Claim for Rc<T> {}
43+
impl Claim for Infallible {}
44+
impl<T: Claim> Claim for Option<T> {}
45+
impl<T: Claim, E: Claim> Claim for Result<T, E> {}

src/lib.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,5 +5,6 @@
55
extern crate alloc;
66
extern crate core;
77

8+
mod claim;
89
pub mod try_clone;
910
pub mod vec;

src/vec.rs

Lines changed: 13 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
use crate::claim::Claim;
12
use crate::try_clone::TryClone;
23
use alloc::alloc::Allocator;
34
use alloc::collections::TryReserveError;
@@ -147,7 +148,7 @@ impl<T, A: Allocator> Vec<T, A> {
147148
}
148149
}
149150

150-
impl<T: Clone, A: Allocator> Vec<T, A> {
151+
impl<T: Claim, A: Allocator> Vec<T, A> {
151152
#[inline]
152153
pub fn extend_from_slice(&mut self, slice: &[T]) -> Result<(), TryReserveError> {
153154
self.reserve(slice.len())?;
@@ -186,7 +187,7 @@ impl<T: Clone, A: Allocator> Vec<T, A> {
186187
}
187188
}
188189

189-
impl<T: Copy, A: Allocator + Clone> TryClone for Vec<T, A> {
190+
impl<T: Claim, A: Allocator + Claim> TryClone for Vec<T, A> {
190191
type Error = TryReserveError;
191192

192193
fn try_clone(&self) -> Result<Self, Self::Error> {
@@ -288,6 +289,7 @@ impl<T, A: Allocator> AsMut<[T]> for Vec<T, A> {
288289
#[cfg(test)]
289290
mod tests {
290291
use super::*;
292+
use crate::claim::Claim;
291293
use alloc::alloc::Global;
292294
use alloc::boxed::Box;
293295
use alloc::collections::TryReserveError;
@@ -303,6 +305,8 @@ mod tests {
303305
in_use: Arc<AtomicUsize>,
304306
}
305307

308+
impl Claim for WatermarkAllocator {}
309+
306310
impl WatermarkAllocator {
307311
pub(crate) fn in_use(&self) -> usize {
308312
self.in_use.load(Ordering::SeqCst)
@@ -496,15 +500,17 @@ mod tests {
496500
assert_eq!(vec[3], 4);
497501
}
498502

499-
/// A type that implements `Clone` but not `Copy`.
503+
/// A type that implements `Clone` and `Claim`, but not `Copy`.
500504
#[derive(Clone, Eq, PartialEq)]
501-
struct Cloneable(i32);
505+
struct Claimable(i32);
506+
507+
impl Claim for Claimable {}
502508

503509
#[test]
504510
fn test_extend_from_slice_clone() {
505511
let wma = WatermarkAllocator::new(32);
506512
let mut vec = Vec::new_in(wma);
507-
vec.extend_from_slice(&[Cloneable(1), Cloneable(2), Cloneable(3), Cloneable(4)])
513+
vec.extend_from_slice(&[Claimable(1), Claimable(2), Claimable(3), Claimable(4)])
508514
.unwrap();
509515
}
510516

@@ -783,12 +789,12 @@ mod tests {
783789
}
784790
}
785791

786-
fn get_first_elem_vec<T: Clone, A: Allocator>(vec: impl AsRef<Vec<T, A>>) -> T {
792+
fn get_first_elem_vec<T: Claim, A: Allocator>(vec: impl AsRef<Vec<T, A>>) -> T {
787793
let vec = vec.as_ref();
788794
vec.first().unwrap().clone()
789795
}
790796

791-
fn get_first_elem_slice<T: Clone>(slice: impl AsRef<[T]>) -> T {
797+
fn get_first_elem_slice<T: Claim>(slice: impl AsRef<[T]>) -> T {
792798
let vec = slice.as_ref();
793799
vec.first().unwrap().clone()
794800
}

0 commit comments

Comments
 (0)