Skip to content

Deprecate auto-application of (non-Java-defined) methods with a single empty parameter list#8833

Merged
dwijnand merged 1 commit intoscala:2.13.xfrom
dwijnand:fast-deprecate-auto-application
Jun 2, 2020
Merged

Deprecate auto-application of (non-Java-defined) methods with a single empty parameter list#8833
dwijnand merged 1 commit intoscala:2.13.xfrom
dwijnand:fast-deprecate-auto-application

Conversation

@dwijnand
Copy link
Member

@dwijnand dwijnand commented Mar 27, 2020

Auto-application is dropped in Scala 3:
https://dotty.epfl.ch/docs/reference/dropped-features/auto-apply.html

So it must be deprecated in 2.13 first.

Strongly related to deprecating overriding nullary (and the inverse, overriding nilary): #8846.

Example

$ scala -deprecation -e 'println'
...
warning: Auto-application to `()` is deprecated. Supply the empty argument list `()` explicitly to invoke method println,
or remove the empty argument list from its definition (Java-defined methods are exempt).
In Scala 3, an unapplied method like this will be eta-expanded into a function.
println
^

How to fix

It is recommended to add the missing parens:

$ scala -deprecation -e 'println()'

The change can be made manually or by using scala-rewrites' ExplicitNonNullaryApply.

How to suppress

Since 2.13.2, Scala offers -Wconf:... and @nowarn for warning suppression. You can suppress the new warning globally by passing -Wconf:cat=deprecation&msg=Auto-application:silent to the compiler, or you can suppress it locally by adding @nowarn("cat=deprecation&msg=Auto-application") at the call site.

@scala-jenkins scala-jenkins added this to the 2.13.3 milestone Mar 27, 2020
@dwijnand dwijnand force-pushed the fast-deprecate-auto-application branch from 40187f6 to 073c8ef Compare March 27, 2020 09:41
@lrytz lrytz closed this Mar 27, 2020
@lrytz lrytz reopened this Mar 27, 2020
@lrytz
Copy link
Member

lrytz commented Mar 27, 2020

Is there (or could we write) a scalafix rule supporting this change? Scalafix exists for 2.13.1.

@dwijnand dwijnand force-pushed the fast-deprecate-auto-application branch from 073c8ef to 0c40835 Compare March 27, 2020 13:37
@dwijnand dwijnand added the release-notes worth highlighting in next release notes label Mar 31, 2020
@SethTisue
Copy link
Member

Let's leave this one for 2.13.3.

@dwijnand
Copy link
Member Author

dwijnand commented Apr 3, 2020

Is there (or could we write) a scalafix rule supporting this change?

lightbend-labs/scala-rewrites#14

@dwijnand dwijnand force-pushed the fast-deprecate-auto-application branch 2 times, most recently from 31fbcf6 to d51c962 Compare April 9, 2020 21:12
@SethTisue SethTisue added the prio:hi high priority (used only by core team, only near release time) label May 12, 2020
@dwijnand dwijnand force-pushed the fast-deprecate-auto-application branch from d51c962 to c78ffa1 Compare May 20, 2020 07:00
@dwijnand dwijnand force-pushed the fast-deprecate-auto-application branch from c78ffa1 to f6c89f7 Compare June 1, 2020 06:55
Auto-application is dropped in Scala 3:
https://dotty.epfl.ch/docs/reference/dropped-features/auto-apply.html

So it must be deprecated in 2.13 first.

Also, AFAICT Object_clone is Java-defined:

    $ qscala
    Welcome to Scala 2.13.2-20200325-150327-bc1cad4 (OpenJDK 64-Bit Server VM, Java 11.0.6).
    Type in expressions for evaluation. Or try :help.

    scala> :power
    Power mode enabled. :phase is at typer.
    import scala.tools.nsc._, intp.global._, definitions._
    Try :help or completions for vals._ and power._

    scala> Object_clone.isJavaDefined
    val res0: Boolean = true
@SethTisue SethTisue force-pushed the fast-deprecate-auto-application branch from f6c89f7 to c900df8 Compare June 1, 2020 22:32
Copy link
Member

@SethTisue SethTisue left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

force-pushed to bump the deprecated-since from 2.13.2 to 2.13.3. let's merge as soon as CI likes it again

@SethTisue SethTisue changed the title Fast-track deprecating auto-application Deprecate auto-application of (non-Java-defined) methods with a single empty parameter list Jun 1, 2020
@SethTisue SethTisue removed the prio:hi high priority (used only by core team, only near release time) label Jun 1, 2020
@SethTisue

