Search code examples
rustassociated-typesdynamic-dispatchtrait-objects

"associated type ... must be specified", but isn't used


Why is the associated type required here, even though it's never used?

trait Tr {
    type Ty;
    fn go(&self) -> () {}
}

fn foo(t: dyn Tr) -> () {
    t.go()
}

I get

2 |   type Ty;   
  |   -------- `Ty` defined here   
...  
6 | fn foo(t: dyn Tr) -> () {  
  |           ^^^^^^ associated type `Ty` must be specified

Solution

  • You are making a trait object, and it is a requirement for trait objects that all associated types are specified. Your case is very simple and the methods of the trait do not use the associated type, but the object safety rules are designed for the more general case.

    If you were just using a type parameter, bound by Tr, you wouldn't need to specify the associated type:

    fn foo<T: Tr>(t: T) -> () {
        t.go()
    }
    

    That's because the associated type can be inferred for each T that you call foo with.

    If trait objects were allowed to have an unspecified associated type then code inside the function would not be able to infer it. You could argue in this case, that this should just limit what the function is allowed to do, but the object safety rules are given for the definition of a trait object type, regardless of how it is actually used. This makes is simpler to think about because there aren't some situations where a trait object can be used and others where it can't.


    As an aside, even if you specified the associated types for the object in your function signature, you would have to pass the object by reference or boxed, e.g.:

    fn foo(t: &dyn Tr<Ty = SomeType>) -> () {
        t.go()
    }
    

    That's because trait objects do not have a size known at compile-time. Instead you need to put them behind a reference, which does have a known size.