-
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
Parse and accept type equality constraints in where clauses #20041
Comments
Adds support for all variants of ast::WherePredicate in clean/mod.rs. Fixes rust-lang#20048, but will need modification when EqualityPredicates are fully implemented in rust-lang#20041.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
I don't think associated type bindings are quite the same as this, since they aren't taken into account for determining overlapping impls (which appears to have been intentional) http://is.gd/em2JNT |
@sgrif Doesn't that make this a kind of duplicate of rust-lang/rfcs#1672? Edit: obviously with semantic differences, but I believe they allow for expressing the same types of bounds. |
I just ran into this limitation pretty hard while trying to do type level operations on HLists. Any work planned? The only possible workaround I see is this bitrotted brilliant abomination |
Show question (answered below)Taking this idea further (`where` on associated types), I want to do the following:
The latter trait on its own does all the work. The first one is just there to make the following work without explicitly specifying the type implementing
|
@dhardy What you want is just |
@sgrif that actually works, thanks! |
Props to @sgrif or this probably wouldn't have happened. rust-lang/rust#20041 (comment)
I would very much like to see this happen. Writing highly generic code is a pain, if you can't rename associated types inside traits, and this helps to do it, by asserting that a simple associated type is the same type as some monstrous thing: |
We discussed this in the lang-team meeting today. I am indeed concerned about general |
Accepting |
When was it decided to use single To me, it ultimately comes down to the symmetry of the operator. |
@scottjmaddox But this constraint only works on |
|
remove E0280 After looking at rust-lang#61137 I tried my hand at E0280. I'm unable to find a reasonable example that emits the error. There are a couple of old examples that compile with the current compiler ([rust-lang#26217](rust-lang#26217), [rust-lang#42114](rust-lang#42114), [rust-lang#27113](rust-lang#27113)) and there is a [bug with chalk](https://github.com/rust-lang/rust/blob/b7cdb635c4b973572307ad288466fba64533369c/src/test/ui/chalkify/bugs/async.rs) that makes it emit the error, with a couple more chalk bugs on zulip. It seems like the error is supposed to be emitted from unfulfilled where bounds, of which two are related to borrow checking (error in where T: 'a or where 'a: 'b) and thus tend to emit errors like "lifetime may not live long enough" from borrow checking instead. The final case is with type equality constraints (where <T as Iterator>::Item == u32), which is unimplemented ([rust-lang#20041](rust-lang#20041)). That such different problems are supposed to have the same error code also seems strange to me. Since the error seems to only be emitted when using chalk I propose to remove it and replace it with an ICE instead. A crater run might be warranted. Pinging `@jackh726` due to removal of chalk test that now ICEs.
The #![allow(unused)]
trait TyEq {}
impl<T: ?Sized> TyEq for (*const T, *const T) {}
fn convert<In, Out>(x: In) -> Out
where
(*const In, *const Out): TyEq,
{
// error[E0308]: mismatched types
x
} Most of the time, working around the lack of type equality constraint isn't too hard, but in more complicated cases it's still a problem: struct Something<F: Foo>(F);
impl<F: Foo> Something {
fn new<B>(b: B) -> Self
where
Wrap<B> == F,
{
Something(Wrap(b))
}
} The only recourse here seems to be to pass in |
``` error: equality constraints are not yet supported in `where` clauses --> $DIR/equality-bound.rs:50:9 | LL | IntoIterator::Item = A, | ^^^^^^^^^^^^^^^^^^^^^^ not supported | = note: see issue rust-lang#20041 <rust-lang#20041> for more information help: if `IntoIterator::Item` is an associated type you're trying to set, use the associated type binding syntax | LL ~ fn from_iter<T: IntoIterator<Item = A>>(_: T) -> Self LL | where LL ~ | error: equality constraints are not yet supported in `where` clauses --> $DIR/equality-bound.rs:63:9 | LL | T::Item = A, | ^^^^^^^^^^^ not supported | = note: see issue rust-lang#20041 <rust-lang#20041> for more information help: if `IntoIterator::Item` is an associated type you're trying to set, use the associated type binding syntax | LL ~ fn from_iter<T: IntoIterator<Item = A>>(_: T) -> Self LL | where LL ~ | ``` Fix rust-lang#68982.
Provide more suggestions on invalid equality where bounds ``` error: equality constraints are not yet supported in `where` clauses --> $DIR/equality-bound.rs:50:9 | LL | IntoIterator::Item = A | ^^^^^^^^^^^^^^^^^^^^^^ not supported | = note: see issue rust-lang#20041 <rust-lang#20041> for more information help: if `IntoIterator::Item` is an associated type you're trying to set, use the associated type binding syntax | LL ~ fn from_iter<T: IntoIterator<Item = A>>(_: T) -> Self LL ~ | error: equality constraints are not yet supported in `where` clauses --> $DIR/equality-bound.rs:63:9 | LL | T::Item = A | ^^^^^^^^^^^ not supported | = note: see issue rust-lang#20041 <rust-lang#20041> for more information help: if `IntoIterator::Item` is an associated type you're trying to set, use the associated type binding syntax | LL ~ fn from_iter<T: IntoIterator<Item = A>>(_: T) -> Self LL ~ | ``` Fix rust-lang#68982.
Rollup merge of rust-lang#120751 - estebank:issue-68982, r=nnethercote Provide more suggestions on invalid equality where bounds ``` error: equality constraints are not yet supported in `where` clauses --> $DIR/equality-bound.rs:50:9 | LL | IntoIterator::Item = A | ^^^^^^^^^^^^^^^^^^^^^^ not supported | = note: see issue rust-lang#20041 <rust-lang#20041> for more information help: if `IntoIterator::Item` is an associated type you're trying to set, use the associated type binding syntax | LL ~ fn from_iter<T: IntoIterator<Item = A>>(_: T) -> Self LL ~ | error: equality constraints are not yet supported in `where` clauses --> $DIR/equality-bound.rs:63:9 | LL | T::Item = A | ^^^^^^^^^^^ not supported | = note: see issue rust-lang#20041 <rust-lang#20041> for more information help: if `IntoIterator::Item` is an associated type you're trying to set, use the associated type binding syntax | LL ~ fn from_iter<T: IntoIterator<Item = A>>(_: T) -> Self LL ~ | ``` Fix rust-lang#68982.
A simple workaround trait TyEq<T> {
fn rw(self) -> T;
fn rwi(x: T) -> Self;
}
impl<T> TyEq<T> for T {
fn rw(self) -> T {
self
}
fn rwi(x: T) -> Self {
x
}
}
fn f<T, U>(x: T) -> U where T: TyEq<U> { // ... where T == U
x.rw()
}
fn g<T, U>(x: T) -> U where U: TyEq<T> { // ... where U == T
U::rwi(x)
} |
Actually, isn't as much of a problem, at least in the example posed. Here's a full example: trait TyEq
where
Self: From<Self::Type> + Into<Self::Type>,
Self::Type: From<Self> + Into<Self>,
{
type Type;
}
impl<T> TyEq for T {
type Type = T;
}
struct Wrap<B>(B);
trait Foo {}
struct Something<F: Foo>(F);
impl<F: Foo> Something<F> {
fn new<B>(b: B) -> Self
where
Wrap<B>: TyEq<Type = F>, // or F: TyEq<Type = Wrap<B>>, or both
{
Something(Wrap(b).into())
}
} One quirk of this approach is that it's not commutative. So Another quirk in this particular implementation is that all types have to be Not at all surprising at the end of the day, but not something you'd necessarily expect from a true equality constraint either. |
Implement the missing type equality constraint specified in RFC 135.
Examples
The text was updated successfully, but these errors were encountered: