Skip to content

Commit d810ffc

Browse files
committed
Fix #7852: avoid reading stale .tasty files from jars
Somehow, if we don't close the classloader used to read .tasty files from jars, a subsequent compilation run might end up reading a stale version of the .tasty file which does not exist on disk anymore. I don't understand why this happens since we don't reuse the classloader itself, but that's life sometimes ¯\_(ツ)_/¯
1 parent 947316d commit d810ffc

File tree

10 files changed

+63
-14
lines changed

10 files changed

+63
-14
lines changed

compiler/src/dotty/tools/dotc/core/classfile/ClassfileParser.scala

+21-14
Original file line numberDiff line numberDiff line change
@@ -780,22 +780,29 @@ class ClassfileParser(
780780
Array.empty
781781
case Some(jar: ZipArchive) => // We are in a jar
782782
val cl = new URLClassLoader(Array(jar.jpath.toUri.toURL), /*parent =*/ null)
783-
val path = classfile.path.stripSuffix(".class") + ".tasty"
784-
val stream = cl.getResourceAsStream(path)
785-
if (stream != null) {
786-
val tastyOutStream = new ByteArrayOutputStream()
787-
val buffer = new Array[Byte](1024)
788-
var read = stream.read(buffer, 0, buffer.length)
789-
while (read != -1) {
790-
tastyOutStream.write(buffer, 0, read)
791-
read = stream.read(buffer, 0, buffer.length)
783+
try {
784+
val path = classfile.path.stripSuffix(".class") + ".tasty"
785+
val stream = cl.getResourceAsStream(path)
786+
if (stream != null) {
787+
val tastyOutStream = new ByteArrayOutputStream()
788+
val buffer = new Array[Byte](1024)
789+
var read = stream.read(buffer, 0, buffer.length)
790+
while (read != -1) {
791+
tastyOutStream.write(buffer, 0, read)
792+
read = stream.read(buffer, 0, buffer.length)
793+
}
794+
tastyOutStream.flush()
795+
tastyOutStream.toByteArray
796+
}
797+
else {
798+
ctx.error(s"Could not find $path in $jar")
799+
Array.empty
792800
}
793-
tastyOutStream.flush()
794-
tastyOutStream.toByteArray
795801
}
796-
else {
797-
ctx.error(s"Could not find $path in $jar")
798-
Array.empty
802+
finally {
803+
// If we don't close the classloader, spooky things happen (see
804+
// scripted test source-dependencies/export-jars2).
805+
cl.close()
799806
}
800807
case _ =>
801808
val plainFile = new PlainFile(io.File(classfile.jpath).changeExtension("tasty"))
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
class A
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
class B {
2+
val x = new A
3+
}
4+
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
lazy val a = Project("a", file("a"))
2+
.settings(
3+
exportJars := true
4+
)
5+
6+
lazy val b = Project("b", file("b"))
7+
.dependsOn(a)
8+
.settings(
9+
exportJars := true
10+
)
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
2+
class A
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
2+
class B {
3+
val x = new A
4+
}
5+
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
import sbt._
2+
import Keys._
3+
4+
object DottyInjectedPlugin extends AutoPlugin {
5+
override def requires = plugins.JvmPlugin
6+
override def trigger = allRequirements
7+
8+
override val projectSettings = Seq(
9+
scalaVersion := sys.props("plugin.scalaVersion"),
10+
scalacOptions += "-language:Scala2Compat"
11+
)
12+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
addSbtPlugin("ch.epfl.lamp" % "sbt-dotty" % sys.props("plugin.version"))
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
> compile
2+
$ copy-file changes/A1.scala a/A.scala
3+
$ copy-file changes/B1.scala b/B.scala
4+
# This used to fail with "Tasty UUID (...) file did not correspond the tasty UUID (...) declared in the classfile"
5+
# because we were somehow reading the .tasty file from the previous compilation run, even though it does not exist
6+
# on disk anymore (#7852)
7+
> compile

0 commit comments

Comments
 (0)