You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Rollup merge of #153513 - fmease:gate-eq-pred, r=jackh726
Syntactically reject equality predicates
### Background (History)
Equality predicates have been *syntactically* valid since PR #39158 / nightly-2017-02-02 / 1.16 (released 2017-03-16, 9 years ago), both forms that is: `$ty = $ty` *and* `$ty == $ty`. They're not registered as an unstable feature despite having a tracking issue (#20041). Naturally, they don't have a feature gate. Of course, we reject them post-expansion, so they are still semantically invalid.
Parser scaffolding for `$ident = $ty` was added in RUST-19391 (2014) which was then generalized to `$ty = $ty` in RUST-20002 (2014) and extended to additionally cover `$ty == $ty` in RUST-39158 (2017). As mentioned, the last PR also made them grammatical.
RUST-87471 (2021) attempted to start impl'ing typeck'ing but it was closed due to concerns: #87471 (comment) (already back in 2017 there were concerns: https://github.com/rust-lang/rust/pull/39158/changes#r97811244).
In 2022, T-lang discussed this feature during a meeting and raised concerns: #20041 (comment). However, they were inclined to accept a restricted form, namely `T::AssocTy = $ty` (`T` is a (self) ty param or a self ty alias) and `<$ty as Trait>::AssocTy = $ty` since that's trivial to support in HIR ty lowering (this is still accurate).
### Change
This renders equality predicates `$ty = $ty` and `$ty == $ty` syntactically invalid again. On stable, they're merely semantically invalid. This is motivated by the fact that
1. their syntax isn't even decided upon
1. should it be `=` or `==`?
2. should the LHS be syntactically restricted to (possibly qualified) paths (i.e., *TypePath | QualifiedPathInType*), only semantically or not at all?
* "syntactically" could indeed make sense since we might want to generalize types to so-called *terms* here (i.e., *Type | GenericArgsConst*) for [mGCA](#132980) but we can't generalize `$ty = $ty` to `$term = $term` due to ambiguities [^1] that would require backtracking whereas `$typepath = $term` wouldn't have that problem
2. we might (decide to) never impl this feature
* after all, implementation concerns were raised as early as 9 years ago which are still relevant today even with the next-gen trait solver on the horizon
3. the compiler + tools contain a bunch of code for dealing with these predicates
* like lowering, name resolution, rustfmt and Clippy
* that's entirely useless since they get unconditionally rejected anyway
* this code doesn't need to exist (for now)
I've merely upgraded the semantic hard error to a syntactic hard error, I've intentionally not introduced an unstable feature under which equality predicates become legal.
That's because a hard error is easier to push through procedurally, it's an important first step (we can always turn it into a feature gate error later on) and since this potential feature isn't backed by any official lang experiment.
I don't consider T-lang's message #20041 (comment) from 2022 to be sufficient because it doesn't answer questions like (1.i), (1.ii) or whether code like `T: Trait<A>, <T as Trait<B>>::AssocTy = Ty` (`A` ≠ `B`) or `T: Trait<'r>, for<'a> <T as Trait<'a>>::AssocTy = Ty` should be legal (which would be more powerful / could lead to typechecking issues, idk) or not assuming we're going with the restricted form ofc (we would need input from T-types).
### Lang nomination
#153513 (comment)
[^1]: Code like `fn f() -> i32 where { 0 }` is intentionally legal today but if we had `$term = $term` the `{ 0 }` could then also be the start of an equality predicate like `{ 0 } = 0`.
0 commit comments