Should given statements in 2.13.16 compile with the "-Xsource:3" flag?

Should all given statements that work in Scala 3.3.6 compile in 2.13.16 with the -Xsource:3 flag? Or is that just wishful thinking on my part?

I have some code that compiles with Scala 3.3.6, but does not compile with 2.13.16:

package object api {
  given Codec[String, IntegerParameter, TextPlain] = {
    def decodeIntegerParameter(s: String): DecodeResult[IntegerParameter] = ???
    def encodeIntegerParameter(integerParameter: IntegerParameter): String = ???
    Codec.string.mapDecode(decodeIntegerParameter)(encodeIntegerParameter)
  }
...//lots of fiddly transcode givens, all nearly identical

which fails in sbt ++2.13.16 api/compile with

type application is not allowed for postfix operators

which is a bit of a throwback to a language feature import. The compiler is trying to make Codec a postfix operator of something named given. That implies the 2.13.16 compiler maybe doesn’t know that given is a keyword with -Xsource:3 .

The crossbuild works with import sttp.tapir.* so the -Xsource:3 parameter is flowing through. That’s probably the simplest thing to translate.

That’s wishful thinking… given declarations are not backported to Scala 2.

Scala 2 with -Xsource:3 | Scala 3 Migration Guide | Scala Documentation is mostly up to date.

1 Like

For posterity

 implicit val integerParameterCodec: Codec[String, IntegerParameter, TextPlain] = { ... }

seems digestible in Scala 2.13.16 and 3.3.6 .

Certain benign syntax features are enabled:
  * case C(xs*) =>
  * A & B type intersection
  * import p.*
  * import p.m as n
  * import p.{given, *}

It knows enough Scala 3 keywords to complain:

scala> val given = "help"
           ^
       warning: Wrap `given` in backticks to use it as an identifier, it will become a keyword in Scala 3. [quickfixable]
val given: String = help

In my opinion it should not be allowed - given definitions is not only change to syntax, but also the semantics in Scala 3:

  • given is essentially a lazy val or def (depending on context)
  • givens might follow different resolution rules, when compared with backward compatible implicits
  • using keyword is required for using arguments, but optional for implicits

So imagine you’re in the middle of migration from Scala 2 to Scala 3, and try to debug some strange bug related to implicits. Just from reading sources (your own, or your dependencies) it would be much harder to figure out what has actually changed and where the problem is.

2 Likes