Skip to content

Commit ba8dce4

Browse files
committed
Solve mima issue (by doubling private method definition)
1 parent 304d1d5 commit ba8dce4

File tree

2 files changed

+101
-3
lines changed

2 files changed

+101
-3
lines changed

compiler/src/dotty/tools/tasty/besteffort/BestEffortTastyHeaderUnpickler.scala

Lines changed: 100 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ package dotty.tools.tasty.besteffort
33
import java.util.UUID
44

55
import BestEffortTastyFormat.{MajorVersion, MinorVersion, ExperimentalVersion, bestEffortHeader, header}
6-
import dotty.tools.tasty.{UnpicklerConfig, TastyHeaderUnpickler, TastyReader, UnpickleException, TastyFormat}
6+
import dotty.tools.tasty.{UnpicklerConfig, TastyHeaderUnpickler, TastyReader, UnpickleException, TastyFormat, TastyVersion}
77

88
/**
99
* The Best Effort Tasty Header consists of six fields:
@@ -33,7 +33,7 @@ sealed abstract case class BestEffortTastyHeader(
3333
)
3434

3535
class BestEffortTastyHeaderUnpickler(config: UnpicklerConfig, reader: TastyReader) {
36-
import TastyHeaderUnpickler._
36+
import BestEffortTastyHeaderUnpickler._
3737
import reader._
3838

3939
def this(reader: TastyReader) = this(UnpicklerConfig.generic, reader)
@@ -75,3 +75,101 @@ class BestEffortTastyHeaderUnpickler(config: UnpicklerConfig, reader: TastyReade
7575
if (!cond) throw new UnpickleException(msg)
7676
}
7777
}
78+
79+
// Copy pasted from dotty.tools.tasty.TastyHeaderUnpickler
80+
// Since that library has strong compatibility guarantees, we do not want
81+
// to add any more methods just to support an experimental feature
82+
// (like best-effort compilation options).
83+
object BestEffortTastyHeaderUnpickler {
84+
85+
private def check(cond: Boolean, msg: => String): Unit = {
86+
if (!cond) throw new UnpickleException(msg)
87+
}
88+
89+
private def checkValidVersion(fileMajor: Int, fileMinor: Int, fileExperimental: Int, toolingVersion: String, config: UnpicklerConfig) = {
90+
val toolMajor: Int = config.majorVersion
91+
val toolMinor: Int = config.minorVersion
92+
val toolExperimental: Int = config.experimentalVersion
93+
val validVersion = TastyFormat.isVersionCompatible(
94+
fileMajor = fileMajor,
95+
fileMinor = fileMinor,
96+
fileExperimental = fileExperimental,
97+
compilerMajor = toolMajor,
98+
compilerMinor = toolMinor,
99+
compilerExperimental = toolExperimental
100+
)
101+
check(validVersion, {
102+
// failure means that the TASTy file cannot be read, therefore it is either:
103+
// - backwards incompatible major, in which case the library should be recompiled by the minimum stable minor
104+
// version supported by this compiler
105+
// - any experimental in an older minor, in which case the library should be recompiled by the stable
106+
// compiler in the same minor.
107+
// - older experimental in the same minor, in which case the compiler is also experimental, and the library
108+
// should be recompiled by the current compiler
109+
// - forward incompatible, in which case the compiler must be upgraded to the same version as the file.
110+
val fileVersion = TastyVersion(fileMajor, fileMinor, fileExperimental)
111+
val toolVersion = TastyVersion(toolMajor, toolMinor, toolExperimental)
112+
113+
val compat = Compatibility.failReason(file = fileVersion, read = toolVersion)
114+
115+
val what = if (compat < 0) "Backward" else "Forward"
116+
val signature = signatureString(fileVersion, toolVersion, what, tool = Some(toolingVersion))
117+
val fix = (
118+
if (compat < 0) {
119+
val newCompiler =
120+
if (compat == Compatibility.BackwardIncompatibleMajor) toolVersion.minStable
121+
else if (compat == Compatibility.BackwardIncompatibleExperimental) fileVersion.nextStable
122+
else toolVersion // recompile the experimental library with the current experimental compiler
123+
recompileFix(newCompiler, config)
124+
}
125+
else upgradeFix(fileVersion, config)
126+
)
127+
signature + fix + tastyAddendum
128+
})
129+
}
130+
131+
private def signatureString(
132+
fileVersion: TastyVersion, toolVersion: TastyVersion, what: String, tool: Option[String]) = {
133+
val optProducedBy = tool.fold("")(t => s", produced by $t")
134+
s"""$what incompatible TASTy file has version ${fileVersion.show}$optProducedBy,
135+
| expected ${toolVersion.validRange}.
136+
|""".stripMargin
137+
}
138+
139+
private def recompileFix(producerVersion: TastyVersion, config: UnpicklerConfig) = {
140+
val addendum = config.recompileAdditionalInfo
141+
val newTool = config.upgradedProducerTool(producerVersion)
142+
s""" The source of this file should be recompiled by $newTool.$addendum""".stripMargin
143+
}
144+
145+
private def upgradeFix(fileVersion: TastyVersion, config: UnpicklerConfig) = {
146+
val addendum = config.upgradeAdditionalInfo(fileVersion)
147+
val newTool = config.upgradedReaderTool(fileVersion)
148+
s""" To read this ${fileVersion.kind} file, use $newTool.$addendum""".stripMargin
149+
}
150+
151+
private def tastyAddendum: String = """
152+
| Please refer to the documentation for information on TASTy versioning:
153+
| https://docs.scala-lang.org/scala3/reference/language-versions/binary-compatibility.html""".stripMargin
154+
155+
private object Compatibility {
156+
final val BackwardIncompatibleMajor = -3
157+
final val BackwardIncompatibleExperimental = -2
158+
final val ExperimentalRecompile = -1
159+
final val ExperimentalUpgrade = 1
160+
final val ForwardIncompatible = 2
161+
162+
/** Given that file can't be read, extract the reason */
163+
def failReason(file: TastyVersion, read: TastyVersion): Int =
164+
if (file.major == read.major && file.minor == read.minor && file.isExperimental && read.isExperimental) {
165+
if (file.experimental < read.experimental) ExperimentalRecompile // recompile library as compiler is too new
166+
else ExperimentalUpgrade // they should upgrade compiler as library is too new
167+
}
168+
else if (file.major < read.major)
169+
BackwardIncompatibleMajor // pre 3.0.0
170+
else if (file.isExperimental && file.major == read.major && file.minor <= read.minor)
171+
// e.g. 3.4.0 reading 3.4.0-RC1-NIGHTLY, or 3.3.0 reading 3.0.2-RC1-NIGHTLY
172+
BackwardIncompatibleExperimental
173+
else ForwardIncompatible
174+
}
175+
}

tasty/src/dotty/tools/tasty/TastyHeaderUnpickler.scala

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -133,7 +133,7 @@ object TastyHeaderUnpickler {
133133
if (!cond) throw new UnpickleException(msg)
134134
}
135135

136-
private[tasty] def checkValidVersion(fileMajor: Int, fileMinor: Int, fileExperimental: Int, toolingVersion: String, config: UnpicklerConfig) = {
136+
private def checkValidVersion(fileMajor: Int, fileMinor: Int, fileExperimental: Int, toolingVersion: String, config: UnpicklerConfig) = {
137137
val toolMajor: Int = config.majorVersion
138138
val toolMinor: Int = config.minorVersion
139139
val toolExperimental: Int = config.experimentalVersion

0 commit comments

Comments
 (0)