Skip to content
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

Associated type equality in trait bounds not properly matched #37883

Closed
sebcrozet opened this issue Nov 19, 2016 · 3 comments · Fixed by #81671
Closed

Associated type equality in trait bounds not properly matched #37883

sebcrozet opened this issue Nov 19, 2016 · 3 comments · Fixed by #81671
Labels
A-associated-items Area: Associated items such as associated types and consts. A-lazy-normalization Area: lazy normalization (tracking issue: #60471) A-traits Area: Trait system C-bug Category: This is a bug. E-needs-test Call for participation: Writing correctness tests. T-lang Relevant to the language team, which will review and decide on the PR/issue.

Comments

@sebcrozet
Copy link
Contributor

sebcrozet commented Nov 19, 2016

I might be missing something but I believe the following (playpen) should compile but does not:

use std::ops::Mul;


fn main() {
}


trait Ring { }
trait Real: Ring { }

trait Module: Sized + Mul<<Self as Module>::Ring, Output = Self> {
    type Ring: Ring;
}

trait EuclideanSpace {
    type Coordinates: Module<Ring = Self::Real>;
    type Real:        Real;
}


pub trait Translation<E: EuclideanSpace> {
    fn to_vector(&self) -> E::Coordinates;

    fn powf(&self, n: <E::Coordinates as Module>::Ring) -> E::Coordinates {
        self.to_vector() * n
    }
}

In self.to_vector() * n, the compiler seems to understand that <E::Coordinates as Module>::Ring> is the same thing as E::Real but fails to applies the Mul<<Self as Module>::Ring, Output = Self> trait from Module.

sebcrozet added a commit to dimforge/alga that referenced this issue Dec 4, 2016
Changelog:

* The `Real` trait now includes some commonly implemented markers, e.g.,
  Sync, Any, 'static, etc.
* The `Module` trait no longer inherit from operator overload traits. This is
  due to a [limitation](rust-lang/rust#37883) in
  the compiler that prevent them from being used properly in generic code.
* The `Transform` trait is split into `Transform` and `ProjectiveTransform`.
  Inverse transformation methods have been moved from the first to the second.
* The `Affine` trait now has methods for appending/prepending pure
  translation/rotation/scaling.
* `EuclideanSpace::Vector` has been renamed `EuclideanSpace::Coordinates`.
* Added `Rotation::scaled_rotation_between` wich is a combination of
  `Rotation::rotation_between` and `Rotation::powf`.
* `FiniteDimVectorSpace` looses `::component` but gains the
  `::component_unchecked_mut` method (for mutable compoent borrowing without
  bound-checking).
* Added `EuclideanSpace::from_coordinates` that builds a point from its
  coordinates.
@apasel422 apasel422 added A-associated-items Area: Associated items such as associated types and consts. A-traits Area: Trait system labels Dec 28, 2016
@Twey
Copy link

Twey commented Mar 16, 2017

Smaller test case (Playground):

pub trait Foo<T> { }
pub trait Bar: Foo<<Self as Bar>::Quux> { type Quux; }
pub trait Arthur { type Wibble: Bar<Quux=()>; }
pub fn assert_is_foo<A: Foo<()>>() { }
pub fn assert_is_bar<B: Bar<Quux=()>>() { }

pub fn test<A: Arthur>() {
    let _: <A::Wibble as Bar>::Quux = ();
    assert_is_bar::<A::Wibble>();
    assert_is_foo::<A::Wibble>(); // the trait bound `<A as Arthur>::Wibble: Foo<()>` is not satisfied
}

This code (in the body of test) knows that A::Wibble: Bar and that <A::Wibble as Bar>::Quux = (), but not that A::Wibble: Foo<()>.

@Mark-Simulacrum Mark-Simulacrum added the C-bug Category: This is a bug. label Jul 26, 2017
@estebank estebank added 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
@estebank
Copy link
Contributor

estebank commented Nov 5, 2019

Current output:

error[E0277]: cannot multiply `<E as EuclideanSpace>::Real` to `<E as EuclideanSpace>::Coordinates`
  --> src/main.rs:25:26
   |
24 |     fn powf(&self, n: <E::Coordinates as Module>::Ring) -> E::Coordinates {
   |                                                                          - help: consider further restricting the associated type: `where <E as EuclideanSpace>::Coordinates: std::ops::Mul<<E as EuclideanSpace>::Real>`
25 |         self.to_vector() * n
   |                          ^ no implementation for `<E as EuclideanSpace>::Coordinates * <E as EuclideanSpace>::Real`
   |
   = help: the trait `std::ops::Mul<<E as EuclideanSpace>::Real>` is not implemented for `<E as EuclideanSpace>::Coordinates`

error[E0308]: mismatched types
  --> src/main.rs:25:28
   |
25 |         self.to_vector() * n
   |                            ^ expected Module::Ring, found EuclideanSpace::Real
   |
   = note: expected type `<<E as EuclideanSpace>::Coordinates as Module>::Ring`
              found type `<E as EuclideanSpace>::Real`
error[E0277]: the trait bound `<A as Arthur>::Wibble: Foo<()>` is not satisfied
  --> src/main.rs:10:5
   |
4  | pub fn assert_is_foo<A: Foo<()>>() { }
   |        -------------    ------- required by this bound in `assert_is_foo`
...
7  | pub fn test<A: Arthur>() {
   |                         - help: consider further restricting the associated type: `where <A as Arthur>::Wibble: Foo<()>`
...
10 |     assert_is_foo::<A::Wibble>();
   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `Foo<()>` is not implemented for `<A as Arthur>::Wibble`

@matthewjasper matthewjasper added the A-lazy-normalization Area: lazy normalization (tracking issue: #60471) label Jul 11, 2020
@estebank estebank added the E-needs-test Call for participation: Writing correctness tests. label Feb 2, 2021
@estebank
Copy link
Contributor

estebank commented Feb 2, 2021

This now compiles.

@jackh726 jackh726 removed the F-associated_type_bounds `#![feature(associated_type_bounds)]` label Feb 2, 2021
jackh726 added a commit to jackh726/rust that referenced this issue Feb 2, 2021
@bors bors closed this as completed in 81c64b3 Feb 3, 2021
xmas7 pushed a commit to RubyOnWorld/alga that referenced this issue Sep 6, 2022
Changelog:

* The `Real` trait now includes some commonly implemented markers, e.g.,
  Sync, Any, 'static, etc.
* The `Module` trait no longer inherit from operator overload traits. This is
  due to a [limitation](rust-lang/rust#37883) in
  the compiler that prevent them from being used properly in generic code.
* The `Transform` trait is split into `Transform` and `ProjectiveTransform`.
  Inverse transformation methods have been moved from the first to the second.
* The `Affine` trait now has methods for appending/prepending pure
  translation/rotation/scaling.
* `EuclideanSpace::Vector` has been renamed `EuclideanSpace::Coordinates`.
* Added `Rotation::scaled_rotation_between` wich is a combination of
  `Rotation::rotation_between` and `Rotation::powf`.
* `FiniteDimVectorSpace` looses `::component` but gains the
  `::component_unchecked_mut` method (for mutable compoent borrowing without
  bound-checking).
* Added `EuclideanSpace::from_coordinates` that builds a point from its
  coordinates.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
A-associated-items Area: Associated items such as associated types and consts. A-lazy-normalization Area: lazy normalization (tracking issue: #60471) A-traits Area: Trait system C-bug Category: This is a bug. E-needs-test Call for participation: Writing correctness tests. 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