This comment has been minimized.

rtyley added a commit to guardian/tagmanager that referenced this pull request Oct 22, 2024
…`()` is deprecated

Scala 2.13 deprecates (with PR scala/scala#8833) the old behaviour of Scala that zero-parameter methods could be called with either one or zero pairs of parenthesis - ie if you have a method `def foo()` you could call it as `foo()` or just `foo`. With Scala 3, you have to match the number of brackets *used in the method declaration* when you call it - so you'd _have_ to use `foo()` or you'd get an error like this:

```
[error] ~/code/presence-indicator/app/actor/OpenSocketActor.scala:79:7: Auto-application to `()` is deprecated. Supply the empty argument list `()` explicitly to invoke method sender,
[error] or remove the empty argument list from its definition (Java-defined methods are exempt).
[error] In Scala 3, an unapplied method like this will be eta-expanded into a function. [quickfixable]
[error]       sender ! Map(serverId -> (LiveActors(connectionPing, subscription)))
[error]       ^
```

Java methods are exempt from this restriction - you can call either `hashCode()` (which, in Java, is how the method _has_ to be defined, with empty brackets) or just `hashCode` (which is how that method would have been declared if it was declared in Scala, in Scala methods with no side-effects should be declared without brackets: https://docs.scala-lang.org/style/method-invocation.html#arity-0).

## Automatically fixing this code issue

There are two possible ways of automating this code fix - in this small project, they both produce the same code changes:

### Fixing if the project is already on Scala 2.13 - use `-quickfix` in `scalac`

You can use the `-quickfix` support added to Scala 2.13.12 with scala/scala#10482:

Add either of these to the `scalacOptions` in `build.sbt`:

* `"-quickfix:any"`  ...to apply *all* available quick fixes
* `"-quickfix:msg=Auto-application"`  ...to apply quick fixes where the message contains "Auto-application"

Then run `compile` on the sbt console - the first compile will still fail, but it will subtly change the error message to say `[rewritten by -quickfix]` - your files have been edited to receive the fix:

```
[error] /Users/Roberto_Tyley/code/presence-indicator/app/actor/OpenSocketActor.scala:79:7: [rewritten by -quickfix] Auto-application to `()` is deprecated. Supply the empty argument list `()` explicitly to invoke method sender,
[error] or remove the empty argument list from its definition (Java-defined methods are exempt).
[error] In Scala 3, an unapplied method like this will be eta-expanded into a function.
[error]       sender ! Map(serverId -> (LiveActors(connectionPing, subscription)))
[error]       ^
```

...run `compile` a second time, and compiler will be much happier.

Examples of other PRs using `-quickfix` to fix this code issue:

* guardian/ophan#5719

### Fixing while still on Scala 2.12 - use Scalafix

Fixing this everywhere in a project can be tedious, but thankfully there is a `ExplicitNonNullaryApply` Scalafix rule to fix this in the https://github.com/lightbend-labs/scala-rewrites project.

The Scalafix rule needs to be run while the project is still on Scala 2.12, not Scala 2.13 (otherwise sbt will say: "Error downloading ch.epfl.scala:sbt-scalafix;sbtVersion=1.0;scalaVersion=2.13:0.13.0").

Once the Scalafix plugin is made available to sbt (by adding `addSbtPlugin("ch.epfl.scala" % "sbt-scalafix" % "0.13.0")`
to either `project/plugins.sbt` or `~/.sbt/1.0/plugins.sbt`), you can run these commands on the sbt prompt to automatically generate the changes in this PR:

```
scalafixEnable
scalafixAll dependency:fix.scala213.ExplicitNonNullaryApply@org.scala-lang:scala-rewrites:0.1.5
```

Examples of other PRs using Scalafix to fix this code issue:

* guardian/mobile-apps-api#2728
* guardian/presence-indicator#196

See also:

* scalacenter/scalafix#204
* lightbend-labs/scala-rewrites#14
hamzaremmal pushed a commit to hamzaremmal/scala3 that referenced this pull request May 2, 2025
…-application

Deprecate auto-application of (non-Java-defined) methods with a single empty parameter list
hamzaremmal pushed a commit to scala/scala3 that referenced this pull request May 7, 2025
…-application

Deprecate auto-application of (non-Java-defined) methods with a single empty parameter list
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

release-notes worth highlighting in next release notes

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants