I have this code (playground):
use std::sync::Arc;
pub trait Messenger : Sync + Send {
fn send_embed<F: FnOnce(String) -> String>(&self, u64, &str, f: F)
-> Option<u64> where Self: Sync + Send;
}
struct MyMessenger {
prefix: String,
}
impl MyMessenger {
fn new(s: &str) -> MyMessenger {
MyMessenger { prefix: s.to_owned(), }
}
}
impl Messenger for MyMessenger {
fn send_embed<F: FnOnce(String) -> String>(&self, channel_id: u64, text: &str, f: F) -> Option<u64> {
println!("Trying to send embed: chid={}, text=\"{}\"", channel_id, text);
None
}
}
struct Bot {
messenger: Arc<Messenger>,
}
impl Bot {
fn new() -> Bot {
Bot {
messenger: Arc::new(MyMessenger::new("HELLO")),
}
}
}
fn main() {
let b = Bot::new();
}
I wanted to make a polymorphic object (trait Messenger
and one of polymorphic implementations is MyMessenger
). But when I try to compile it I have an error:
error[E0038]: the trait `Messenger` cannot be made into an object
--> <anon>:25:5
|
25 | messenger: Arc<Messenger>,
| ^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `Messenger` cannot be made into an object
|
= note: method `send_embed` has generic type parameters
I have found that I must require Sized
in this case, but this does not solve it. If I change my send_embed
method to the following:
fn send_embed<F: FnOnce(String) -> String>(&self, u64, &str, f: F)
-> Option<u64> where Self: Sized + Sync + Send;
Then it compiles successfully but:
- Why do we need
Sized
here? This violates polymorphism if we can not use this method from a trait object. We actually can't use this method from
Arc<Messenger>
then:fn main() { let b = Bot::new(); b.messenger.send_embed(0u64, "ABRACADABRA", |s| s); }
Gives:
error[E0277]: the trait bound `Messenger + 'static: std::marker::Sized` is not satisfied --> <anon>:37:17 | 37 | b.messenger.send_embed(0u64, "ABRACADABRA", |s| s); | ^^^^^^^^^^ the trait `std::marker::Sized` is not implemented for `Messenger + 'static` | = note: `Messenger + 'static` does not have a constant size known at compile-time
I am totally stuck here. No idea how to use polymorphism with generic method in a trait. Is there a way?