Chained type parameters marked as never used

Consider a code like this (of course, this is an extremely simplified version of what I really have):

 trait A {}

trait B<T: A> {
    fn get_a() -> T;
}

struct C<U, T>
where
    T: A,
    U: B<T>,
{
    field: U,
}

The compiler throws a [E0392] error because it thinks the type parameter T of C is unused. However, it is completely necessary to specify that U's type parameter meets the trait constraint.

In my use case, B is a factory that creates A's. A concrete factory will always create the same type of struct implementing A, that's why I do not use a Box.

I can work around this by adding a PhantomData field to the struct, but shouldn't the compiler notice that T is needed? Is there another approach to achieve something like that?

Shouldn't T be an associated type inside B and not a type parameter? Currently, it's possible to have U: B<T1> and U: B<T2> at the same time - does this make sense from your point of view?

1 Like

I may be wrong, but I think the compiler is missing variance information there:
https://doc.rust-lang.org/nightly/nomicon/subtyping.html
So for example, should it accept code like that:

fn take_short_lived_t<'a>(c: C<(), &'a ()>) -> &'a () {
    // ...
}

let c: C<(), &'static ()> = /* ... */;
take_short_lived_t(c);

?
To answer this, you need to use PhantomData in your struct.

1 Like

To illustrate the associated type version:

trait A {}

trait B {
    type T: A;

    fn get_a() -> Self::T;
}

struct C<U>
where
    U: B,
    U::T: A,
{
    field: U,
}

The above compiles.

2 Likes

Thanks @Cerberuser and @alice. Surely the associated type version is a better approach to my use case. It captures the fact that a B will always produce the same type of A.

I still wonder why the original code requires the PhantomData (guess there's some other use case where code like that makes sense). What arnaudgolfouse says makes sense, the compiler needs to know whether C is covariant, contrabariant or invariant over T.

The original code requires a PhantomData because T is otherwise not uniquely determined by the fields.

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.