Skip to content

Associated type bound isn't always present for checking #43475

New issue

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

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

Already on GitHub? # to your account

Closed
Twey opened this issue Jul 25, 2017 · 3 comments · Fixed by #81485
Closed

Associated type bound isn't always present for checking #43475

Twey opened this issue Jul 25, 2017 · 3 comments · Fixed by #81485
Labels
A-associated-items Area: Associated items (types, constants & functions) C-bug Category: This is a bug. T-lang Relevant to the language team, which will review and decide on the PR/issue.

Comments

@Twey
Copy link

Twey commented Jul 25, 2017

Trait bounds on associated types seem to be required, not implied, when the trait in question mentions an associated type on a type parameter.

Concretely, this code (or playground) produces an error:

trait Foo { type FooT: Foo; }
impl Foo for () { type FooT = (); }
trait Bar<T: Foo> { type BarT: Bar<T::FooT>; }
impl Bar<()> for () { type BarT = (); }

fn test<C: Bar<()>>() { }
error[E0277]: the trait bound `<C as Bar<()>>::BarT: Bar<()>` is not satisfied
 --> src/main.rs:6:1
  |
6 | fn test<C: Bar<()>>() { }
  | ^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `Bar<()>` is not implemented for `<C as Bar<()>>::BarT`
  |
  = help: consider adding a `where <C as Bar<()>>::BarT: Bar<()>` bound
  = note: required by `Bar`

despite the C::BarT: Bar<()> bound being required by the definition of Bar itself, and in fact this means that the trait Bar<T> can never be mentioned.

This similar example (playground) that doesn't use an associated type in the trait parameter compiles:

trait Foo { type FooT: Foo; }
impl Foo for () { type FooT = (); }
trait Bar<T: Foo> { type BarT: Bar<T>; }
impl Bar<()> for () { type BarT = (); }

fn test<C: Bar<()>>() { }

while this version (playground), which uses a third trait to avoid the self-reference, does not:

trait Foo { type FooT: Foo; }
impl Foo for () { type FooT = (); }
trait Bar<T: Foo> { type BarT: Baz<T::FooT>; }
impl Bar<()> for () { type BarT = (); }
trait Baz<T: Foo> { }
impl Baz<()> for () { }

fn test<C: Bar<()>>() { }

Is this just a missing normalization step?

@Mark-Simulacrum Mark-Simulacrum added the C-bug Category: This is a bug. label Jul 26, 2017
@Marwes
Copy link
Contributor

Marwes commented Aug 1, 2017

Pretty sure I encountered the same bug when specifying an associated type explicitly in a signature.

pub trait Param<P> {
    fn param(p: P) -> Self;
}

pub trait Test: Sized {
    type T: Param<Self::Item>;
    type Item;
}

// Compiles
fn test<T: Test>(p: T::Item) -> T::T {
    T::T::param(p)
}

// Does not compile
fn test2<T: Test<Item = u8>>(p: T::Item) -> T::T {
    T::T::param(p)
}

fn main() {
}
Compiling playground v0.0.1 (file:///playground)
error[E0277]: the trait bound `<T as Test>::T: Param<u8>` is not satisfied
  --> src/main.rs:15:1
   |
15 | / fn test2<T: Test<Item = u8>>(p: T::Item) -> T::T {
16 | |     T::T::param(p)
17 | | }
   | |_^ the trait `Param<u8>` is not implemented for `<T as Test>::T`
   |
   = help: consider adding a `where <T as Test>::T: Param<u8>` bound
   = note: required by `Test`

error: aborting due to previous error

error: Could not compile `playground`.

To learn more, run the command again with --verbose.

https://play.rust-lang.org/?gist=20c9d87e34aecc76754bc687734e00c5&version=nightly

Twey added a commit to Twey/rust that referenced this issue Aug 4, 2017
@shepmaster
Copy link
Member

/cc @arielb1 you wanted to ensure this test case fell into the trait system rewrite.

@rkarp
Copy link
Contributor

rkarp commented Dec 10, 2017

I've just run into this as well, it seems. Here's a very simple example:

trait Foo {
    type Item;
    type FnOfItem: Fn(Self::Item);
}

fn test<T>()
where
    T: Foo<Item = usize>,
    //T::FnOfItem: Fn(T::Item), // <-- Compile error without this
{}

fn main() {}
error[E0277]: the trait bound `<T as Foo>::FnOfItem: std::ops::Fn<(usize,)>` is not satisfied
  --> src/main.rs:6:1
   |
6  | / fn test<T>()
7  | | where
8  | |     T: Foo<Item = usize>,
9  | |     //T::FnOfItem: Fn(T::Item), // <-- Compile error without this
10 | | {}
   | |__^ the trait `std::ops::Fn<(usize,)>` is not implemented for `<T as Foo>::FnOfItem`
   |
   = help: consider adding a `where <T as Foo>::FnOfItem: std::ops::Fn<(usize,)>` bound
   = note: required by `Foo`

https://play.rust-lang.org/?gist=add5141b26dc781bd27c5b09c8c14f2d&version=nightly

@estebank estebank added A-associated-items Area: Associated items (types, constants & functions) F-associated_type_bounds `#![feature(associated_type_bounds)]` T-lang Relevant to the language team, which will review and decide on the PR/issue. labels Nov 5, 2019
yvt added a commit to r3-os/r3 that referenced this issue Jun 9, 2020
The modification to `constance_port_std` in this commit is a work-around
for <rust-lang/rust#43475>.
@jonas-schievink jonas-schievink removed the F-associated_type_bounds `#![feature(associated_type_bounds)]` label Jan 28, 2021
JohnTitor added a commit to JohnTitor/rust that referenced this issue Feb 2, 2021
Add some tests for associated-type-bounds issues

Closes rust-lang#38917
Closes rust-lang#40093
Closes rust-lang#43475
Closes rust-lang#63591

rust-lang#47897 is likely closable too, but it needs an MCVE
~~rust-lang#38917, rust-lang#40093, rust-lang#43475, rust-lang#47897 all are mislabeled and shouldn't have the `F-associated-type-bounds` label~~

~~rust-lang#71685 is also mislabeled as commented on in that thread~~
@bors bors closed this as completed in a61e6ab Feb 2, 2021
# for free to join this conversation on GitHub. Already have an account? # to comment
Labels
A-associated-items Area: Associated items (types, constants & functions) C-bug Category: This is a bug. T-lang Relevant to the language team, which will review and decide on the PR/issue.
Projects
None yet
Development

Successfully merging a pull request may close this issue.

7 participants