| A type, const or lifetime parameter that is specified for `impl` is not | |
| constrained. | |
| Erroneous code example: | |
| ```compile_fail,E0207 | |
| 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() | |
| } | |
| } | |
| ``` | |
| Any type or const parameter of an `impl` must meet at least one of the | |
| following criteria: | |
| - it appears in the _implementing type_ of the impl, e.g. `impl<T> Foo<T>` | |
| - for a trait impl, it appears in the _implemented trait_, e.g. | |
| `impl<T> SomeTrait<T> for Foo` | |
| - it is bound as an associated type, e.g. `impl<T, U> SomeTrait for T | |
| where T: AnotherTrait<AssocType=U>` | |
| Any unconstrained lifetime parameter of an `impl` is not supported if the | |
| lifetime parameter is used by an associated type. | |
| ### Error example 1 | |
| Suppose we have a struct `Foo` and we would like to define some methods for it. | |
| The previous code example has a definition which leads to a compiler error: | |
| The problem is that the parameter `T` does not appear in the implementing 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`: | |
| ``` | |
| struct Foo; | |
| // Move the type parameter from the impl to the method | |
| impl Foo { | |
| fn get<T: Default>(&self) -> T { | |
| <T as Default>::default() | |
| } | |
| } | |
| ``` | |
| ### 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,E0207 | |
| 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() } | |
| } | |
| } | |
| ``` | |
| 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; | |
| } | |
| struct Foo<T> { | |
| foo: T | |
| } | |
| // 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() } | |
| } | |
| } | |
| ``` | |
| ### Error example 3 | |
| Suppose we have a struct `Foo` and we would like to define some methods for it. | |
| The following code example has a definition which leads to a compiler error: | |
| ```compile_fail,E0207 | |
| struct Foo; | |
| impl<const T: i32> Foo { | |
| // error: the const parameter `T` is not constrained by the impl trait, self | |
| // type, or predicates [E0207] | |
| fn get(&self) -> i32 { | |
| i32::default() | |
| } | |
| } | |
| ``` | |
| The problem is that the const parameter `T` does not appear in the implementing | |
| 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`: | |
| ``` | |
| struct Foo; | |
| // Move the const parameter from the impl to the method | |
| impl Foo { | |
| fn get<const T: i32>(&self) -> i32 { | |
| i32::default() | |
| } | |
| } | |
| ``` | |
| ### Error example 4 | |
| Suppose we have a struct `Foo` and a struct `Bar` that uses lifetime `'a`. We | |
| would like to implement trait `Contains` for `Foo`. The trait `Contains` have | |
| the associated type `B`. The following code example has a definition which | |
| leads to a compiler error: | |
| ```compile_fail,E0207 | |
| struct Foo; | |
| struct Bar<'a>; | |
| trait Contains { | |
| type B; | |
| fn get(&self) -> i32; | |
| } | |
| impl<'a> Contains for Foo { | |
| type B = Bar<'a>; | |
| // error: the lifetime parameter `'a` is not constrained by the impl trait, | |
| // self type, or predicates [E0207] | |
| fn get(&self) -> i32 { | |
| i32::default() | |
| } | |
| } | |
| ``` | |
| Please note that unconstrained lifetime parameters are not supported if they are | |
| being used by an associated type. | |
| In cases where the associated type's lifetime is meant to be tied to the | |
| self type, and none of the methods on the trait need ownership or different | |
| mutability, then an option is to implement the trait on a borrowed type: | |
| ```rust | |
| struct Foo(i32); | |
| trait Contents { | |
| type Item; | |
| fn get(&self) -> Self::Item; | |
| } | |
| // Note the lifetime `'a` is used both for the self type... | |
| impl<'a> Contents for &'a Foo { | |
| // ...and the associated type. | |
| type Item = &'a i32; | |
| fn get(&self) -> Self::Item { | |
| &self.0 | |
| } | |
| } | |
| ``` | |
| ### Additional information | |
| For more information, please see [RFC 447]. | |
| [RFC 447]: https://rust-lang.github.io/rfcs/0447-no-unused-impl-parameters.html |