Compile error calling def on package object with overload in Trait

While upgrading a third party library (Circe) I’ve encountered a compilation failure, that on the surface looks like a compiler bug (tested with various versions of 2.13, including 2.13.18).

Short background:

In Circe 0.14.x, the parser package object was the entry point for the default parser, by invoking io.circe.yaml.parser.parse(Reader) or io.circe.yaml.parser.parse(String).

In Circe 0.15.0, the parser package object was changed to extend a Parser trait, and calls to the Reader variant are now failing compilation, claiming that a String is expected.

This was reported as Can't call io.circe.yaml.parser.parse on an input stream reader in 0.15.1 · Issue #410 · circe/circe-yaml · GitHub , which included a minimal reproducer:

object X extends App {
  B.f(0)
}

trait A {
  def f(x: String): String
}

package object B extends A {
  def f(x: Int): String    = ???
  def f(x: String): String = ???
}

This code fails to compile with the error:

type mismatch;
found : Int(0)
required: String
B.f(0)
^

If the package object B is changed to an object B then this code compiles.

Interestingly:

  • if the f(Int) def is pulled up to the trait, then the code compiles.
  • if the f(Int) def is pulled up to a parent trait of A, then the problem inverts - calls to f(Int) compile, but calls to f(String) do not.

Is there some restriction on package objects I’m not aware of here, or is this just a Scala compiler bug?

It’s a bug.

The restriction is that package objects were always a bit buggy.

Scala 3 fixed that by introducing “top-level defs” and more package objects, instead of deprecating them as hopeless.

The example compiles in Scala 3 if wrapped in an enclosing package, since the empty package can’t be accessed from a named package (even in the same file).

4 Likes

I’m afraid there is no hope for Scala 2 issue numbers to keep up with Scala 3 issue numbers, which are closing in on 25,000. The sum of scala/scala and scala/bug is just over 24,000.

1 Like