Closed
Description
Description
Getting warning #[warn(where_clauses_object_safety)]
when adding default implementation for async_trait
Sample Case
use tokio::time;
#[async_trait::async_trait]
trait Waiter {
async fn wait_inner_sec(&self, name: &str);
}
struct Walker {
inner: u64,
}
impl Walker {
fn new(inner: u64) -> Self { Self { inner } }
}
#[async_trait::async_trait]
impl Waiter for Walker {
async fn wait_inner_sec(&self, name: &str) {
println!("waiting for: {}", name);
time::sleep(time::Duration::new(self.inner, 0)).await
}
}
#[tokio::main]
async fn main() {
let walker = Walker::new(1);
let dyn_walker: Box<&(dyn Waiter)> = Box::new(&walker);
dyn_walker.wait_inner_sec("plane").await;
}
This example works properly and there is no issue with object-safety here!
Now, if I add a default implementation for the trait
#[async_trait::async_trait]
trait Waiter {
async fn wait_inner_sec(&self, name: &str) {
println!("waiting for: {}", name);
time::sleep(time::Duration::new(5, 0)).await
}
}
After this change, I suddenly get 1 warning and 1 error.
The Error
error[E0277]: `dyn Waiter` cannot be shared between threads safely
--> src/main.rs:31:5
|
31 | dyn_walker.wait_inner_sec("plane").await;
| ^^^^^^^^^^ -------------- required by a bound introduced by this call
| |
| `dyn Waiter` cannot be shared between threads safely
|
= help: the trait `Sync` is not implemented for `dyn Waiter`
note: required by a bound in `Waiter::wait_inner_sec`
--> src/main.rs:5:5
|
5 | async fn wait_inner_sec(&self, name: &str) {
| ^^^^^ required by this bound in `Waiter::wait_inner_sec`
This can be solved with
- let dyn_walker: Box<&(dyn Waiter)> = Box::new(&walker);
+ let dyn_walker: Box<&(dyn Waiter + Sync)> = Box::new(&walker);
The Warning
warning: the trait `Waiter` cannot be made into an object
--> src/main.rs:5:14
|
5 | async fn wait_inner_sec(&self, name: &str) {
| ^^^^^^^^^^^^^^
|
= warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
= note: for more information, see issue #51443 <https://github.com/rust-lang/rust/issues/51443>
note: for a trait to be "object safe" it needs to allow building a vtable to allow the call to be resolvable dynamically; for more information visit <https://doc.rust-lang.org/reference/items/traits.html#object-safety>
--> src/main.rs:5:14
|
4 | trait Waiter {
| ------ this trait cannot be made into an object...
5 | async fn wait_inner_sec(&self, name: &str) {
| ^^^^^^^^^^^^^^ ...because method `wait_inner_sec` references the `Self` type in its `where` clause
= help: consider moving `wait_inner_sec` to another trait
= note: `#[warn(where_clauses_object_safety)]` on by default
- The warning doesn't provide the whole context
- In my implementation I haven't used any where clause.
- After expanding the macro turns out the function has a where clause, where self is referenced
Self: Sync
- This problem can be solved by
trait Waiter: Sync
, but should this warning even occur?
Metadata
Metadata
Assignees
Labels
No labels