Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Define a method in trait returning a default implementation of Self

Tags:

rust

traits

I would like to have the following functionality

trait Policy {
    fn eval(&self, k: u32) -> bool;

    fn default() -> Box<dyn Policy>
    where
        Self: Sized,
    {
        Box::new(MaxPolicy { max: 2 })
    }
}

struct MaxPolicy {
    max: u32,
}

impl Policy for MaxPolicy {
    fn eval(&self, k: u32) -> bool {
        println!("MaxPolicy");
        k < self.max
    }
}

#[test]
fn max_policy() {
    let p = MaxPolicy { max: 2 };
    assert!(!p.eval(3));
}

#[test]
fn default_policy() {
    let p = Policy::default();
    assert!(!p.eval(3));
}

(Playground)

This does not compile:

error[E0283]: type annotations needed
  --> src/lib.rs:31:13
   |
4  |     fn default() -> Box<dyn Policy>
   |        -------
5  |     where
6  |         Self: Sized,
   |               ----- required by this bound in `Policy::default`
...
31 |     let p = Policy::default();
   |             ^^^^^^^^^^^^^^^ cannot infer type
   |
   = note: cannot resolve `_: Policy`

Would it possible to alter the approach to make it work? Is this even possible for trait objects to have a method returning some implementation of Self? If not, why not?

like image 395
Victor Ermolaev Avatar asked Oct 19 '25 14:10

Victor Ermolaev


1 Answers

Implement default on the trait object type, not on the trait:

trait Policy {
    fn eval(&self, k: u32) -> bool;
}

impl dyn Policy {
    fn default() -> Box<Self> {
        Box::new(MaxPolicy { max: 2 })
    }
}

See also:

  • Why would I implement methods on a trait instead of as part of the trait?
like image 198
Shepmaster Avatar answered Oct 21 '25 03:10

Shepmaster