-
Notifications
You must be signed in to change notification settings - Fork 13.4k
Constraints on supertraits associated types are ignored #24616
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
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: