@@ -81,12 +81,74 @@ object DottyJSPlugin extends AutoPlugin {
8181object Build {
8282 import ScaladocConfigs ._
8383
84+ /** Version of the Scala compiler used to build the artifacts.
85+ * Reference version should track the latest version pushed to Maven:
86+ * - In main branch it should be the last RC version
87+ * - In release branch it should be the last stable release
88+ *
89+ * Warning: Change of this variable needs to be consulted with `expectedTastyVersion`
90+ */
8491 val referenceVersion = " 3.3.5"
8592
86- val baseVersion = " 3.3.6-RC1"
93+ /** Version of the Scala compiler targeted in the current release cycle
94+ * Contains a version without RC/SNAPSHOT/NIGHTLY specific suffixes
95+ * Should be updated ONLY after release or cutoff for previous release cycle.
96+ *
97+ * Should only be referred from `dottyVersion` or settings/tasks requiring simplified version string,
98+ * eg. `compatMode` or Windows native distribution version.
99+ *
100+ * Warning: Change of this variable might require updating `expectedTastyVersion`
101+ */
102+ val developedVersion = " 3.3.6"
103+
104+ /** The version of the compiler including the RC prefix.
105+ * Defined as common base before calculating environment specific suffixes in `dottyVersion`
106+ *
107+ * By default, during development cycle defined as `${developedVersion}-RC1`;
108+ * During release candidate cycle incremented by the release officer before publishing a subsequent RC version;
109+ * During final, stable release is set exactly to `developedVersion`.
110+ */
111+ val baseVersion = s " $developedVersion-RC1 "
112+
113+ /** The version of TASTY that should be emitted, checked in runtime test
114+ * For defails on how TASTY version should be set see related discussions:
115+ * - https://github.com/scala/scala3/issues/13447#issuecomment-912447107
116+ * - https://github.com/scala/scala3/issues/14306#issuecomment-1069333516
117+ * - https://github.com/scala/scala3/pull/19321
118+ *
119+ * Simplified rules, given 3.$minor.$patch = $developedVersion
120+ * - Major version is always 28
121+ * - TASTY minor version:
122+ * - in main (NIGHTLY): {if $patch == 0 || ${referenceVersion.matches(raw"3.$minor.0-RC\d")} then $minor else ${minor + 1}}
123+ * - in LTS branch (NIGHTLY): always equal to $minor
124+ * - in release branch is always equal to $minor
125+ * - TASTY experimental version:
126+ * - in main (NIGHTLY) is always experimental
127+ * - in LTS branch (NIGHTLY) is always non-experimental
128+ * - in release candidate branch is experimental if {patch == 0}
129+ * - in stable release is always non-experimetnal
130+ */
131+ val expectedTastyVersion = " 28.3"
132+ checkReleasedTastyVersion()
133+
134+ /** Final version of Scala compiler, controlled by environment variables. */
135+ val dottyVersion = {
136+ if (isRelease) baseVersion
137+ else if (isNightly) s " ${baseVersion}-bin- ${VersionUtil .commitDate}- ${VersionUtil .gitHash}-NIGHTLY "
138+ else s " ${baseVersion}-bin-SNAPSHOT "
139+ }
140+ def isRelease = sys.env.get(" RELEASEBUILD" ).contains(" yes" )
141+ def isNightly = sys.env.get(" NIGHTLYBUILD" ).contains(" yes" )
142+
143+ /** Version calculate for `nonbootstrapped` projects */
144+ val dottyNonBootstrappedVersion = {
145+ // Make sure sbt always computes the scalaBinaryVersion correctly
146+ val bin = if (! dottyVersion.contains(" -bin" )) " -bin" else " "
147+ dottyVersion + bin + " -nonbootstrapped"
148+ }
87149
88150 // LTS or Next
89- val versionLine = " LTS"
151+ final val versionLine = " LTS"
90152
91153 // Versions used by the vscode extension to create a new project
92154 // This should be the latest published releases.
@@ -95,23 +157,22 @@ object Build {
95157 val publishedDottyVersion = referenceVersion
96158 val sbtDottyVersion = " 0.5.5"
97159
98- /** Version against which we check binary compatibility.
160+ /** LTS version against which we check binary compatibility.
99161 *
100- * This must be the latest published release in the same versioning line.
101- * For example, if the next version is going to be 3.1.4, then this must be
102- * set to 3.1.3. If it is going to be 3.1.0, it must be set to the latest
103- * 3.0.x release.
162+ * This must be the earliest published release in the LTS versioning line.
163+ * For example, if the latest LTS release is be 3.3.4, then this must be
164+ * set to 3.3.0.
104165 */
105- val previousDottyVersion = " 3.3.5 "
166+ val mimaPreviousLTSDottyVersion = " 3.3.0 "
106167
107168 object CompatMode {
108169 final val BinaryCompatible = 0
109170 final val SourceAndBinaryCompatible = 1
110171 }
111172
112173 val compatMode = {
113- val VersionRE = """ ^\d+\.(\d+).(\d+).* """ .r
114- baseVersion match {
174+ val VersionRE = """ ^\d+\.(\d+)\ .(\d+)""" .r
175+ developedVersion match {
115176 case VersionRE (_, " 0" ) => CompatMode .BinaryCompatible
116177 case _ => CompatMode .SourceAndBinaryCompatible
117178 }
@@ -132,24 +193,6 @@ object Build {
132193 val dottyGithubUrl = " https://github.com/scala/scala3"
133194 val dottyGithubRawUserContentUrl = " https://raw.githubusercontent.com/scala/scala3"
134195
135-
136- val isRelease = sys.env.get(" RELEASEBUILD" ) == Some (" yes" )
137-
138- val dottyVersion = {
139- def isNightly = sys.env.get(" NIGHTLYBUILD" ) == Some (" yes" )
140- if (isRelease)
141- baseVersion
142- else if (isNightly)
143- baseVersion + " -bin-" + VersionUtil .commitDate + " -" + VersionUtil .gitHash + " -NIGHTLY"
144- else
145- baseVersion + " -bin-SNAPSHOT"
146- }
147- val dottyNonBootstrappedVersion = {
148- // Make sure sbt always computes the scalaBinaryVersion correctly
149- val bin = if (! dottyVersion.contains(" -bin" )) " -bin" else " "
150- dottyVersion + bin + " -nonbootstrapped"
151- }
152-
153196 val sbtCommunityBuildVersion = " 0.1.0-SNAPSHOT"
154197
155198 val agentOptions = List (
@@ -477,7 +520,7 @@ object Build {
477520 case cv : Disabled => thisProjectID.name
478521 case cv : Binary => s " ${thisProjectID.name}_ ${cv.prefix}3 ${cv.suffix}"
479522 }
480- (thisProjectID.organization % crossedName % previousDottyVersion )
523+ (thisProjectID.organization % crossedName % mimaPreviousLTSDottyVersion )
481524 },
482525
483526 mimaCheckDirection := (compatMode match {
@@ -2032,6 +2075,9 @@ object Build {
20322075 settings(disableDocSetting).
20332076 settings(
20342077 versionScheme := Some (" semver-spec" ),
2078+ Test / envVars ++= Map (
2079+ " EXPECTED_TASTY_VERSION" -> expectedTastyVersion,
2080+ ),
20352081 if (mode == Bootstrapped ) Def .settings(
20362082 commonMiMaSettings,
20372083 mimaBinaryIssueFilters ++= MiMaFilters .TastyCore ,
@@ -2066,6 +2112,49 @@ object Build {
20662112 case Bootstrapped => commonBootstrappedSettings
20672113 })
20682114 }
2115+
2116+ /* Tests TASTy version invariants during NIGHLY, RC or Stable releases */
2117+ def checkReleasedTastyVersion (): Unit = {
2118+ case class ScalaVersion (minor : Int , patch : Int , isRC : Boolean )
2119+ def parseScalaVersion (version : String ): ScalaVersion = version.split(" \\ .|-" ).take(4 ) match {
2120+ case Array (" 3" , minor, patch) => ScalaVersion (minor.toInt, patch.toInt, false )
2121+ case Array (" 3" , minor, patch, _) => ScalaVersion (minor.toInt, patch.toInt, true )
2122+ case other => sys.error(s " Invalid Scala base version string: $baseVersion" )
2123+ }
2124+ lazy val version = parseScalaVersion(baseVersion)
2125+ lazy val referenceV = parseScalaVersion(referenceVersion)
2126+ lazy val (tastyMinor, tastyIsExperimental) = expectedTastyVersion.split(" \\ .|-" ).take(4 ) match {
2127+ case Array (" 28" , minor) => (minor.toInt, false )
2128+ case Array (" 28" , minor, " experimental" , _) => (minor.toInt, true )
2129+ case other => sys.error(s " Invalid TASTy version string: $expectedTastyVersion" )
2130+ }
2131+ val isLTS = versionLine == " LTS"
2132+
2133+ if (isNightly) {
2134+ assert(tastyIsExperimental || isLTS, " TASTY needs to be experimental in nightly builds" )
2135+ val expectedTastyMinor = version.patch match {
2136+ case 0 => version.minor
2137+ case 1 if referenceV.patch == 0 && referenceV.isRC =>
2138+ // Special case for a period when reference version is a new unstable minor
2139+ // Needed for non_bootstrapped tests requiring either stable tasty or the same experimental version produced by both reference and bootstrapped compiler
2140+ assert(version.minor == referenceV.minor, " Expected reference and base version to use the same minor" )
2141+ version.minor
2142+ case _ =>
2143+ if (isLTS) version.minor
2144+ else version.minor + 1
2145+ }
2146+ assert(tastyMinor == expectedTastyMinor, s " Invalid TASTy minor version, expected $expectedTastyMinor, got $tastyMinor" )
2147+ }
2148+
2149+ if (isRelease) {
2150+ assert(version.minor == tastyMinor, " Minor versions of TASTY vesion and Scala version should match in release builds" )
2151+ assert(! referenceV.isRC, " Stable release needs to use stable compiler version" )
2152+ if (version.isRC && version.patch == 0 )
2153+ assert(tastyIsExperimental, " TASTy should be experimental when releasing a new minor version RC" )
2154+ else
2155+ assert(! tastyIsExperimental, " Stable version cannot use experimental TASTY" )
2156+ }
2157+ }
20692158}
20702159
20712160object ScaladocConfigs {
0 commit comments