Description
The source below does not compile, where the expected behavior is for it to compile as far as I can tell. Removing the Send
bound on drop_send
causes it to compile. Removing the async {}.await
no-op causes it to compile. This seems likely related to #64552, with the same sort of leakage of regions that should not be user-visible occurring. However, the error message is quite opaque in this case.
note: `Bound` would have to be implemented for the type `(dyn Object + '0)`, for any lifetime `'0`...
= note: ...but `Bound` is actually implemented for the type `(dyn Object + '1)`, for some specific lifetime `'1`
My presumption is therefore that the auto trait is being correctly satisfied in the generator for some lifetime, the implementation of Bound
is implicitly constrained on Send
by Object
where the async block is required to be Send
, so #64552 is occurring in a lifetime-dependent fashion resulting in an altogether surprising error message. I'm not as familiar with borrow checker internals as I'd like so this may be barking up the wrong tree.
I am, however, unclear as to why the associated type parametrization over T::Type
as opposed to simply T
is necessary to reproduce.
use std::marker::PhantomData;
// remove this Send bound and it compiles
fn drop_send<F: Send>(_: F) {}
trait Object: Send {}
pub trait Bound {
type Type;
}
impl Bound for dyn Object {
type Type = ();
}
trait Contains<T> {}
struct IsBound<T: Bound + ?Sized>(PhantomData<dyn Contains<T::Type> + Send>);
impl<T: Bound + ?Sized> IsBound<T> {
pub fn new() -> Self {
IsBound(PhantomData)
}
}
fn fails() {
drop_send(async {
let collection: IsBound<dyn Object> = IsBound::new();
// comment out this no-op and it builds:
async {}.await;
})
}
Finally, here is a playground demonstrating this issue to show independence from any local state of my own system