diff options
| author | Jacob Pratt <jacob@jhpratt.dev> | 2024-05-13 21:14:16 -0400 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2024-05-13 21:14:16 -0400 |
| commit | 209703af853eed8abfc4dfce54aa7f38273fcf6d (patch) | |
| tree | d449a6dd994c684462dd58928c59e83e3ca47b85 | |
| parent | 18d9c039bb83483c5b1bfec2ebc333d0462c508d (diff) | |
| parent | b3a78c1d094eb978ec876643c3c4d0e5349b1073 (diff) | |
Rollup merge of #125072 - Darksonn:pin-dyn-dispatch-sound, r=jhpratt
Add test for dynamic dispatch + Pin::new soundness While working on [the `#[derive(SmartPointer)]` RFC][1], I realized that the soundness of <code>impl [DispatchFromDyn](https://doc.rust-lang.org/stable/std/ops/trait.DispatchFromDyn.html) for [Pin](https://doc.rust-lang.org/stable/std/pin/struct.Pin.html)</code> relies on the restriction that you can't implement [`Unpin`](https://doc.rust-lang.org/stable/std/marker/trait.Unpin.html) for trait objects. As far as I can tell, the relevant error exists to solve some unrelated issues with coherence. To avoid cases where `Pin` is made unsound due to changes in the coherence-related errors, add a test that verifies that unsound use of `Pin` and `DispatchFromDyn` does not become allowed in the future. [1]: https://github.com/rust-lang/rfcs/pull/3621
| -rw-r--r-- | tests/ui/coercion/pin-dyn-dispatch-sound.rs | 19 | ||||
| -rw-r--r-- | tests/ui/coercion/pin-dyn-dispatch-sound.stderr | 9 |
2 files changed, 28 insertions, 0 deletions
diff --git a/tests/ui/coercion/pin-dyn-dispatch-sound.rs b/tests/ui/coercion/pin-dyn-dispatch-sound.rs new file mode 100644 index 00000000000..b9d43ebac8b --- /dev/null +++ b/tests/ui/coercion/pin-dyn-dispatch-sound.rs @@ -0,0 +1,19 @@ +use std::marker::PhantomPinned; +use std::pin::Pin; + +trait MyUnpinTrait { + fn into_pinned_type(self: Pin<&mut Self>) -> Pin<&mut PhantomPinned>; +} +impl MyUnpinTrait for PhantomPinned { + fn into_pinned_type(self: Pin<&mut Self>) -> Pin<&mut PhantomPinned> { + self + } +} +impl Unpin for dyn MyUnpinTrait {} //~ ERROR E0321 + +// It would be unsound for this function to compile. +fn pin_it(not_yet_pinned: &mut PhantomPinned) -> Pin<&mut PhantomPinned> { + Pin::new(not_yet_pinned as &mut dyn MyUnpinTrait).into_pinned_type() +} + +fn main() {} diff --git a/tests/ui/coercion/pin-dyn-dispatch-sound.stderr b/tests/ui/coercion/pin-dyn-dispatch-sound.stderr new file mode 100644 index 00000000000..45860bfcfc7 --- /dev/null +++ b/tests/ui/coercion/pin-dyn-dispatch-sound.stderr @@ -0,0 +1,9 @@ +error[E0321]: cross-crate traits with a default impl, like `Unpin`, can only be implemented for a struct/enum type, not `(dyn MyUnpinTrait + 'static)` + --> $DIR/pin-dyn-dispatch-sound.rs:12:1 + | +LL | impl Unpin for dyn MyUnpinTrait {} + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ can't implement cross-crate trait with a default impl for non-struct/enum type + +error: aborting due to 1 previous error + +For more information about this error, try `rustc --explain E0321`. |
