From 05ec7c1dbf41bd3e9013a1451ed5816fcae753ea Mon Sep 17 00:00:00 2001 From: Ryan Lopopolo Date: Tue, 15 Jun 2021 06:54:59 -0700 Subject: [PATCH] Add Adopt::try_adopt --- src/adopt.rs | 33 ++++++++++++++++++++++++++++++--- src/lib.rs | 1 + 2 files changed, 31 insertions(+), 3 deletions(-) diff --git a/src/adopt.rs b/src/adopt.rs index d5d55bab7..cc15c2b18 100644 --- a/src/adopt.rs +++ b/src/adopt.rs @@ -1,3 +1,4 @@ +use core::fmt; use core::ptr; use crate::link::Link; @@ -13,6 +14,21 @@ mod sealed { impl Sealed for Rc {} } +/// The error type for `try_adopt` methods. +/// +/// See [`Adopt::try_adopt`] for more information. +#[derive(Debug, Clone, Copy, Hash, PartialEq, Eq, PartialOrd, Ord)] +pub struct AdoptError(()); + +#[cfg(feature = "std")] +impl std::error::Error for AdoptError {} + +impl fmt::Display for AdoptError { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + f.write_str("Rc adoption failed because the Rc does not own a pointer to the adoptee") + } +} + /// Build a graph of linked [`Rc`] smart pointers to enable busting cycles on /// drop. /// @@ -34,12 +50,20 @@ mod sealed { /// /// [`adopt_unchecked`]: Adopt::adopt_unchecked /// [undefined behavior]: https://doc.rust-lang.org/reference/behavior-considered-undefined.html -pub unsafe trait Adopt: sealed::Sealed { +pub unsafe trait Adopt: sealed::Sealed + Sized { /// The smart pointer's inner owned value. type Inner; /// TODO: document me! - fn adopt(this: &mut Self, other: &Self) + fn adopt(this: &mut Self, other: &Self) -> Self + where + Self::Inner: Trace, + { + Self::try_adopt(this, other).unwrap_or_else(|err| panic!("{}", err)) + } + + /// TODO: document me! + fn try_adopt(this: &mut Self, other: &Self) -> Result where Self::Inner: Trace; @@ -92,7 +116,7 @@ unsafe impl Adopt for Rc { type Inner = T; /// TODO: document me! - fn adopt(this: &mut Self, other: &Self) + fn try_adopt(this: &mut Self, other: &Self) -> Result where Self::Inner: Trace, { @@ -125,6 +149,9 @@ unsafe impl Adopt for Rc { unsafe { Self::adopt_unchecked(this, &node); } + Ok(node) + } else { + Err(AdoptError(())) } } diff --git a/src/lib.rs b/src/lib.rs index 5078f44dd..1024e6619 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -145,6 +145,7 @@ mod trace; pub mod implementing_self_referential_data_structures; pub use adopt::Adopt; +pub use adopt::AdoptError; pub use rc::Rc; pub use rc::Weak; pub use trace::Trace;