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

Constraints on associated types declared in subtraits do not propagate. #32722

Closed
brendanzab opened this issue Apr 4, 2016 · 8 comments
Closed
Labels
A-associated-items Area: Associated items (types, constants & functions) A-trait-system Area: Trait system A-type-system Area: Type system C-bug Category: This is a bug. F-associated_type_bounds `#![feature(associated_type_bounds)]` T-lang Relevant to the language team, which will review and decide on the PR/issue.

Comments

@brendanzab
Copy link
Member

Pretty bad title - sorry. Somebody who knows the type checker might be able to do better.

Here is a minimal example:

pub trait Real {}

pub trait VectorSpace {
    type Scalar;
}

pub trait InnerSpace: VectorSpace where
    <Self as VectorSpace>::Scalar: Real,
{
    fn dot(self, other: Self) -> Self::Scalar;
}

pub fn dot<V: InnerSpace>(a: V, b: V) -> V::Scalar {
    V::dot(a, b)
}
<anon>:13:1: 15:2 error: the trait `Real` is not implemented for the type `<V as VectorSpace>::Scalar` [E0277]
<anon>:13 pub fn dot<V: InnerSpace>(a: V, b: V) -> V::Scalar {
<anon>:14     V::dot(a, b)
<anon>:15 }
<anon>:13:1: 15:2 help: see the detailed explanation for E0277
<anon>:13:1: 15:2 note: required by `InnerSpace`

http://is.gd/vjIVwO

@apoelstra
Copy link
Contributor

apoelstra commented Jul 23, 2016

Another example:

trait SomeBound {}

trait A {
    type Type;
}

trait B: A where Self::Type: SomeBound {
}

trait C: B {}

fn main() {}

I don't think the problem is that the bounds "don't propagate". It simply should not matter to trait C: B what conditions B would like to have; if I've got a type that implements B then obviously those are satisfied, whatever they are.

Edit: Here is my actual usecase. I think something like this is required to get ergonomic session types in Rust:

trait SessionType {
    type Dual;
}

trait Recv: SessionType
    where Self::Dual: Send {
}

trait Send: SessionType
    where Self::Dual: Recv {
}

fn main() {}
test.rs:6:1: 8:2 error: the trait bound `<<Self as SessionType>::Dual as SessionType>::Dual: Recv` is not satisfied [E0277]
test.rs:6 trait Recv: SessionType
test.rs:7     where Self::Dual: Send {
test.rs:8 }
test.rs:6:1: 8:2 help: run `rustc --explain E0277` to see a detailed explanation
test.rs:6:1: 8:2 help: consider adding a `where <<Self as SessionType>::Dual as SessionType>::Dual: Recv` bound
test.rs:6:1: 8:2 note: required by `Send`
test.rs:10:1: 12:2 error: the trait bound `<<Self as SessionType>::Dual as SessionType>::Dual: Send` is not satisfied [E0277]
test.rs:10 trait Send: SessionType
test.rs:11     where Self::Dual: Recv {
test.rs:12 }
test.rs:10:1: 12:2 help: run `rustc --explain E0277` to see a detailed explanation
test.rs:10:1: 12:2 help: consider adding a `where <<Self as SessionType>::Dual as SessionType>::Dual: Send` bound
test.rs:10:1: 12:2 note: required by `Recv`

@CasualX
Copy link

CasualX commented Oct 1, 2016

I ran into this when creating a trait that requires FromStr and constrains FromStr::Err: 'static + Error. Anything that uses this trait must repeat the associated type constraint or I get this error.

@brendanzab brendanzab added the A-type-system Area: Type system label Oct 2, 2016
@brendanzab
Copy link
Member Author

cc. @sebcrozet

@Popog
Copy link

Popog commented Oct 26, 2016

Is this the same issue as #20671?

@Mark-Simulacrum Mark-Simulacrum added the C-bug Category: This is a bug. label Jul 24, 2017
@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. and removed A-type-system Area: Type system labels Nov 5, 2019
@estebank
Copy link
Contributor

estebank commented Nov 5, 2019

Current output suggests code that would be accepted today:

