-
Notifications
You must be signed in to change notification settings - Fork 1.1k
Parse unary operators as regular identifiers when followed by square brackets #14299
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
Conversation
Clever tweak! |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
What is the reason for the change? I guess we all agree that a +
operation as in the test is very bad style. Why encourage it with the change to the parsing rules?
I find it also concerning that
+(6)
and
+[Int](6)
now are parsed differently. This goes counter to the intuition that type arguments are optional.
My team is building a DSL on top of Scala. We are using Scalameta to parse right now and it has this behavior. I thought it was harmless to include, and possibly even intended given Scalameta's choice. The ambiguity around unary ops in Scala is already pretty surprising -- most on my team are very surprised that Note that right now, if you define the def +[T](x: T): String = "x"
`+`[Int](5) does not parse. If such a function can be defined but not invoked, it seems better to disallow them altogether. In general, I think it would be nice if unary operators were more like class Foo {
def apply(x: (Int, Int)): String = "5"
}
def foo(x: Int): Int = 5
locally {
val foo = new Foo
foo(5, 6): String
} compiles just fine, but fails to compile if |
There is an historically very consistent expectation that backticks should do something here. ("Neutralize" unary syntax? Un-unary?) (The ticket for things named The idea to defer interpretation of "can be defined but not invoked" says too much, because you can always |
scalameta is definitely not the canonical arbiter of Scala syntax. Unary There is one legitimate use case that I can see: To invoke an extension method in direct style. Say you have object obj:
extension (x: T) def + (y: T) Then you want to be able to call obj.+(a)(b) |
I did not mean to imply that scalameta is authoritative, just that it was indication that this area was at least not clearly specified. I think you'll agree that that the situation with Happy to close the PR since this is a very minor point for us. IMHO it would be more inline with my expectations that backticked |
worth adding that scala 2 is also not authoritative, because it accepts infix type args out of spec, but it does accept the syntax under discussion, which is within spec, or "within tolerance" as the engineers say, which for us means our tolerance for the weird syntax:
|
Maintaining backwards compatibility where possible is a reasonable argument in favor? |
Yes, but it needs to be weighed against the argument that Scala 3 is about cleaning up the language. So backwards compatibility is not an absolute here. I still think that accepting the syntax was a bug, and Scala 3 fixed it. I can already see the puzzler in my head that would exploit the Scala 2 behavior. |
Currently,
+(6)
parses as a unary+
on the expression6
and+[Int](6)
does not parse at all because[Int](6)
is not the legal start of an expression. This PR makes+[Int](y)
parse as regular apply by removing[
from the set of tokens that can follow a unary operator. I believe this is safe because although[
can begin an expression, it can only begin a typed lambda like[T] => T => Int
, and a+
could not parse as a unary operator on such an expression in any case. This also happens to be the behavior of Scalameta. I'm not sure which behavior is correct but I believe there is no reason to disallow this behavior.