diff --git a/tests/ui/async-await/higher-ranked-auto-trait-18.no_assumptions.stderr b/tests/ui/async-await/higher-ranked-auto-trait-18.no_assumptions.stderr new file mode 100644 index 0000000000000..5a4c99acd0d43 --- /dev/null +++ b/tests/ui/async-await/higher-ranked-auto-trait-18.no_assumptions.stderr @@ -0,0 +1,13 @@ +error: higher-ranked lifetime error + --> $DIR/higher-ranked-auto-trait-18.rs:69:5 + | +LL | / require_send(async { +LL | | let r = Receiver::> { _value: None, _not_sync: PhantomData }; +LL | | let _ = r.await; +LL | | }); + | |______^ + | + = note: could not prove `{async block@$DIR/higher-ranked-auto-trait-18.rs:69:18: 69:23}: Send` + +error: aborting due to 1 previous error + diff --git a/tests/ui/async-await/higher-ranked-auto-trait-18.rs b/tests/ui/async-await/higher-ranked-auto-trait-18.rs new file mode 100644 index 0000000000000..3839fd86cfeba --- /dev/null +++ b/tests/ui/async-await/higher-ranked-auto-trait-18.rs @@ -0,0 +1,79 @@ +// Repro for a bug where `PhantomData<*mut ()>` + `unsafe impl Send` fails to prove +// `Send` for an async block when the type parameter is a trait object (`dyn Trait`). +// +// The static assertion `assert_send::>>()` succeeds, +// but the same type captured across an `.await` in an async block does not. +// This is because MIR erases the `'static` lifetime from `dyn MyTrait + 'static`, +// and the auto-trait analysis cannot recover the `T: 'static` bound without +// higher-ranked assumptions. +// +// Using `PhantomData>` instead of `PhantomData<*mut ()>` avoids the +// issue because `Cell<()>` is natively `Send`, so no `unsafe impl` (with its +// `T: 'static` bound) is needed. +// +// See . +//@ edition: 2021 +//@ revisions: assumptions no_assumptions +//@[assumptions] compile-flags: -Zhigher-ranked-assumptions +//@[assumptions] check-pass +//@[no_assumptions] known-bug: #110338 + +use std::cell::Cell; +use std::future::Future; +use std::marker::PhantomData; +use std::pin::Pin; +use std::task::{Context, Poll}; + +// --- PhantomData<*mut ()> version: needs `unsafe impl Send` --- + +struct Receiver { + _value: Option, + _not_sync: PhantomData<*mut ()>, +} + +unsafe impl Send for Receiver {} + +impl Future for Receiver { + type Output = T; + fn poll(self: Pin<&mut Self>, _cx: &mut Context<'_>) -> Poll { + Poll::Pending + } +} + +// --- PhantomData> version: auto-derived Send works --- + +struct ReceiverCell { + _value: Option, + _not_sync: PhantomData>, +} + +impl Future for ReceiverCell { + type Output = T; + fn poll(self: Pin<&mut Self>, _cx: &mut Context<'_>) -> Poll { + Poll::Pending + } +} + +trait MyTrait: Send {} + +fn require_send(_f: F) {} + +fn main() { + // PhantomData<*mut ()> + concrete type: always works. + require_send(async { + let r = Receiver:: { _value: None, _not_sync: PhantomData }; + let _ = r.await; + }); + + // PhantomData<*mut ()> + dyn Trait: fails without higher-ranked assumptions. + require_send(async { + let r = Receiver::> { _value: None, _not_sync: PhantomData }; + let _ = r.await; + }); + + // PhantomData> + dyn Trait: always works (auto-derived Send). + require_send(async { + let r = ReceiverCell::> { _value: None, _not_sync: PhantomData }; + let _ = r.await; + }); +}