error[E0277]: the trait bound `<V as VectorSpace>::Scalar: Real` is not satisfied
  --> src/lib.rs:13:1
   |
7  | / pub trait InnerSpace: VectorSpace where
8  | |     <Self as VectorSpace>::Scalar: Real,
9  | | {
10 | |     fn dot(self, other: Self) -> Self::Scalar;
11 | | }
   | |_- required by `InnerSpace`
12 | 
13 |   pub fn dot<V: InnerSpace>(a: V, b: V) -> V::Scalar {
   |   ^                                                 - help: consider further restricting the associated type: `where <V as VectorSpace>::Scalar: Real`
   |  _|
   | |
14 | |     V::dot(a, b)
15 | | }
   | |_^ the trait `Real` is not implemented for `<V as VectorSpace>::Scalar`
error[E0277]: the trait bound `<Self as A>::Type: SomeBound` is not satisfied
  --> src/main.rs:10:1
   |
7  | trait B: A where Self::Type: SomeBound {
   | -------------------------------------- required by `B`
...
10 | trait C: B {}
   | ^^^^^^^^^^-^^
   | |         |
   | |         help: consider further restricting the associated type: `where <Self as A>::Type: SomeBound`
   | the trait `SomeBound` is not implemented for `<Self as A>::Type`
error[E0277]: the trait bound `<<Self as SessionType>::Dual as SessionType>::Dual: Recv` is not satisfied
  --> src/main.rs:5:1
   |
5  | / trait Recv: SessionType
6  | |     where Self::Dual: Send {
   | |                           - help: consider further restricting the associated type: `, <<Self as SessionType>::Dual as SessionType>::Dual: Recv`
7  | | }
   | |_^ the trait `Recv` is not implemented for `<<Self as SessionType>::Dual as SessionType>::Dual`
8  | 
9  | / trait Send: SessionType
10 | |     where Self::Dual: Recv {
11 | | }
   | |_- required by `Send`

error[E0277]: the trait bound `<<Self as SessionType>::Dual as SessionType>::Dual: Send` is not satisfied
  --> src/main.rs:9:1
   |
5  | / trait Recv: SessionType
6  | |     where Self::Dual: Send {
7  | | }
   | |_- required by `Recv`
8  | 
9  | / trait Send: SessionType
10 | |     where Self::Dual: Recv {
   | |                           - help: consider further restricting the associated type: `, <<Self as SessionType>::Dual as SessionType>::Dual: Send`
11 | | }
   | |_^ the trait `Send` is not implemented for `<<Self as SessionType>::Dual as SessionType>::Dual`

@CasualX
Copy link

CasualX commented Nov 5, 2019

@estebank Rust error messages have come a long way :)

In this particular case however it would be nice if Rust knew how to propagate the where clause on traits. Another similar demonstration looks like this:

use std::str::FromStr;
use std::error::Error;

trait Parse: FromStr where Self::Err: 'static + Error {}

fn parse<T: Parse>(s: &str) -> Result<T, T::Err> {
    s.parse()
}

Results in the compiler complaining that just because T must implement Parse doesn't mean that T::Err implements std::error::Error. Which is dumb as there are no types which implement Parse which have their Err associated type not implement std error trait.

So even though the Rust compiler now makes a suggestion this is still painful as you must repeat the bounds everywhere (perhaps the entire point to make this trait was to imply a whole bunch of traits in a single name).

@estebank
Copy link
Contributor

estebank commented Nov 5, 2019

That feature work is likely to happen at some point and it is widely requested. I haven't closed this ticket because the feature work is not done, but at least we have a mitigation in place.

@estebank estebank added A-trait-system Area: Trait system A-type-system Area: Type system labels Dec 13, 2019
@jonas-schievink
Copy link
Contributor

Duplicate of #20671. Also see #44491.

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 (types, constants & functions) A-trait-system Area: Trait system A-type-system Area: Type system C-bug Category: This is a bug. F-associated_type_bounds `#![feature(associated_type_bounds)]` T-lang Relevant to the language team, which will review and decide on the PR/issue.
Projects
None yet
Development

No branches or pull requests

7 participants