Overzealous warning from scala compiler: Auto-application to `()` is deprecated

I’m copying this message here from discord, as it may need additional discussion and reflection.

Can someone help me understand this compiler warning.

[warn] /Users/jnewton/Repos/regular-type-expression/cl-robdd-scala/src/test/scala/bdd/BddTestSuite.scala:93:36: Auto-application to `()` is deprecated. Supply the empty argument list `()` explicitly to invoke method size,
[warn] or remove the empty argument list from its definition (Java-defined methods are exempt).
[warn] In Scala 3, an unapplied method like this will be eta-expanded into a function.
[warn]           case _: BddTerm => assert(bdd.size() == 1)
[warn]                                    ^

Is this really a warning, telling me to do what I’m already doing? or is it rather just an info message and should not be a warning at all? Or am I reading the message wrong?

Is the message telling me to omit the () or to keep them there?

I’m confused.

Here is the offending code

  def genSamples(): Set[Bdd] = {
    ...
  }

  test("size") {
    withNewBddHash {

      val samples = genSamples()

      for (bdd <- samples) {
        bdd match {
          case _: BddTerm => assert(bdd.size() == 1)
          case b: BddNode => assert(bdd.size() <= 1 + b.positive.size() + b.negative.size()) // maybe less because some nodes or terms might be shared
        }
      }
    }
  }

The size method is indeed defined using parens ()

sealed abstract class Bdd {
  ...
  
  def size():Int = {
    ...
  }
...
}

Can’t reproduce: Scastie - An interactive playground for Scala.

What is that withNewBddHash {? Feels like something that would do dark magic at compile / runtime; which may be related to the error.

Nothing strange here. Do you think the compiler gets confused inside call-by-name code?

  val maybeNodeHash = new DynamicVariable[Option[Cache]](None)

  // wrapper for all code which needs to calculate with Bdds.  The Bdd
  //   calculations need a hash map to enforce structural identity.
  //   Attempt to construct a Bdd outside the dynamic extend of this
  //   function results in an error.
  def withNewBddHash[A](code: => A): A = {
    maybeNodeHash.withValue(Some(newCache())) {
      code
    }
  }

Do you think the compiler gets confused inside call-by-name code?

Inside call by name, no.
But maybe the DynamicVariable may be related. Anyways, without a reproducible example is impossible to help.

To answer the question, this warning is straightforward, but parens are surprisingly tricky.

The caret is pointing at the apply paren for assert, which is wrong.

I’d recommend -Vprint:parser,typer,refchecks which will show what the trees really look like. If you turn on -Werror and it’s emitting this warning, it will error out after typer.

I’ve been always cross-compiling with Scala 3, in case one compiler gives better messaging.

assert is probably a scalatest macro so I guess that it’s generating code that the compiler doesn’t like anymore. You could try using the latest scalatest version and see if that fixes it.

2 Likes

I’ve updated to scalatest 3.2.15, and the error seems to still be there.

libraryDependencies += "org.scalactic" %% "scalactic" % "3.2.15"
libraryDependencies += "org.scalatest" %% "scalatest" % "3.2.15" % "test"

I reported the issue with scalatest

The workaround suggested by the developers is to use Predef.assert() rather than assert().

Looks like they also merged a fix.

1 Like