Description
Compiler version
Scala 3.2.2
Minimized code
extension [C1 <: Int](c2: (C1, C2)) // C2 looks like invalid forward reference
def ra2_:[C2 <: C1](c1: (C1, C2)): C2 =
???
https://scastie.scala-lang.org/4LgQkgomTNijNcj1BjhGPw
More examples here (tests all confusing situations):
https://scastie.scala-lang.org/B4eX394PQbazeycIPqWiXQ
Expectation
Should not compile
Why it happens
Right associative extension methods go through a confusing swap*, for example the method above becomes:
<extension> def ra2_:[C1 <: Int][C2 <: C1](c1: (C1, C2))(c2: (C1, C2))
Which is indeed a valid method (if you ignore the curried type clauses), even though the original is invalid
*At the time of writing, it is described incorrectly in the reference, and a fixed version for it is here
Why it matters
While it is fine to give surprising tricks to language experts, in this case, this can have very confusing repercussions for normal users:
Type C2 = String
extension [C1 <: Int](c2: (C1, C2)) // C2 looks like it is an alias of String, but is actually a subtype of Int !
def ra2_:[C2 <: C1](c1: (C1, C2)): C2 =
???
How to fix it
My proposal is the following:
In case the swapped groups of clauses (leftParams trailingUsing
and rightTyParam rightParam
) have any reference to something defined in the other group, throw an error
The error should clearly explain why it is not allowed, and maybe solutions for the problem