Description
edit/summary by @lcnr
This is a regression caused by the unsoundness fix in #124336 which causes uses of impls to now have to prove the outlives bounds of the trait. In this case, this requires proving the 'static
bound of Role
whenever we're using an impl.
We expected that this only causes unintended breakage due to higher ranked goals. However, this can also trigger #110338. This is a general issue with the way generator interiors are handled. We deeply care about fixing this issue and doing so should cause this pattern to compile again.
Until then, we believe the fallout to be minor enough for this to be acceptable. For this to trigger we need to
- prove an auto trait bound for a generator
- the generator contains a field for which proving the auto trait bound requires using an impl of a trait with a region bound
- this either requires an impl like
impl<T: Role> Send for MyType<T>
or a field whose normalization requires proving the trait
Code
I tried this (reduced) code:
use tokio::sync::mpsc::{unbounded_channel,UnboundedSender};
pub trait Role: 'static + Sync + Send {
type Return : Send;
}
pub trait BasicRole: 'static + Send + Sync {}
impl Role for dyn BasicRole + '_ {
type Return = ();
}
pub struct ReturnEnvelope<R: Role + ?Sized> {
pub return_path: Option<R::Return>,
}
pub fn start() {
let (_basic_role_input, mut basic_role_output): (UnboundedSender<ReturnEnvelope<dyn BasicRole>>, _) = unbounded_channel();
let event_loop = async move {
let _ = basic_role_output.recv().await;
};
let _ = ::tokio::task::spawn(event_loop);
}
I expected to see this happen: successful compile.
Instead, this happened: I received this error:
error: implementation of `Role` is not general enough
--> src/lib.rs:22:13
|
22 | let _ = ::tokio::task::spawn(event_loop);
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ implementation of `Role` is not general enough
|
= note: `Role` would have to be implemented for the type `(dyn BasicRole + '0)`, for any lifetime `'0`...
= note: ...but `Role` is actually implemented for the type `(dyn BasicRole + '1)`, for some specific lifetime `'1`
This can also be seen on the playground configured to use nightly.
I am aware that handling this construct correctly seems to be an outstanding issue, I'm specifically reporting the inconsistency that it does work on stable and not nightly.
Version it worked on
It most recently worked on: 1.81.0 stable (most recent)
Version with regression
rustc --version --verbose
:
rustc 1.83.0-nightly (eb4e23467 2024-10-09)
binary: rustc
commit-hash: eb4e2346748e1760f74fcaa27b42431e0b95f8f3
commit-date: 2024-10-09
host: x86_64-pc-windows-msvc
release: 1.83.0-nightly
LLVM version: 19.1.1
However, this has been an issue since at least the 2024-08-17 nightly (feeba19)
@rustbot modify labels: +regression-from-stable-to-nightly -regression-untriaged