async-trait
async-trait copied to clipboard
Using `type` in async trait will cause some problems?
Hi, me again. I found using type in trait will cause some problems...
- mismatched types
- cannot infer an appropriate lifetime for lifetime parameter
'adue to conflicting requirements
extern crate async_trait;
use async_trait::async_trait;
use futures::executor::block_on;
#[async_trait]
pub trait State<'a> {
type Command: 'a + Send;
async fn add_comm(mut self, more_str: Self::Command) -> Self where Self: Sized;
async fn add_more_comm(mut self, str1: Self::Command, str2: Self::Command) -> Self where Self: Sized {
let self1 = self.add_comm(str1).await;
let self2 = self1.add_comm(str2).await;
self2
}
}
#[derive(Debug)]
pub struct RealState(String);
#[async_trait]
impl <'a> State<'a> for RealState {
type Command = String;
async fn add_comm(mut self, more_str: Self::Command) -> Self {
self.0 = self.0.clone() + more_str.as_ref();
self
}
}
fn main() {
let state = RealState(Default::default());
let state1 = block_on(state.add_more_str("hello", " world"));
println!("{:?}", state1);
}
Error:
error[E0308]: mismatched types
--> src/lifetime-error.rs:6:1
|
6 | #[async_trait]
| ^^^^^^^^^^^^^^ one type is more general than the other
|
= note: expected type `std::marker::Send`
found type `std::marker::Send`
error[E0495]: cannot infer an appropriate lifetime for lifetime parameter `'a` due to conflicting requirements
--> src/lifetime-error.rs:6:1
|
6 | #[async_trait]
| ^^^^^^^^^^^^^^
|
note: first, the lifetime cannot outlive the lifetime 'a as defined on the trait at 7:17...
--> src/lifetime-error.rs:7:17
|
7 | pub trait State<'a> {
| ^^
= note: ...so that the expression is assignable:
expected <Self as State<'_>>::Command
found <Self as State<'a>>::Command
note: but, the lifetime must be valid for the lifetime 'async_trait as defined on the method body at 6:1...
--> src/lifetime-error.rs:6:1
|
6 | #[async_trait]
| ^^^^^^^^^^^^^^
= note: ...so that the expression is assignable:
expected std::pin::Pin<std::boxed::Box<(dyn core::future::future::Future<Output = Self> + std::marker::Send + 'async_trait)>>
found std::pin::Pin<std::boxed::Box<dyn core::future::future::Future<Output = Self> + std::marker::Send>>
This is a compiler bug. :cry: https://github.com/rust-lang/rust/issues/60658
I've run in to one type is more general than the other with the same types as well.
| |_____^ one type is more general than the other
|
= note: expected type `FnOnce<(&Model,)>`
found type `FnOnce<(&Model,)>`
This error only happens when the function call is in, or downstream of, an async_trait fn impl. There is no error when calling from outside an async_trait context.
I'm trying to figure out if this is the same issue or a different one? I've widdled down this repro (playground). The buffer_unordered() stream wrapper seems to trigger the issue. Calling the working function in build compiles.
Closing in favor of https://github.com/rust-lang/rust/issues/60658, since this is not going to be actionable in async-trait. We can reopen in the event that the rustc bug gets fixed in a way that doesn't immediately solve this.