This commit is contained in:
Dario Nieuwenhuis 2022-07-22 15:22:00 +02:00
parent 715fa51468
commit f9f2de3dfb
2 changed files with 18 additions and 65 deletions

View File

@ -82,14 +82,12 @@ macro_rules! unborrow {
#[macro_export] #[macro_export]
macro_rules! unsafe_impl_unborrow { macro_rules! unsafe_impl_unborrow {
($type:ident) => { ($type:ident) => {
unsafe impl $crate::Unborrow for $type { impl $crate::Unborrow for $type {
type Target = $type; type Target = $type;
#[inline] #[inline]
fn unborrow<'a>(self) -> $crate::Unborrowed<'a, Self::Target> unsafe fn unborrow_unchecked(&mut self) -> Self::Target {
where $type { ..*self }
Self: 'a,
{
$crate::Unborrowed::new(self)
} }
} }
}; };

View File

@ -43,75 +43,30 @@ impl<'a, T> DerefMut for Unborrowed<'a, T> {
/// ///
/// This allows writing HAL drivers that either own or borrow their peripherals, but that don't have /// This allows writing HAL drivers that either own or borrow their peripherals, but that don't have
/// to store pointers in the borrowed case. /// to store pointers in the borrowed case.
/// pub trait Unborrow: Sized {
/// Safety: this trait can be used to copy non-Copy types. Implementors must not cause
/// immediate UB when copied, and must not cause UB when copies are later used, provided they
/// are only used according the [`Self::unborrow`] safety contract.
///
pub unsafe trait Unborrow {
/// Unborrow result type /// Unborrow result type
type Target; type Target;
unsafe fn unborrow_unchecked(&mut self) -> Self::Target;
/// Unborrow a value. /// Unborrow a value.
fn unborrow<'a>(self) -> Unborrowed<'a, Self::Target> #[inline]
where fn unborrow<'a>(mut self) -> Unborrowed<'a, Self::Target>
Self: 'a;
}
unsafe impl<'b, T: Unborrow> Unborrow for &'b mut T {
type Target = T::Target;
fn unborrow<'a>(self) -> Unborrowed<'a, Self::Target>
where where
Self: 'a, Self: 'a,
{ {
// Safety: This returns a copy of a singleton that's normally not Unborrowed::new(unsafe { self.unborrow_unchecked() })
// copiable. The returned copy must ONLY be used while the lifetime of `self` is
// valid, as if it were accessed through `self` every time.
T::unborrow(unsafe { core::ptr::read(self) })
} }
} }
unsafe impl<'b, T> Unborrow for Unborrowed<'b, T> { impl<'b, T: DerefMut> Unborrow for T
type Target = T; where
T::Target: Unborrow,
{
type Target = <T::Target as Unborrow>::Target;
fn unborrow<'a>(self) -> Unborrowed<'a, Self::Target> #[inline]
where unsafe fn unborrow_unchecked(&mut self) -> Self::Target {
Self: 'a, self.deref_mut().unborrow_unchecked()
{
self
} }
} }
macro_rules! unsafe_impl_unborrow_tuples {
($($t:ident),+) => {
unsafe impl<$($t),+> Unborrow for ($($t),+)
where
$(
$t: Unborrow<Target = $t>
),+
{
type Target = ($($t),+);
fn unborrow<'a>(self) -> Unborrowed<'a, Self::Target>
where
Self: 'a
{
Unborrowed::new(self)
}
}
};
}
unsafe_impl_unborrow_tuples!(A, B);
unsafe_impl_unborrow_tuples!(A, B, C);
unsafe_impl_unborrow_tuples!(A, B, C, D);
unsafe_impl_unborrow_tuples!(A, B, C, D, E);
unsafe_impl_unborrow_tuples!(A, B, C, D, E, F);
unsafe_impl_unborrow_tuples!(A, B, C, D, E, F, G);
unsafe_impl_unborrow_tuples!(A, B, C, D, E, F, G, H);
unsafe_impl_unborrow_tuples!(A, B, C, D, E, F, G, H, I);
unsafe_impl_unborrow_tuples!(A, B, C, D, E, F, G, H, I, J);
unsafe_impl_unborrow_tuples!(A, B, C, D, E, F, G, H, I, J, K);
unsafe_impl_unborrow_tuples!(A, B, C, D, E, F, G, H, I, J, K, L);