use async_trait::async_trait;
use tokio::{self, spawn};
#[async_trait]
pub trait Consumer {
async fn consume(&self);
}
pub struct DefaultConsumer;
#[async_trait]
impl Consumer for DefaultConsumer {
async fn consume(&self) {
println!("hello consumer!");
}
}
struct Test {
inner: Box<dyn Consumer + Send>,
}
impl Test {
async fn run(mut self) {
let f = self.level1();
f.await;
}
async fn level1(&mut self) {
let f = self.level2();
f.await;
}
async fn level2(&self) { // OK if change to `&mut self`
}
}
#[tokio::main]
async fn main() {
let mut t = Test {
inner: Box::new(DefaultConsumer),
};
spawn(async move {
let f = t.run();
f.await;
});
}
Is the question essentially "why can we call &self
method on &mut self
"?
Why wouldn't it work? What did you expect instead?
1 Like
Because Test
is not Sync
. And for some T
which is !Sync
, &T
is !Send
but &mut T
is Send
.
With sending &T
to another thread, since &T
is Copy
as well, you can effectively access T
from two different thread at the same time, with violates T: !Sync
. But you cannot copy &mut T
, which is unique, so it doesn't violate T: !Sync
.
2 Likes
This topic was automatically closed 90 days after the last reply. We invite you to open a new topic if you have further questions or comments.