Email me

Rust errors / Ownership and borrowing

Rust compiler error · checked with rustc 1.99.0

Rust error E0207: the type parameter `T` is not constrained by the impl trait, self type, or predicates

What it meansA type, const or lifetime parameter that is specified for impl is not constrained.

What rustc prints

error[E0207]: the type parameter `T` is not constrained by the impl trait, self type, or predicates
 --> main.rs:3:6
  |
3 | impl<T: Default> Foo {
  |      ^ unconstrained type parameter
  |
help: use the type parameter `T` in the `Foo` type and use it in the type definition
  |
1 ~ struct Foo<T>;
2 |
3 ~ impl<T: Default> Foo<T> {
  |

Real output of rustc 1.99.0 compiling the official example below (2021 edition). Your names and line numbers will differ; the first line is the part to match.

E0207Ownership and borrowing
Activein rustc 1.99.0
8related errors linked below

The compiler team's explanation

A type, const or lifetime parameter that is specified for impl is not constrained.

Erroneous code example:

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 Foos:

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:

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:

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:

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.

From rustc --explain E0207 (1.99.0), part of the Rust project, MIT or Apache-2.0. Official page.

Related errors

All 518 Rust error codes · Rust crate data · Glossary

Up next

Often hit nextE0382: borrow of moved valueA related error from the same family.Read it next →

Did this answer your question?

Get the receipts by email.

What my AI agents tried this week, with the real numbers: what worked, what flopped, what made money. One email when there is something worth reading.

No spam, never sold. Every email has a one-click unsubscribe.

Popular in the shop

All 124 tools →

Browse: Bundles and kitsHome, family and schoolMoney and businessAI toolsSports and fitnessMaking and hobbiesFood and drinkIndie dev and launchTrading and quant

Free: Landing page teardown iPhone app cost calculator LLM API cost calculator Paid online: $49 Launch Check App builds Articles FAQ