scala / scala3

The Scala 3 compiler, also known as Dotty.
https://dotty.epfl.ch
Apache License 2.0
5.8k stars 1.04k forks source link

Exported nullary methods from java-defined classes require parentheses #17589

Open prolativ opened 1 year ago

prolativ commented 1 year ago

Compiler version

3.3.1-RC1-bin-20230524-5262680-NIGHTLY and before

Minimized code

class StringBox(inner: String):
  export inner.length

val l = StringBox("abc").length

Output

[error] Export.scala:4:9
[error] method length in class StringBox must be called with () argument
[error] val l = StringBox("abc").length
[error]         ^^^^^^^^^^^^^^^^^^^^^^^

Expectation

This should compile. In general, it should be possible to call nullary methods exported from java-defined classes without parentheses.

odersky commented 1 year ago

Why? We demand parentheses to be exact for Scala-compiled methods, and forwarders are Scala-compiled.

prolativ commented 1 year ago

My reasoning is that when someone defines a proxy-like class analogous to StringBox above, they might expect all methods to be proxied directly so that a consumer of the API can use an instance of the boxing class in the same way they would use the underlying class

odersky commented 1 year ago

That would mean we treat Java and Scala classes alike (which is what we did originally, () were optional everywhere). But that just introduced too many ways to do the same thing. So now the rules are stricter for Scala classes, but for Java classes we have to make an exception because nobody wants to add () to all toString calls. For proxy classes we have to draw the line somewhere and the Scala/Java distinction is the one that's simplest.

som-snytt commented 1 year ago

I was momentarily nonplussed by the loss of convenience, but the feature doc is explicit about what an "alias" is.

(As a user, I would naively expect export aliases to be no more restrictive than import aliases, similar to what prolativ suggests.)

The doc lists what magical properties are preserved, such as stability, implicitness, extension, etc. It could also document that "Java-defined" is not preserved. Now I also wonder if there is an interaction with explicit nulls.