diff --git a/library/core/src/pin.rs b/library/core/src/pin.rs index 14bf7ba90150e..5e35c7ba84dcb 100644 --- a/library/core/src/pin.rs +++ b/library/core/src/pin.rs @@ -1676,8 +1676,60 @@ impl Deref for Pin { } } +mod hidden { + use super::*; + + /// Helper that prevents downstream crates from implementing `DerefMut` for `Pin`. + /// + /// This type is not `#[fundamental]`, so it's possible to relax its `DerefMut` impl bounds in + /// the future, so the orphan rules reject downstream impls of `DerefMut` of `Pin`. + #[repr(transparent)] + #[unstable(feature = "pin_derefmut_internals", issue = "none")] + #[allow(missing_debug_implementations)] + pub struct PinHelper { + pointer: Ptr, + } + + #[unstable(feature = "pin_derefmut_internals", issue = "none")] + impl Deref for PinHelper { + type Target = Ptr::Target; + fn deref(&self) -> &Ptr::Target { + &self.pointer + } + } + + #[unstable(feature = "pin_derefmut_internals", issue = "none")] + impl> DerefMut for PinHelper { + #[inline(always)] + fn deref_mut(&mut self) -> &mut Ptr::Target { + &mut self.pointer + } + } +} + #[stable(feature = "pin", since = "1.33.0")] -impl> DerefMut for Pin { +#[cfg(not(doc))] +impl DerefMut for Pin +where + Ptr: Deref, + hidden::PinHelper: DerefMut, +{ + fn deref_mut(&mut self) -> &mut Ptr::Target { + // SAFETY: Pin and PinHelper have the same layout, so this is equivalent to + // `&mut self.pointer` which is safe because `Target: Unpin`. + unsafe { &mut **(self as *mut Pin as *mut hidden::PinHelper) } + } +} + +// This impl is only used during documentation, but it is fully equivalent to the above impl with +// the exception of how the orphan rule treats it. +#[stable(feature = "pin", since = "1.33.0")] +#[cfg(doc)] +impl DerefMut for Pin +where + Ptr: DerefMut, + Ptr::Target: Unpin, +{ fn deref_mut(&mut self) -> &mut Ptr::Target { Pin::get_mut(Pin::as_mut(self)) } @@ -1759,7 +1811,7 @@ unsafe impl<'a, T: ?Sized> PinCoerceUnsized for &'a T {} unsafe impl<'a, T: ?Sized> PinCoerceUnsized for &'a mut T {} #[stable(feature = "pin", since = "1.33.0")] -unsafe impl PinCoerceUnsized for Pin {} +unsafe impl PinCoerceUnsized for Pin {} #[stable(feature = "pin", since = "1.33.0")] unsafe impl PinCoerceUnsized for *const T {} diff --git a/tests/mir-opt/inline_coroutine_body.run2-{closure#0}.Inline.panic-abort.diff b/tests/mir-opt/inline_coroutine_body.run2-{closure#0}.Inline.panic-abort.diff index 22e6ea722ddaf..fc5eeb13e569c 100644 --- a/tests/mir-opt/inline_coroutine_body.run2-{closure#0}.Inline.panic-abort.diff +++ b/tests/mir-opt/inline_coroutine_body.run2-{closure#0}.Inline.panic-abort.diff @@ -64,27 +64,25 @@ + let mut _45: &mut std::future::Ready<()>; + let mut _46: &mut std::pin::Pin<&mut std::future::Ready<()>>; + scope 14 (inlined > as DerefMut>::deref_mut) { -+ scope 15 (inlined Pin::<&mut std::future::Ready<()>>::as_mut) { -+ let mut _47: &mut &mut std::future::Ready<()>; -+ scope 16 (inlined Pin::<&mut std::future::Ready<()>>::new_unchecked) { ++ let mut _47: *mut std::pin::hidden::PinHelper<&mut std::future::Ready<()>>; ++ let mut _48: *mut std::pin::Pin<&mut std::future::Ready<()>>; ++ scope 15 (inlined > as DerefMut>::deref_mut) { ++ let mut _49: &mut &mut std::future::Ready<()>; ++ scope 16 (inlined <&mut std::future::Ready<()> as DerefMut>::deref_mut) { + } -+ scope 18 (inlined <&mut std::future::Ready<()> as DerefMut>::deref_mut) { -+ } -+ } -+ scope 17 (inlined Pin::<&mut std::future::Ready<()>>::get_mut) { + } + } -+ scope 19 (inlined Option::<()>::take) { -+ let mut _48: std::option::Option<()>; -+ scope 20 (inlined std::mem::replace::>) { -+ scope 21 { ++ scope 17 (inlined Option::<()>::take) { ++ let mut _50: std::option::Option<()>; ++ scope 18 (inlined std::mem::replace::>) { ++ scope 19 { + } + } + } -+ scope 22 (inlined #[track_caller] Option::<()>::expect) { -+ let mut _49: isize; -+ let mut _50: !; -+ scope 23 { ++ scope 20 (inlined #[track_caller] Option::<()>::expect) { ++ let mut _51: isize; ++ let mut _52: !; ++ scope 21 { + } + } + } @@ -227,26 +225,32 @@ + _22 = &mut (*_23); + StorageDead(_24); + StorageLive(_45); -+ StorageLive(_46); -+ StorageLive(_50); ++ StorageLive(_47); ++ StorageLive(_52); + StorageLive(_42); + StorageLive(_43); + StorageLive(_44); ++ StorageLive(_46); + _46 = &mut _19; -+ StorageLive(_47); -+ _47 = &mut (_19.0: &mut std::future::Ready<()>); -+ _45 = copy (_19.0: &mut std::future::Ready<()>); -+ StorageDead(_47); -+ _44 = &mut ((*_45).0: std::option::Option<()>); + StorageLive(_48); -+ _48 = Option::<()>::None; -+ _43 = copy ((*_45).0: std::option::Option<()>); -+ ((*_45).0: std::option::Option<()>) = copy _48; ++ _48 = &raw mut _19; ++ _47 = move _48 as *mut std::pin::hidden::PinHelper<&mut std::future::Ready<()>> (PtrToPtr); + StorageDead(_48); -+ StorageDead(_44); + StorageLive(_49); -+ _49 = discriminant(_43); -+ switchInt(move _49) -> [0: bb11, 1: bb12, otherwise: bb5]; ++ _49 = &mut ((*_47).0: &mut std::future::Ready<()>); ++ _45 = copy ((*_47).0: &mut std::future::Ready<()>); ++ StorageDead(_49); ++ StorageDead(_46); ++ _44 = &mut ((*_45).0: std::option::Option<()>); ++ StorageLive(_50); ++ _50 = Option::<()>::None; ++ _43 = copy ((*_45).0: std::option::Option<()>); ++ ((*_45).0: std::option::Option<()>) = copy _50; ++ StorageDead(_50); ++ StorageDead(_44); ++ StorageLive(_51); ++ _51 = discriminant(_43); ++ switchInt(move _51) -> [0: bb11, 1: bb12, otherwise: bb5]; } + + bb5: { @@ -309,17 +313,17 @@ + } + + bb11: { -+ _50 = option::expect_failed(const "`Ready` polled after completion") -> unwind unreachable; ++ _52 = option::expect_failed(const "`Ready` polled after completion") -> unwind unreachable; + } + + bb12: { + _42 = move ((_43 as Some).0: ()); -+ StorageDead(_49); ++ StorageDead(_51); + StorageDead(_43); + _18 = Poll::<()>::Ready(move _42); + StorageDead(_42); -+ StorageDead(_50); -+ StorageDead(_46); ++ StorageDead(_52); ++ StorageDead(_47); + StorageDead(_45); + StorageDead(_22); + StorageDead(_19); diff --git a/tests/mir-opt/inline_coroutine_body.run2-{closure#0}.Inline.panic-unwind.diff b/tests/mir-opt/inline_coroutine_body.run2-{closure#0}.Inline.panic-unwind.diff index 8b027e988b8e8..792f209f3b1e7 100644 --- a/tests/mir-opt/inline_coroutine_body.run2-{closure#0}.Inline.panic-unwind.diff +++ b/tests/mir-opt/inline_coroutine_body.run2-{closure#0}.Inline.panic-unwind.diff @@ -66,27 +66,25 @@ + let mut _47: &mut std::future::Ready<()>; + let mut _48: &mut std::pin::Pin<&mut std::future::Ready<()>>; + scope 14 (inlined > as DerefMut>::deref_mut) { -+ scope 15 (inlined Pin::<&mut std::future::Ready<()>>::as_mut) { -+ let mut _49: &mut &mut std::future::Ready<()>; -+ scope 16 (inlined Pin::<&mut std::future::Ready<()>>::new_unchecked) { ++ let mut _49: *mut std::pin::hidden::PinHelper<&mut std::future::Ready<()>>; ++ let mut _50: *mut std::pin::Pin<&mut std::future::Ready<()>>; ++ scope 15 (inlined > as DerefMut>::deref_mut) { ++ let mut _51: &mut &mut std::future::Ready<()>; ++ scope 16 (inlined <&mut std::future::Ready<()> as DerefMut>::deref_mut) { + } -+ scope 18 (inlined <&mut std::future::Ready<()> as DerefMut>::deref_mut) { -+ } -+ } -+ scope 17 (inlined Pin::<&mut std::future::Ready<()>>::get_mut) { + } + } -+ scope 19 (inlined Option::<()>::take) { -+ let mut _50: std::option::Option<()>; -+ scope 20 (inlined std::mem::replace::>) { -+ scope 21 { ++ scope 17 (inlined Option::<()>::take) { ++ let mut _52: std::option::Option<()>; ++ scope 18 (inlined std::mem::replace::>) { ++ scope 19 { + } + } + } -+ scope 22 (inlined #[track_caller] Option::<()>::expect) { -+ let mut _51: isize; -+ let mut _52: !; -+ scope 23 { ++ scope 20 (inlined #[track_caller] Option::<()>::expect) { ++ let mut _53: isize; ++ let mut _54: !; ++ scope 21 { + } + } + } @@ -244,26 +242,32 @@ + _22 = &mut (*_23); + StorageDead(_24); + StorageLive(_47); -+ StorageLive(_48); -+ StorageLive(_52); ++ StorageLive(_49); ++ StorageLive(_54); + StorageLive(_44); + StorageLive(_45); + StorageLive(_46); ++ StorageLive(_48); + _48 = &mut _19; -+ StorageLive(_49); -+ _49 = &mut (_19.0: &mut std::future::Ready<()>); -+ _47 = copy (_19.0: &mut std::future::Ready<()>); -+ StorageDead(_49); -+ _46 = &mut ((*_47).0: std::option::Option<()>); + StorageLive(_50); -+ _50 = Option::<()>::None; -+ _45 = copy ((*_47).0: std::option::Option<()>); -+ ((*_47).0: std::option::Option<()>) = copy _50; ++ _50 = &raw mut _19; ++ _49 = move _50 as *mut std::pin::hidden::PinHelper<&mut std::future::Ready<()>> (PtrToPtr); + StorageDead(_50); -+ StorageDead(_46); + StorageLive(_51); -+ _51 = discriminant(_45); -+ switchInt(move _51) -> [0: bb16, 1: bb17, otherwise: bb7]; ++ _51 = &mut ((*_49).0: &mut std::future::Ready<()>); ++ _47 = copy ((*_49).0: &mut std::future::Ready<()>); ++ StorageDead(_51); ++ StorageDead(_48); ++ _46 = &mut ((*_47).0: std::option::Option<()>); ++ StorageLive(_52); ++ _52 = Option::<()>::None; ++ _45 = copy ((*_47).0: std::option::Option<()>); ++ ((*_47).0: std::option::Option<()>) = copy _52; ++ StorageDead(_52); ++ StorageDead(_46); ++ StorageLive(_53); ++ _53 = discriminant(_45); ++ switchInt(move _53) -> [0: bb16, 1: bb17, otherwise: bb7]; } - bb6 (cleanup): { @@ -350,17 +354,17 @@ + } + + bb16: { -+ _52 = option::expect_failed(const "`Ready` polled after completion") -> bb11; ++ _54 = option::expect_failed(const "`Ready` polled after completion") -> bb11; + } + + bb17: { + _44 = move ((_45 as Some).0: ()); -+ StorageDead(_51); ++ StorageDead(_53); + StorageDead(_45); + _18 = Poll::<()>::Ready(move _44); + StorageDead(_44); -+ StorageDead(_52); -+ StorageDead(_48); ++ StorageDead(_54); ++ StorageDead(_49); + StorageDead(_47); + StorageDead(_22); + StorageDead(_19); diff --git a/tests/ui/deref/pin-deref.rs b/tests/ui/deref/pin-deref.rs new file mode 100644 index 0000000000000..175cd80ab1292 --- /dev/null +++ b/tests/ui/deref/pin-deref.rs @@ -0,0 +1,74 @@ +// The purpose of this file is to track the error messages from Pin and DerefMut interacting. + +//@ check-fail + +use std::ops::DerefMut; +use std::pin::Pin; + +struct MyUnpinType {} + +impl MyUnpinType { + fn at_self(&self) {} + fn at_mut_self(&mut self) {} +} + +struct MyPinType(core::marker::PhantomPinned); + +impl MyPinType { + fn at_self(&self) {} + fn at_mut_self(&mut self) {} +} + +fn call_mut_ref_unpin(mut r_unpin: Pin<&mut MyUnpinType>) { + r_unpin.at_self(); + r_unpin.at_mut_self(); +} + +fn call_ref_unpin(mut r_unpin: Pin<&MyUnpinType>) { + r_unpin.at_self(); + r_unpin.at_mut_self(); //~ ERROR: cannot borrow data in dereference of `Pin<&MyUnpinType>` as mutable +} + +fn call_mut_ref_pin(mut r_pin: Pin<&mut MyPinType>) { + r_pin.at_self(); + r_pin.at_mut_self(); //~ ERROR: cannot borrow data in dereference of `Pin<&mut MyPinType>` as mutable +} + +fn call_ref_pin(mut r_pin: Pin<&MyPinType>) { + r_pin.at_self(); + r_pin.at_mut_self(); //~ ERROR: cannot borrow data in dereference of `Pin<&MyPinType>` as mutable +} + +fn coerce_unpin_rr<'a>(mut r_unpin: &'a mut Pin<&MyUnpinType>) -> &'a MyUnpinType { + r_unpin +} + +fn coerce_unpin_rm<'a>(mut r_unpin: &'a mut Pin<&MyUnpinType>) -> &'a mut MyUnpinType { + r_unpin //~ ERROR: cannot borrow data in dereference of `Pin<&MyUnpinType>` as mutable +} + +fn coerce_unpin_mr<'a>(mut r_unpin: &'a mut Pin<&mut MyUnpinType>) -> &'a MyUnpinType { + r_unpin +} + +fn coerce_unpin_mm<'a>(mut r_unpin: &'a mut Pin<&mut MyUnpinType>) -> &'a mut MyUnpinType { + r_unpin +} + +fn coerce_pin_rr<'a>(mut r_pin: &'a mut Pin<&MyPinType>) -> &'a MyPinType { + r_pin +} + +fn coerce_pin_rm<'a>(mut r_pin: &'a mut Pin<&MyPinType>) -> &'a mut MyPinType { + r_pin //~ ERROR: cannot borrow data in dereference of `Pin<&MyPinType>` as mutable +} + +fn coerce_pin_mr<'a>(mut r_pin: &'a mut Pin<&mut MyPinType>) -> &'a MyPinType { + r_pin +} + +fn coerce_pin_mm<'a>(mut r_pin: &'a mut Pin<&mut MyPinType>) -> &'a mut MyPinType { + r_pin //~ ERROR: cannot borrow data in dereference of `Pin<&mut MyPinType>` as mutable +} + +fn main() {} diff --git a/tests/ui/deref/pin-deref.stderr b/tests/ui/deref/pin-deref.stderr new file mode 100644 index 0000000000000..4fb056e5643c9 --- /dev/null +++ b/tests/ui/deref/pin-deref.stderr @@ -0,0 +1,51 @@ +error[E0596]: cannot borrow data in dereference of `Pin<&MyUnpinType>` as mutable + --> $DIR/pin-deref.rs:29:5 + | +LL | r_unpin.at_mut_self(); + | ^^^^^^^ cannot borrow as mutable + | + = help: trait `DerefMut` is required to modify through a dereference, but it is not implemented for `Pin<&MyUnpinType>` + +error[E0596]: cannot borrow data in dereference of `Pin<&mut MyPinType>` as mutable + --> $DIR/pin-deref.rs:34:5 + | +LL | r_pin.at_mut_self(); + | ^^^^^ cannot borrow as mutable + | + = help: trait `DerefMut` is required to modify through a dereference, but it is not implemented for `Pin<&mut MyPinType>` + +error[E0596]: cannot borrow data in dereference of `Pin<&MyPinType>` as mutable + --> $DIR/pin-deref.rs:39:5 + | +LL | r_pin.at_mut_self(); + | ^^^^^ cannot borrow as mutable + | + = help: trait `DerefMut` is required to modify through a dereference, but it is not implemented for `Pin<&MyPinType>` + +error[E0596]: cannot borrow data in dereference of `Pin<&MyUnpinType>` as mutable + --> $DIR/pin-deref.rs:47:5 + | +LL | r_unpin + | ^^^^^^^ cannot borrow as mutable + | + = help: trait `DerefMut` is required to modify through a dereference, but it is not implemented for `Pin<&MyUnpinType>` + +error[E0596]: cannot borrow data in dereference of `Pin<&MyPinType>` as mutable + --> $DIR/pin-deref.rs:63:5 + | +LL | r_pin + | ^^^^^ cannot borrow as mutable + | + = help: trait `DerefMut` is required to modify through a dereference, but it is not implemented for `Pin<&MyPinType>` + +error[E0596]: cannot borrow data in dereference of `Pin<&mut MyPinType>` as mutable + --> $DIR/pin-deref.rs:71:5 + | +LL | r_pin + | ^^^^^ cannot borrow as mutable + | + = help: trait `DerefMut` is required to modify through a dereference, but it is not implemented for `Pin<&mut MyPinType>` + +error: aborting due to 6 previous errors + +For more information about this error, try `rustc --explain E0596`. diff --git a/tests/ui/deref/pin-impl-deref.rs b/tests/ui/deref/pin-impl-deref.rs new file mode 100644 index 0000000000000..d09c551794ee4 --- /dev/null +++ b/tests/ui/deref/pin-impl-deref.rs @@ -0,0 +1,40 @@ +// The purpose of this file is to track the error messages from Pin and DerefMut interacting. + +//@ check-fail + +use std::ops::DerefMut; +use std::pin::Pin; + +struct MyUnpinType {} + +impl MyUnpinType { + fn at_self(&self) {} + fn at_mut_self(&mut self) {} +} + +struct MyPinType(core::marker::PhantomPinned); + +impl MyPinType { + fn at_self(&self) {} + fn at_mut_self(&mut self) {} +} + +fn impl_deref_mut(_: impl DerefMut) {} +fn unpin_impl_ref(r_unpin: Pin<&MyUnpinType>) { + impl_deref_mut(r_unpin) + //~^ ERROR: the trait bound `pin::hidden::PinHelper<&MyUnpinType>: DerefMut` is not satisfied +} +fn unpin_impl_mut(r_unpin: Pin<&mut MyUnpinType>) { + impl_deref_mut(r_unpin) +} +fn pin_impl_ref(r_pin: Pin<&MyPinType>) { + impl_deref_mut(r_pin) + //~^ ERROR: `PhantomPinned` cannot be unpinned + //~| ERROR: the trait bound `pin::hidden::PinHelper<&MyPinType>: DerefMut` is not satisfied +} +fn pin_impl_mut(r_pin: Pin<&mut MyPinType>) { + impl_deref_mut(r_pin) + //~^ ERROR: `PhantomPinned` cannot be unpinned +} + +fn main() {} diff --git a/tests/ui/deref/pin-impl-deref.stderr b/tests/ui/deref/pin-impl-deref.stderr new file mode 100644 index 0000000000000..c40f9527356de --- /dev/null +++ b/tests/ui/deref/pin-impl-deref.stderr @@ -0,0 +1,93 @@ +error[E0277]: the trait bound `pin::hidden::PinHelper<&MyUnpinType>: DerefMut` is not satisfied + --> $DIR/pin-impl-deref.rs:24:20 + | +LL | impl_deref_mut(r_unpin) + | -------------- ^^^^^^^ the trait `DerefMut` is not implemented for `pin::hidden::PinHelper<&MyUnpinType>` + | | + | required by a bound introduced by this call + | + = note: required for `pin::hidden::PinHelper<&MyUnpinType>` to implement `DerefMut` + = note: 1 redundant requirement hidden + = note: required for `Pin<&MyUnpinType>` to implement `DerefMut` +note: required by a bound in `impl_deref_mut` + --> $DIR/pin-impl-deref.rs:22:27 + | +LL | fn impl_deref_mut(_: impl DerefMut) {} + | ^^^^^^^^ required by this bound in `impl_deref_mut` +help: consider mutably borrowing here + | +LL | impl_deref_mut(&mut r_unpin) + | ++++ + +error[E0277]: the trait bound `pin::hidden::PinHelper<&MyPinType>: DerefMut` is not satisfied + --> $DIR/pin-impl-deref.rs:31:20 + | +LL | impl_deref_mut(r_pin) + | -------------- ^^^^^ the trait `DerefMut` is not implemented for `pin::hidden::PinHelper<&MyPinType>` + | | + | required by a bound introduced by this call + | + = note: required for `pin::hidden::PinHelper<&MyPinType>` to implement `DerefMut` + = note: 1 redundant requirement hidden + = note: required for `Pin<&MyPinType>` to implement `DerefMut` +note: required by a bound in `impl_deref_mut` + --> $DIR/pin-impl-deref.rs:22:27 + | +LL | fn impl_deref_mut(_: impl DerefMut) {} + | ^^^^^^^^ required by this bound in `impl_deref_mut` +help: consider mutably borrowing here + | +LL | impl_deref_mut(&mut r_pin) + | ++++ + +error[E0277]: `PhantomPinned` cannot be unpinned + --> $DIR/pin-impl-deref.rs:31:20 + | +LL | impl_deref_mut(r_pin) + | -------------- ^^^^^ within `MyPinType`, the trait `Unpin` is not implemented for `PhantomPinned` + | | + | required by a bound introduced by this call + | + = note: consider using the `pin!` macro + consider using `Box::pin` if you need to access the pinned value outside of the current scope +note: required because it appears within the type `MyPinType` + --> $DIR/pin-impl-deref.rs:15:8 + | +LL | struct MyPinType(core::marker::PhantomPinned); + | ^^^^^^^^^ + = note: required for `pin::hidden::PinHelper<&MyPinType>` to implement `DerefMut` + = note: 1 redundant requirement hidden + = note: required for `Pin<&MyPinType>` to implement `DerefMut` +note: required by a bound in `impl_deref_mut` + --> $DIR/pin-impl-deref.rs:22:27 + | +LL | fn impl_deref_mut(_: impl DerefMut) {} + | ^^^^^^^^ required by this bound in `impl_deref_mut` + +error[E0277]: `PhantomPinned` cannot be unpinned + --> $DIR/pin-impl-deref.rs:36:20 + | +LL | impl_deref_mut(r_pin) + | -------------- ^^^^^ within `MyPinType`, the trait `Unpin` is not implemented for `PhantomPinned` + | | + | required by a bound introduced by this call + | + = note: consider using the `pin!` macro + consider using `Box::pin` if you need to access the pinned value outside of the current scope +note: required because it appears within the type `MyPinType` + --> $DIR/pin-impl-deref.rs:15:8 + | +LL | struct MyPinType(core::marker::PhantomPinned); + | ^^^^^^^^^ + = note: required for `pin::hidden::PinHelper<&mut MyPinType>` to implement `DerefMut` + = note: 1 redundant requirement hidden + = note: required for `Pin<&mut MyPinType>` to implement `DerefMut` +note: required by a bound in `impl_deref_mut` + --> $DIR/pin-impl-deref.rs:22:27 + | +LL | fn impl_deref_mut(_: impl DerefMut) {} + | ^^^^^^^^ required by this bound in `impl_deref_mut` + +error: aborting due to 4 previous errors + +For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/typeck/pin-unsound-issue-85099-derefmut.rs b/tests/ui/typeck/pin-unsound-issue-85099-derefmut.rs index f3ece563f5403..e8c3bbba1e458 100644 --- a/tests/ui/typeck/pin-unsound-issue-85099-derefmut.rs +++ b/tests/ui/typeck/pin-unsound-issue-85099-derefmut.rs @@ -1,5 +1,4 @@ -//@ check-pass -//@ known-bug: #85099 +//@ check-fail // Should fail. Can coerce `Pin` into `Pin` where // `T: Deref` and `U: Deref`, using the @@ -43,6 +42,7 @@ impl<'a, Fut: Future> SomeTrait<'a, Fut> for Fut { } impl<'b, 'a, Fut> DerefMut for Pin<&'b dyn SomeTrait<'a, Fut>> { +//~^ ERROR: conflicting implementations of trait `DerefMut` fn deref_mut<'c>( self: &'c mut Pin<&'b dyn SomeTrait<'a, Fut>>, ) -> &'c mut (dyn SomeTrait<'a, Fut> + 'b) { diff --git a/tests/ui/typeck/pin-unsound-issue-85099-derefmut.stderr b/tests/ui/typeck/pin-unsound-issue-85099-derefmut.stderr new file mode 100644 index 0000000000000..455ac0eebeec6 --- /dev/null +++ b/tests/ui/typeck/pin-unsound-issue-85099-derefmut.stderr @@ -0,0 +1,14 @@ +error[E0119]: conflicting implementations of trait `DerefMut` for type `Pin<&dyn SomeTrait<'_, _>>` + --> $DIR/pin-unsound-issue-85099-derefmut.rs:44:1 + | +LL | impl<'b, 'a, Fut> DerefMut for Pin<&'b dyn SomeTrait<'a, Fut>> { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: conflicting implementation in crate `core`: + - impl DerefMut for Pin + where as Deref>::Target == as Deref>::Target, Ptr: Deref, pin::hidden::PinHelper: DerefMut, pin::hidden::PinHelper: ?Sized; + = note: upstream crates may add a new impl of trait `std::ops::DerefMut` for type `std::pin::hidden::PinHelper<&dyn SomeTrait<'_, _>>` in future versions + +error: aborting due to 1 previous error + +For more information about this error, try `rustc --explain E0119`.