Skip to content

Commit 385a34c

Browse files
committed
Prevent downstream impl DerefMut for Pin<LocalType>
1 parent 501f8e0 commit 385a34c

File tree

1 file changed

+58
-1
lines changed

1 file changed

+58
-1
lines changed

core/src/pin.rs

Lines changed: 58 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1689,9 +1689,66 @@ impl<Ptr: [const] Deref> const Deref for Pin<Ptr> {
16891689
}
16901690
}
16911691

1692+
mod helper {
1693+
/// Helper that prevents downstream crates from implementing `DerefMut` for `Pin`.
1694+
///
1695+
/// This type is not `#[fundamental]`, so it's possible to relax its `DerefMut` impl bounds in
1696+
/// the future, so the orphan rules reject downstream impls of `DerefMut` of `Pin`.
1697+
#[repr(transparent)]
1698+
#[unstable(feature = "pin_derefmut_internals", issue = "none")]
1699+
#[allow(missing_debug_implementations)]
1700+
pub struct Pin<Ptr> {
1701+
pointer: Ptr,
1702+
}
1703+
1704+
#[unstable(feature = "pin_derefmut_internals", issue = "none")]
1705+
#[rustc_const_unstable(feature = "const_convert", issue = "143773")]
1706+
pub const trait DerefMut {
1707+
type Target: ?Sized;
1708+
fn deref_mut(&mut self) -> &mut Self::Target;
1709+
}
1710+
1711+
#[unstable(feature = "pin_derefmut_internals", issue = "none")]
1712+
#[rustc_const_unstable(feature = "const_convert", issue = "143773")]
1713+
impl<Ptr: [const] super::DerefMut> const DerefMut for Pin<Ptr>
1714+
where
1715+
Ptr::Target: crate::marker::Unpin,
1716+
{
1717+
type Target = Ptr::Target;
1718+
1719+
#[inline(always)]
1720+
fn deref_mut(&mut self) -> &mut Ptr::Target {
1721+
&mut self.pointer
1722+
}
1723+
}
1724+
}
1725+
16921726
#[stable(feature = "pin", since = "1.33.0")]
16931727
#[rustc_const_unstable(feature = "const_convert", issue = "143773")]
1694-
impl<Ptr: [const] DerefMut<Target: Unpin>> const DerefMut for Pin<Ptr> {
1728+
#[cfg(not(doc))]
1729+
impl<Ptr> const DerefMut for Pin<Ptr>
1730+
where
1731+
Ptr: [const] Deref,
1732+
helper::Pin<Ptr>: [const] helper::DerefMut<Target = Self::Target>,
1733+
{
1734+
#[inline]
1735+
fn deref_mut(&mut self) -> &mut Ptr::Target {
1736+
// SAFETY: Pin and helper::Pin have the same layout, so this is equivalent to
1737+
// `&mut self.pointer` which is safe because `Target: Unpin`.
1738+
helper::DerefMut::deref_mut(unsafe {
1739+
&mut *(self as *mut Pin<Ptr> as *mut helper::Pin<Ptr>)
1740+
})
1741+
}
1742+
}
1743+
1744+
#[stable(feature = "pin", since = "1.33.0")]
1745+
#[rustc_const_unstable(feature = "const_convert", issue = "143773")]
1746+
#[cfg(doc)]
1747+
impl<Ptr> const DerefMut for Pin<Ptr>
1748+
where
1749+
Ptr: [const] DerefMut,
1750+
Ptr::Target: Unpin,
1751+
{
16951752
fn deref_mut(&mut self) -> &mut Ptr::Target {
16961753
Pin::get_mut(Pin::as_mut(self))
16971754
}

0 commit comments

Comments
 (0)