genericsrustenumsconstraints

Constrained type is unconstrained?


I've been writing Rust for a several months now, and I've come across this headscratcher:

I have the following code:

trait MyTrait {}
impl MyTrait for String {}
impl MyTrait for str {}
impl MyTrait for u32 {}

pub enum myEnum {
    Stuff,
    Things,
}

impl<T: MyTrait> MyEnum {
    fn new(s: T) -> Self {
        ... branching logic based on types happens here
    }
}

Correct me if I'm wrong, but a constraint is anything you had in the angled brackets after <T: and I have constrained my impl my trait to ensure only the types I'm planning to handle are passed in.

Yet, I get this error when I try to compile...

error[E0207]: the type parameter `T` is not constrained by the impl trait, self type, or predicates
   --> src/lib.rs:235:6
    |
235 | impl<T: MyTrait> MyEnum {
    |      ^ unconstrained type parameter

The Rust Error Docs suggest putting a phantom type on the base structs... but I have no base structs, since I'm using primitives (which as I understand is only allowed if you defined the trait in your code, which I have) with an Enum which I'm not even sure HOW to put phantom data in...

So by everything I've read in the manual, the docs, and forums, it appears I've done this correctly. Yet it still says I have an unconstrained type parameter. What do I need to change to fix this? The error is less than helpful on how it's unconstrained.


Solution

  • "unconstrained type parameter" refers to a different thing than constraints in where clauses. Or rather, it's kinda the same thing. The basic idea is that if a type parameter is declared on the impl, it must have a single possible value. The exact rules can be found in the Reference about generic implementations.

    Luckily, for your case there is a simple solution - just move the type parameter to the method:

    impl MyEnum {
        fn new<T: MyTrait>(s: T) -> Self {
            ... branching logic based on types happens here
        }
    }