“Expected type parameter” error in the constructor of a generic struct

Here’s a reproduction of your error:

struct Foo<T> {
    val: T,
}

impl<T> Foo<T> {
    fn new() -> Self {
        Foo { val: true }
    }
}

fn main() {}

The problem arises because you tried to lie to the compiler. This code:

impl<T> Foo<T> {
    fn new() -> Self {
        /* ... */
    }
}

Says “For whatever T the caller chooses, I will create a Foo with that type”. Then your actual implementation picks a concrete type — in the example, a bool. There’s no guarantee that T is a bool. Note that your new function doesn’t even accept any parameter of type T, which is highly suspect as that’s how the caller picks the concrete type 99% of the time.

The correct way of saying this would be

impl Foo<bool> {
    fn new() -> Self {
        Foo { val: true }
    }
}

Although you probably want to pick a more specific name than new, as it looks as if you are trying to make your struct generic. Presumably there would be other constructors with different types.

For your exact code, you probably want something like

impl TextureFactory<gfx_device_gl::Resources> { /* ... */ }

Another possible solution would be to remove the generic type parameter from your struct. If you only ever construct it with a gfx_device_gl::Resources, then there’s no reason to make it generic.

In other cases, you may be trying to return a type that implements a trait. For that, you can use a boxed trait object:

impl Foo<Box<dyn std::fmt::Display>> {
    fn new() -> Self {
        Foo { val: Box::new(true) }
    }
}

In the future, you may also be able to use impl Trait (a.k.a. existential types):

#![feature(type_alias_impl_trait)]

struct Foo<T> {
    val: T,
}

type SomeConcreteButOpaqueType = impl std::fmt::Display;

impl Foo<SomeConcreteButOpaqueType> {
    fn new() -> Self {
        Foo { val: true }
    }
}

See also:

Leave a Comment