Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Provided method casting &self to trait object

Tags:

I have a trait in which I want to provide a method. The method is to be implemented in terms of some helpers that have no business being inside the trait and are non-trivial enough that dynamic polymorphism makes more sense than making them generic. So I have code along the lines of

fn use_trait(x: &Trait) {
    println!("object says {}", x.needed());
}

trait Trait {
    fn needed(&self) -> &str;

    fn provided(&self) {
        use_trait(self);
    }
}

struct Struct();

impl Trait for Struct {
    fn needed(&self) -> &str {
        "Hello, world!"
    }
}

fn main() {
    Struct().provided();
}

Which, however, does not compile, with error:

error[E0277]: the trait bound `Self: std::marker::Sized` is not satisfied
 --> <anon>:9:19
  |
9 |         use_trait(self);
  |                   ^^^^ the trait `std::marker::Sized` is not implemented for `Self`
  |
  = help: consider adding a `where Self: std::marker::Sized` bound
  = note: required for the cast to the object type `Trait`

I understand why—it is not guaranteed somebody won't implement the trait for an unsized type (converting from &T where T: Trait to &Trait requires T: Sized, but the declaration does not require that).

However, the advice will not do what I need. I can add

fn needed(&self) -> &str where Self: Sized

but then the needed() method won't be accessible on &Trait (because Trait : ?Sized), which renders the thing useless, because the type (the actual one that does something useful) is always handled as Arc<Trait>. And adding

trait Trait: Sized

is even worse, because that does not permit &Trait at all (Trait as a type is unsized, so Trait type does not implement trait Trait).

Of course I can simply make

fn use_trait<T: Trait>(x: &T)

but there is a lot behind it in the real code, so I don't want monomorphisation there especially since the trait is otherwise always handled as trait object.

Is there any way to tell Rust that all types that impl Trait must be sized and here is a definition of a method that should work for all of them?