Skip to content

Consistent naming of output-version settings #14606

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 1 commit into from
Mar 2, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -161,7 +161,7 @@ final case class SbtCommunityProject(

def withScalaRelease(release: String): SbtCommunityProject =
this.copy(
scalacOptions = scalacOptions ++ Seq("-Yscala-release", release)
scalacOptions = scalacOptions ++ Seq("-scala-output-version", release)
)

object SbtCommunityProject:
Expand Down
6 changes: 3 additions & 3 deletions compiler/src/dotty/tools/backend/jvm/BCodeIdiomatic.scala
Original file line number Diff line number Diff line change
Expand Up @@ -27,14 +27,14 @@ trait BCodeIdiomatic {


lazy val target =
val releaseValue = Option(ctx.settings.release.value).filter(_.nonEmpty)
val targetValue = Option(ctx.settings.Xtarget.value).filter(_.nonEmpty)
val releaseValue = Option(ctx.settings.javaOutputVersion.value).filter(_.nonEmpty)
val targetValue = Option(ctx.settings.XuncheckedJavaOutputVersion.value).filter(_.nonEmpty)
val defaultTarget = "8"
(releaseValue, targetValue) match
case (Some(release), None) => release
case (None, Some(target)) => target
case (Some(release), Some(_)) =>
report.warning(s"The value of ${ctx.settings.Xtarget.name} was overridden by ${ctx.settings.release.name}")
report.warning(s"The value of ${ctx.settings.XuncheckedJavaOutputVersion.name} was overridden by ${ctx.settings.javaOutputVersion.name}")
release
case (None, None) => "8" // least supported version by default

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ sealed trait ZipAndJarFileLookupFactory {
private val cache = new FileBasedCache[ClassPath]

def create(zipFile: AbstractFile)(using Context): ClassPath =
val release = Option(ctx.settings.release.value).filter(_.nonEmpty)
val release = Option(ctx.settings.javaOutputVersion.value).filter(_.nonEmpty)
if (ctx.settings.YdisableFlatCpCaching.value || zipFile.file == null) createForZipFile(zipFile, release)
else createUsingCache(zipFile, release)

Expand Down
2 changes: 1 addition & 1 deletion compiler/src/dotty/tools/dotc/config/PathResolver.scala
Original file line number Diff line number Diff line change
Expand Up @@ -207,7 +207,7 @@ class PathResolver(using c: Context) {

// Assemble the elements!
def basis: List[Traversable[ClassPath]] =
val release = Option(ctx.settings.release.value).filter(_.nonEmpty)
val release = Option(ctx.settings.javaOutputVersion.value).filter(_.nonEmpty)

List(
JrtClassPath(release), // 1. The Java 9+ classpath (backed by the jrt:/ virtual system, if available)
Expand Down
7 changes: 4 additions & 3 deletions compiler/src/dotty/tools/dotc/config/ScalaSettings.scala
Original file line number Diff line number Diff line change
Expand Up @@ -103,7 +103,9 @@ trait CommonScalaSettings:
val pageWidth: Setting[Int] = IntSetting("-pagewidth", "Set page width", ScalaSettings.defaultPageWidth, aliases = List("--page-width"))
val silentWarnings: Setting[Boolean] = BooleanSetting("-nowarn", "Silence all warnings.", aliases = List("--no-warnings"))

val release: Setting[String] = ChoiceSetting("-release", "release", "Compile code with classes specific to the given version of the Java platform available on the classpath and emit bytecode for this version.", ScalaSettings.supportedReleaseVersions, "", aliases = List("--release"))
val javaOutputVersion: Setting[String] = ChoiceSetting("-java-output-version", "version", "Compile code with classes specific to the given version of the Java platform available on the classpath and emit bytecode for this version. Corresponds to -release flag in javac.", ScalaSettings.supportedReleaseVersions, "", aliases = List("-release", "--release"))
Copy link
Member

Choose a reason for hiding this comment

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

Could you make a PR to Scala 2 to also rename -release there?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I'm not sure we should rename it for scala 2 as the semantics of -release and -target are slightly different there #8634 (comment)

Copy link
Member

Choose a reason for hiding this comment

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

Yeah I think that would also require changing the scala 2 flag to also set the target, IMO the current behavior is an oversight.

Copy link
Contributor

Choose a reason for hiding this comment

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

scala/bug#12543

without over-promising, maybe I'll take the opportunity to understand the issues and ergonomics.

val scalaOutputVersion: Setting[String] = ChoiceSetting("-scala-output-version", "version", "Emit TASTy files that can be consumed by specified version of the compiler. The compilation will fail if for any reason valid TASTy cannot be produced (e.g. the code contains references to some parts of the standard library API that are missing in the older stdlib or uses language features unexpressible in the older version of TASTy format)", ScalaSettings.supportedScalaReleaseVersions, "")

val deprecation: Setting[Boolean] = BooleanSetting("-deprecation", "Emit warning and location for usages of deprecated APIs.", aliases = List("--deprecation"))
val feature: Setting[Boolean] = BooleanSetting("-feature", "Emit warning and location for usages of features that should be imported explicitly.", aliases = List("--feature"))
val explain: Setting[Boolean] = BooleanSetting("-explain", "Explain errors in more detail.", aliases = List("--explain"))
Expand Down Expand Up @@ -221,7 +223,7 @@ private sealed trait XSettings:
val XignoreScala2Macros: Setting[Boolean] = BooleanSetting("-Xignore-scala2-macros", "Ignore errors when compiling code that calls Scala2 macros, these will fail at runtime.")
val XimportSuggestionTimeout: Setting[Int] = IntSetting("-Ximport-suggestion-timeout", "Timeout (in ms) for searching for import suggestions when errors are reported.", 8000)
val Xsemanticdb: Setting[Boolean] = BooleanSetting("-Xsemanticdb", "Store information in SemanticDB.", aliases = List("-Ysemanticdb"))
val Xtarget: Setting[String] = ChoiceSetting("-Xtarget", "target", "Emit bytecode for the specified version of the Java platform. This might produce bytecode that will break at runtime. When on JDK 9+, consider -release as a safer alternative.", ScalaSettings.supportedTargetVersions, "", aliases = List("--Xtarget"))
val XuncheckedJavaOutputVersion: Setting[String] = ChoiceSetting("-Xunchecked-java-output-version", "target", "Emit bytecode for the specified version of the Java platform. This might produce bytecode that will break at runtime. Corresponds to -target flag in javac. When on JDK 9+, consider -java-output-version as a safer alternative.", ScalaSettings.supportedTargetVersions, "", aliases = List("-Xtarget", "--Xtarget"))
val XcheckMacros: Setting[Boolean] = BooleanSetting("-Xcheck-macros", "Check some invariants of macro generated code while expanding macros", aliases = List("--Xcheck-macros"))
val XmainClass: Setting[String] = StringSetting("-Xmain-class", "path", "Class for manifest's Main-Class entry (only useful with -d <jar>)", "")
val XimplicitSearchLimit: Setting[Int] = IntSetting("-Ximplicit-search-limit", "Maximal number of expressions to be generated in an implicit search", 50000)
Expand Down Expand Up @@ -310,7 +312,6 @@ private sealed trait YSettings:
val YexplicitNulls: Setting[Boolean] = BooleanSetting("-Yexplicit-nulls", "Make reference types non-nullable. Nullable types can be expressed with unions: e.g. String|Null.")
val YcheckInit: Setting[Boolean] = BooleanSetting("-Ysafe-init", "Ensure safe initialization of objects")
val YrequireTargetName: Setting[Boolean] = BooleanSetting("-Yrequire-targetName", "Warn if an operator is defined without a @targetName annotation")
val YscalaRelease: Setting[String] = ChoiceSetting("-Yscala-release", "release", "Emit TASTy files that can be consumed by specified version of the compiler. The compilation will fail if for any reason valid TASTy cannot be produced (e.g. the code contains references to some parts of the standard library API that are missing in the older stdlib or uses language features unexpressible in the older version of TASTy format)", ScalaSettings.supportedScalaReleaseVersions, "", aliases = List("--Yscala-release"))

/** Area-specific debug output */
val YexplainLowlevel: Setting[Boolean] = BooleanSetting("-Yexplain-lowlevel", "When explaining type errors, show types at a lower level.")
Expand Down
4 changes: 2 additions & 2 deletions compiler/src/dotty/tools/dotc/core/Contexts.scala
Original file line number Diff line number Diff line change
Expand Up @@ -486,15 +486,15 @@ object Contexts {
fresh.setImportInfo(ImportInfo(sym, imp.selectors, imp.expr))

def scalaRelease: ScalaRelease =
val releaseName = base.settings.YscalaRelease.value
val releaseName = base.settings.scalaOutputVersion.value
if releaseName.nonEmpty then ScalaRelease.parse(releaseName).get else ScalaRelease.latest

def tastyVersion: TastyVersion =
import math.Ordered.orderingToOrdered
val latestRelease = ScalaRelease.latest
val specifiedRelease = scalaRelease
if specifiedRelease < latestRelease then
// This is needed to make -Yscala-release a no-op when set to the latest release for unstable versions of the compiler
// This is needed to make -scala-output-version a no-op when set to the latest release for unstable versions of the compiler
// (which might have the tasty format version numbers set to higher values before they're decreased during a release)
TastyVersion.fromStableScalaRelease(specifiedRelease.majorVersion, specifiedRelease.minorVersion)
else
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ class MultiReleaseJarTest extends dotty.tools.backend.jvm.DottyBytecodeTest {
given ctx: Context = initCtx.fresh
ctx.settings.usejavacp.update(true)
ctx.settings.classpath.update(jarPath.toAbsolutePath.toString)
ctx.settings.release.update(release)
ctx.settings.javaOutputVersion.update(release)
ctx.initialize()
val classNames = Seq("p1.Foo", "p2.Bar")
val classFiles = classNames.flatMap(ctx.platform.classPath.findClassFile)
Expand Down Expand Up @@ -75,7 +75,7 @@ class MultiReleaseJarTest extends dotty.tools.backend.jvm.DottyBytecodeTest {
def classExists(className: String, release: String): Boolean = {
given ctx: Context = initCtx.fresh
ctx.settings.usejavacp.update(true)
ctx.settings.release.update(release)
ctx.settings.javaOutputVersion.update(release)
ctx.initialize()
val classFile = ctx.platform.classPath.findClassFile(className)
classFile.isDefined
Expand Down
2 changes: 1 addition & 1 deletion compiler/test/dotty/tools/vulpix/ParallelTesting.scala
Original file line number Diff line number Diff line change
Expand Up @@ -216,7 +216,7 @@ trait ParallelTesting extends RunnerOrchestration { self =>

case testSource @ SeparateCompilationSource(_, dir, flags, outDir) =>
testSource.compilationGroups.map { (group, files) =>
val flags1 = if group.release.isEmpty then flags else flags.and("-Yscala-release", group.release)
val flags1 = if group.release.isEmpty then flags else flags.and("-scala-output-version", group.release)
if group.compiler.isEmpty then
compile(files, flags1, suppressErrors, outDir)
else
Expand Down
2 changes: 1 addition & 1 deletion docs/_docs/contributing/testing.md
Original file line number Diff line number Diff line change
Expand Up @@ -134,7 +134,7 @@ When the sources of a test consist of multiple source files places in a single d
There are also other suffixes indicating how some particular files are compiled:
* `_c${compilerVersion}` - compile a file with a specific version of the compiler instead of the one developed on the current branch
(e.g. `Foo_c3.0.2.scala`)
* `_r${release}` - compile a file with a given value of `-Yscala-release` flag (e.g. `Foo_r3.0.scala`)
* `_r${release}` - compile a file with a given value of `-scala-output-version` flag (e.g. `Foo_r3.0.scala`)

Different suffixes can be mixed together (their order is not important although consistency is advised), e.g. `Foo_1_r3.0`, `Bar_2_c3.0.2`.

Expand Down
10 changes: 5 additions & 5 deletions docs/_docs/reference/language-versions/binary-compatibility.md
Original file line number Diff line number Diff line change
Expand Up @@ -14,14 +14,14 @@ TASTy version number has the format of `<major_version>.<minor_version>-<experim
Being able to bump the compiler version in a project without having to wait for all of its dependencies to do the same is already a big leap forward when compared to Scala 2. However, we might still try to do better, especially from the perspective of authors of libraries.
If you maintain a library and you would like it to be usable as a dependency for all Scala 3 projects, you would have to always emit TASTy in a version that would be readble by everyone, which would normally mean getting stuck at 3.0.x forever.

To solve this problem a new experimental compiler flag `-Yscala-release <release-version>` (available since 3.1.2-RC1) has been added. Setting this flag makes the compiler produce TASTy files that should be possible to use by all Scala 3 compilers in version `<release-version>` or newer (this flag was inspired by how `-release` works for specifying the target version of JDK). More specifically this enforces emitting TASTy files in an older format ensuring that:
* the code contains no references to parts of the standard library which were added to the API after `<release-version>` and would crash at runtime when a program is executed with the older version of the standard library on the classpath
* no dependency found on the classpath during compilation (except for the standard library itself) contains TASTy files produced by a compiler newer than `<release-version>` (otherwise they could potentially leak such disallowed references to the standard library).
To solve this problem a new experimental compiler flag `-scala-output-version <version>` (available since 3.1.2) has been added. Setting this flag makes the compiler produce TASTy files that should be possible to use by all Scala 3 compilers in version `<version>` or newer. This flag was inspired by how `-java-output-version` (formerly `-release`) works for specifying the target version of JDK. More specifically this enforces emitting TASTy files in an older format ensuring that:
* the code contains no references to parts of the standard library which were added to the API after `<version>` and would crash at runtime when a program is executed with the older version of the standard library on the classpath
* no dependency found on the classpath during compilation (except for the standard library itself) contains TASTy files produced by a compiler newer than `<version>` (otherwise they could potentially leak such disallowed references to the standard library).

If any of the checks above is not fulfilled or for any other reason older TASTy cannot be emitted (e.g. the code uses some new language features which cannot be expressed the the older format) the entire compilation fails (with errors reported for each of such issues).

As this feature is experimental it does not have any special support in build tools yet (at least not in sbt 1.6.1 or lower).
E.g. when a project gets compiled with Scala compiler `3.x1.y1` and `-Yscala-release 3.x2` option and then published using sbt
E.g. when a project gets compiled with Scala compiler `3.x1.y1` and `-scala-output-version 3.x2` option and then published using sbt
then the standard library in version `3.x1.y1` gets added to the project's dependencies instead of `3.x2.y2`.
When the dependencies are added to the classpath during compilation with Scala `3.x2.y2` the compiler will crash while trying to read TASTy files in the newer format.
A currently known workaround is to modify the build definition of the dependent project by explicitly overriding the version of Scala standard library in dependencies, e.g.
Expand All @@ -33,4 +33,4 @@ dependencyOverrides ++= Seq(
)
```

The behaviour of `-Yscala-release` flag might still change in the future, especially it's not guaranteed that every new version of the compiler would be able to generate TASTy in all older formats going back to the one produced by `3.0.x` compiler.
The behaviour of `-scala-output-version` flag might still change in the future, especially it's not guaranteed that every new version of the compiler would be able to generate TASTy in all older formats going back to the one produced by `3.0.x` compiler.