Change:
The code above fails to compile with error ... ... even though is used in the associated type . This example looks very similar to a legal case , namely: One workaround is the use of ... ... which to my mind shouldn't be required in the first place.
This is intended behavior: The idea behind associated types is that they are uniqly determined by and all input type parameters. In you example and workaround, this is always the case: If you want to allow many possible types for the same type, you have to use input type parameters:
Thank you very much for the clarification - it seems rather obvious now !

Discussion:
"##, E0207: r##" <del> You declared an unused type parameter when implementing a trait on an object. Erroneous code example: </del> <ins> Any type parameter or lifetime parameter of an `impl` must meet at least one of the following criteria: - it appears in the self type of the impl - for a trait impl, it appears in the trait reference - it is bound as an associated type ### Error example 1 Suppose we have a struct `Foo` and we would like to define some methods for it. The following definition leads to a compiler error: </ins> ```compile_fail <del> trait MyTrait { fn get(&self) -> usize; </del> <ins> struct Foo; impl<T: Default> Foo { // error: the type parameter `T` is not constrained by the impl trait, self // type, or predicates [E0207] fn get(&self) -> T { <T as Default>::default() } </ins> } <ins> ``` The problem is that the parameter `T` does not appear in the self type (`Foo`) of the impl. In this case, we can fix the error by moving the type parameter from the `impl` to the method `get`: ``` </ins> struct Foo; <del> impl<T> MyTrait for Foo { fn get(&self) -> usize { 0 </del> <ins> // Move the type parameter from the impl to the method impl Foo { fn get<T: Default>(&self) -> T { <T as Default>::default() </ins> } } ``` <del> Please check your object definition and remove unused type parameter(s). Example: </del> <ins> ### Error example 2 As another example, suppose we have a `Maker` trait and want to establish a type `FooMaker` that makes `Foo`s: ```compile_fail trait Maker { type Item; fn make(&mut self) -> Self::Item; } struct Foo<T> { foo: T } struct FooMaker; impl<T: Default> Maker for FooMaker { // error: the type parameter `T` is not constrained by the impl trait, self // type, or predicates [E0207] type Item = Foo<T>; fn make(&mut self) -> Foo<T> { Foo { foo: <T as Default>::default() } } } </ins> ``` <del> trait MyTrait { fn get(&self) -> usize; </del> <ins> This fails to compile because `T` does not appear in the trait or in the implementing type. One way to work around this is to introduce a phantom type parameter into `FooMaker`, like so: ``` use std::marker::PhantomData; trait Maker { type Item; fn make(&mut self) -> Self::Item; </ins> } <del> struct Foo; </del> <ins> struct Foo<T> { foo: T } </ins> <del> impl MyTrait for Foo { fn get(&self) -> usize { 0 </del> <ins> // Add a type parameter to `FooMaker` struct FooMaker<T> { phantom: PhantomData<T>, } impl<T: Default> Maker for FooMaker<T> { type Item = Foo<T>; fn make(&mut self) -> Foo<T> { Foo { foo: <T as Default>::default(), } } } ``` Another way is to do away with the associated type in `Maker` and use an input type parameter instead: ``` // Use a type parameter instead of an associated type here trait Maker<Item> { fn make(&mut self) -> Item; } struct Foo<T> { foo: T } struct FooMaker; impl<T: Default> Maker<Foo<T>> for FooMaker { fn make(&mut self) -> Foo<T> { Foo { foo: <T as Default>::default() } </ins> } } ``` <ins> ### Additional information For more information, please see [RFC 447]. [RFC 447]: https://github.com/rust-lang/rfcs/blob/master/text/0447-no-unused-impl-parameters.md </ins> "##, E0210: r##"