Skip to content

[E0207] thrown even though T is used in associated type #22834

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
Byron opened this issue Feb 26, 2015 · 2 comments
Closed

[E0207] thrown even though T is used in associated type #22834

Byron opened this issue Feb 26, 2015 · 2 comments

Comments

@Byron
Copy link
Member

Byron commented Feb 26, 2015

use std::default::Default;

trait Maker {
    type Item;

    fn make(&mut self) -> Self::Item;
}

struct Foo<T> {
    a: T,
}

struct Bar;

impl<T> Maker for Bar
    where T: Default  {
    type Item = Foo<T>;

    fn make(&mut self) -> Foo<T> {
        Foo {
            a: <T as Default>::default(),
        }
    }
}

The code above fails to compile with error ...

tests/lang.rs:1000:10: 1000:11 error: the type parameter `T` is not constrained by the impl trait, self type, or predicates [E0207]
tests/lang.rs:1000     impl<T> Maker for Bar

... even though T is used in the associated type Foo. This example looks very similar to a legal case in the respective RFC, namely:

// Legal:
// - A is used in the self type.
// - B is used in the input trait type parameters.
impl<A,B> SomeTrait<Option<B>> for Foo<A> {
    type Output = Result<A, IoError>;
}

One workaround is the use of PhantomData ...

use std::marker::PhantomData;
struct Bar<T> {
    _m: PhantomData<T>
}

impl<T> Maker for Bar<T>
    where T: Default  {
    type Item = Foo<T>;

    fn make(&mut self) -> Foo<T> {
        Foo {
            a: <T as Default>::default(),
        }
    }
}

... which to my mind shouldn't be required in the first place.

Meta

$ rustc --verbose --version
rustc 1.0.0-nightly (522d09dfe 2015-02-19) (built 2015-02-19)
binary: rustc
commit-hash: 522d09dfecbeca1595f25ac58c6d0178bbd21d7d
commit-date: 2015-02-19
build-date: 2015-02-19
host: x86_64-apple-darwin
release: 1.0.0-nightly
Byron added a commit to Byron/depot that referenced this issue Feb 26, 2015
@Kimundi
Copy link
Member

Kimundi commented Feb 26, 2015

This is intended behavior: The idea behind associated types is that they are uniqly determined by Self and all input type parameters. In you example and workaround, this is always the case:

impl<A,B> SomeTrait<Option<B>> for Foo<A> {
    type Output = Result<A, IoError>;
}

// Foo<A>::Output is different for each A

struct Bar<T> {
    _m: PhantomData<T>
}

// Bar<T>::Maker is different for each T

If you want to allow many possible types for the same Self type, you have to use input type parameters:

use std::default::Default;

trait Maker<Item> {
    fn make(&mut self) -> Item;
}

struct Foo<T> {
    a: T,
}

struct Bar;

impl<T> Maker<Foo<T>> for Bar
    where T: Default  
{

    fn make(&mut self) -> Foo<T> {
        Foo {
            a: <T as Default>::default(),
        }
    }
}

@Byron
Copy link
Member Author

Byron commented Feb 26, 2015

Thank you very much for the clarification - it seems rather obvious now !

@Byron Byron closed this as completed Feb 26, 2015
nham pushed a commit to nham/rust that referenced this issue May 23, 2016
The previous explanation does not seem to explain what it means for an
implementation parameter to be used or unused. The new explanation lists
the three ways specific ways by which an impl parameter becomes constrained
(taken from RFC 447).

This also adds a link to RFC 447.

The explanation has two different examples. The first is adapted from RFC 447,
and shows an instance of E0207 on a impl for a type. The second one is a trait
impl example adapted from issue rust-lang#22834.

Closes rust-lang#33650
GuillaumeGomez added a commit to GuillaumeGomez/rust that referenced this issue May 24, 2016
Improve the long explanation of E0207.

The previous explanation does not seem to explain what it means for an
implementation parameter to be used or unused. The new explanation lists
the three ways specific ways by which an impl parameter becomes constrained
(taken from RFC 447).

This also adds a link to RFC 447.

The explanation has two different examples. The first is adapted from RFC 447,
and shows an instance of E0207 on a impl for a type. The second one is a trait
impl example adapted from issue rust-lang#22834.

Closes rust-lang#33650

cc rust-lang#32777

r? @GuillaumeGomez
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants