-
Notifications
You must be signed in to change notification settings - Fork 12.9k
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 supertraits associated types are ignored #24616
Comments
Related to #20671? |
Here's another, although less general example of this bug: use std::path::Path;
use std::convert::AsRef;
use std::iter::Peekable;
use std::env;
trait PathIterator: Iterator where <Self as Iterator>::Item : AsRef<Path> {}
impl<I: ?Sized, T: AsRef<Path>> PathIterator for I
where I: Iterator<Item = T> {}
struct A<I: PathIterator> {
paths: Peekable<I>,
}
impl<I: PathIterator> A<I> {
fn next_path(&self) -> Option<&Path> {
self.paths.peek().map(|p| p.as_ref())
}
}
fn main() { }
|
I believe this is the issue that I'm having, and it depends on whether you are implementing a trait with a member function or not. In addition to the compiler not correctly figuring out type constraints, it takes much longer to compile when given type constraints with a Consider the following two implementations of addition over Peano numbers using Rust's type system: First, using Then, using a custom trait for addition, The key difference is here: Using impl<Lhs: Peano + AddPeano<Rhs>, Rhs: Peano> AddPeano<Rhs> for Succ<Lhs> {
type Output = Succ<<Lhs as AddPeano<Rhs>>::Output>;
} Using impl<Lhs: Peano + Add<Rhs>, Rhs: Peano> Add<Rhs> for Succ<Lhs> where <Lhs as Add<Rhs>>::Output: Peano {
type Output = Succ<<Lhs as Add<Rhs>>::Output>;
fn add(self, rhs: Rhs) -> Self::Output { unreachable!() }
} without the
In I have had similar results locally ... even using up 8 GB of ram in the case of the |
Predicates on Self's associated types aren't supertrait predicates and are not elaborated - you need to add the where-clauses explicitly (e.g. @paholg |
Okay, will do. Thanks, @arielb1. |
There's a workaround for the first example: trait Foo {
type T;
}
trait Bar {
fn bar(&self);
}
trait QuuxMyT {
type MyT: Bar;
}
trait Quux: QuuxMyT + Foo<T=<Self as QuuxMyT>::MyT> {
fn quux(&self) -> Self::T;
}
struct Baz<X> {
x: X,
}
impl<X: Quux> Baz<X> {
fn baz(&self) {
self.x.quux().bar()
}
} Basically, use the fact that bounds on associated types are always assumed (elaborated? the relevant RFC said 'assume') by moving the bound to a helper trait's associated type, then force the identity relation on that helper trait's associated type and the relevant associated type of the supertrait. |
The following code:
fails to compile, with the error message
the trait Bar is not implemented for the type <X as Foo>::T [E0277]
As it is impossible for the return type of
quux()
to not return a type that implementsBar
, I think this is a bug in the compiler.The text was updated successfully, but these errors were encountered: