try_clone/lib.rs
1#![cfg_attr(
2 feature = "blanket-impl",
3 feature(auto_traits, negative_impls, min_specialization)
4)]
5#![cfg_attr(
6 all(feature = "alloc", feature = "nightly"),
7 feature(allocator_api, clone_from_ref)
8)]
9#![cfg_attr(feature = "doc-cfg", feature(doc_cfg))]
10#![cfg_attr(not(feature = "std"), no_std)]
11
12//! Fallible cloning.
13//!
14//! This crate defines [`TryClone`], a small trait for types whose cloning
15//! operation can fail. Unlike [`Clone`], which is infallible by design,
16//! [`TryClone`] returns a [`Result`] to allow implementations to report errors.
17//!
18//! Implementations are provided for standard library types that expose a
19//! `try_clone` API, such as [`File`](::std::fs::File), as well as for common containers
20//! and collections ([`Box`], [`Arc`](::std::sync::Arc), [`Vec`], ...) where appropriate APIs
21//! exists.
22//!
23//! A blanket implementation is available behind the `blanket-impl` feature,
24//! which implements [`TryClone`] for all [`Clone`] types.
25
26/// A fallible variant of [`Clone`].
27///
28/// this trait is intended for types where cloning can fail, for example due to
29/// allocation failures, resource limits, or external constraints.
30///
31/// Unlike [`Clone`], the cloning operation returns a [`Result`] with an
32/// associated error type.
33pub trait TryClone: Sized {
34 /// The error type returned when cloning fails.
35 type Err;
36
37 /// Tries to create a duplicate of the value.
38 ///
39 /// # Errors
40 /// Returns [`Err`] if cloning fails.
41 fn try_clone(&self) -> Result<Self, Self::Err>;
42
43 /// Performs copy-assignment from source.
44 /// `a.clone_from(&b)` is equivalent to `a = b.clone()` in functionality, but can be overridden to reuse the resources of `a` to avoid unnecessary allocations.
45 ///
46 /// # Errors
47 /// Returns [`Err`] if cloning fails.
48 fn try_clone_from(&mut self, source: &Self) -> Result<(), Self::Err> {
49 *self = source.try_clone()?;
50 Ok(())
51 }
52}
53
54/// A trait for fallibly cloning a value into an owned form.
55///
56/// This is similar in spirit to [`ToOwned`], but allows the conversion
57/// to fail and does not require `Owned` to implement [`Clone`].
58pub trait TryCloneToOwned: Sized {
59 /// The owned type produced by cloning.
60 type Owned;
61 /// The error type returned when cloning fails.
62 type Err;
63
64 /// Attempts to create an owned version of the value.
65 ///
66 /// # Errors
67 /// Returns [`Err`] if cloning fails.
68 fn try_clone_to_owned(&self) -> Result<Self::Owned, Self::Err>;
69}
70
71#[cfg(feature = "blanket-impl")]
72use ::core::convert::Infallible;
73
74#[cfg(feature = "blanket-impl")]
75include!("blanket_impl.rs");
76
77#[cfg(feature = "blanket-impl")]
78impl<T: Clone + ForwardTryCloneToClone> TryClone for T {
79 type Err = Infallible;
80
81 default fn try_clone(&self) -> Result<Self, Self::Err> {
82 Ok(self.clone())
83 }
84
85 default fn try_clone_from(&mut self, source: &Self) -> Result<(), Self::Err> {
86 self.clone_from(source);
87 Ok(())
88 }
89}
90
91mod core;
92
93#[cfg(feature = "alloc")]
94mod alloc;
95
96#[cfg(feature = "std")]
97mod std;
98
99#[cfg(all(feature = "std", windows))]
100mod windows;
101
102#[cfg(all(feature = "std", unix))]
103mod unix;