Understanding the `XSource` option

#1

I’m working on a library that cross-compiles to Scala 2.11 and 2.12 (as well as 2.13 in the not too distant future). This can be a frustrating experience at times. Recently I had a problem where I wanted to use Scala 2.12 functionality (specifically, overriding an apply method of a case class, which works fine in 2.12 but gives ambiguity errors in 2.11). After some fiddling I found out I could add a flag to the compiler: Xsource:2.12. What does this flag really do?

The documentation says:

Treat compiler input as Scala source for the specified version, see SI-8126

This doesn’t mean much to me. Does it mean that the compiler treats all my source as Scala 2.12 but compiles it to 2.11 JVM bytecode? Are there any downsides to adding this compiler flag?

#2

The Xsource option let’s you generate code for a specific Scala version, but I think you need something different, something that allows you to code differences in Scala 2.11 and Scala 2.12 by separate and use them in the same project, so here a sample about it ->

As explained in the sample, it’s just a hello world, but demonstrate how to have the same trait (in this case the HelloWorld trait) in difference source folders (one for each Scala version) and they can behave slightly different (in this case is just a String that as a sample is different) but in a real World case you may catch an exception in one version that in other does not occur or a patch of code at previous Scala version that do not exists yet but it can be add it ad hoc, etc.

Best regards,

Carlos

#3

No, this is an option for backward compatibility. It makes the compiler accept unsound (legacy) code which it would otherwise reject due to fixes it has implemented. So you might be able to compile code which was accepted by an older compiler with a newer compiler that would normally reject it.

~If course, it does not work the other way around, you cannot make a Scala 2.11 compiler accept Scala 2.12 code.~ It seems that this option indeed also goes forward, not only backward. That would allow you to use features of the language only the next version would accept or constrain the use of deprecated features that are deprecated and will be removed in the next version.

#4

Thanks for getting back to me. I still don’t think I understand this flag completely. I’m running tests on CI for both 2.11 and 2.12, and tests pass for both versions. This is with code that prior to adding the XSource flag did not compile.

Why is this?

#5

This depends on the code of course. Show the relevant code and error you get and someone could probably pinpoint the issue.

For example, the fix for Scala bug 6541 is behind the -XSource:2.12 switch. Maybe you hit this one?

#6

I’ve made a small Scastie example: https://scastie.scala-lang.org/torkelrogstad/PBfi92FVSAyM5Pl1kzyqzw/1

Note that if you remove the added scalac option from the build config, the project does not compile.

#7

This is a feature of Scala 2.11.11, which allows user defined apply and unapply methods for case classes in the companion object. From the release notes:

  • #5730, #5846 Allow custom apply and unapply methods in case class companions. Also allows case class constructors and apply methods to be private. (In 2.11.11, -Xsource:2.12 is needed to enable these changes. In Scala 2.12.2, they are on by default.)
1 Like
#8

Note that I would not recommend using -Xsource in production code. Enabling it, regardless of whether you use it to go forwards or backwards in time, gives you a combination of language features and compiler behaviors that have received only limited testing.

The flag can be useful for experiments and for migration; you might temporarily enable it as one stage of a migration process.