Skip to content

Commit

Permalink
Remove the -Yemit-tasty-in-class option, along with handling of .hasT…
Browse files Browse the repository at this point in the history
…asty.

The default was flipped in a645566
in July 2018. Since then, it has not been really tested.

Completely removing it will allow the tooling not to worry about
`.hasTasty` and the need to read TASTy from class files.

We keep the support of `.hasTasty` files in sbt-dotty for now, so
that it still supports older versions of dotty.
  • Loading branch information
sjrd committed Dec 9, 2020
1 parent f70ee5f commit dbc1457
Show file tree
Hide file tree
Showing 10 changed files with 41 additions and 52 deletions.
1 change: 0 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
*.DS_Store
*.class
*.tasty
*.hasTasty
*.log
*.swp
*~
Expand Down
2 changes: 1 addition & 1 deletion .vscode-template/settings.json
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@

"search.exclude": {
"**/*.class": true,
"**/*.hasTasty": true,
"**/*.tasty": true,
"**/target/": true,
"community-build/community-projects": true
}
Expand Down
48 changes: 21 additions & 27 deletions compiler/src/dotty/tools/backend/jvm/GenBCode.scala
Original file line number Diff line number Diff line change
Expand Up @@ -234,33 +234,27 @@ class GenBCodePipeline(val int: DottyBackendInterface, val primitives: DottyPrim
for (binary <- ctx.compilationUnit.pickled.get(claszSymbol.asClass)) {
val store = if (mirrorC ne null) mirrorC else plainC
val tasty =
if (!ctx.settings.YemitTastyInClass.value) {
val outTastyFile = getFileForClassfile(outF, store.name, ".tasty")
val outstream = new DataOutputStream(outTastyFile.bufferedOutput)
try outstream.write(binary())
catch case ex: ClosedByInterruptException =>
try
outTastyFile.delete() // don't leave an empty or half-written tastyfile around after an interrupt
catch case _: Throwable =>
throw ex
finally outstream.close()

val uuid = new TastyHeaderUnpickler(binary()).readHeader()
val lo = uuid.getMostSignificantBits
val hi = uuid.getLeastSignificantBits

// TASTY attribute is created but only the UUID bytes are stored in it.
// A TASTY attribute has length 16 if and only if the .tasty file exists.
val buffer = new TastyBuffer(16)
buffer.writeUncompressedLong(lo)
buffer.writeUncompressedLong(hi)
buffer.bytes
} else {
// Create an empty file to signal that a tasty section exist in the corresponding .class
// This is much cheaper and simpler to check than doing classfile parsing
getFileForClassfile(outF, store.name, ".hasTasty")
binary()
}
val outTastyFile = getFileForClassfile(outF, store.name, ".tasty")
val outstream = new DataOutputStream(outTastyFile.bufferedOutput)
try outstream.write(binary())
catch case ex: ClosedByInterruptException =>
try
outTastyFile.delete() // don't leave an empty or half-written tastyfile around after an interrupt
catch case _: Throwable =>
throw ex
finally outstream.close()

val uuid = new TastyHeaderUnpickler(binary()).readHeader()
val lo = uuid.getMostSignificantBits
val hi = uuid.getLeastSignificantBits

// TASTY attribute is created but only the UUID bytes are stored in it.
// A TASTY attribute has length 16 if and only if the .tasty file exists.
val buffer = new TastyBuffer(16)
buffer.writeUncompressedLong(lo)
buffer.writeUncompressedLong(hi)
buffer.bytes

val dataAttr = createJAttribute(nme.TASTYATTR.mangledString, tasty, 0, tasty.length)
store.visitAttribute(dataAttr)
}
Expand Down
1 change: 0 additions & 1 deletion compiler/src/dotty/tools/dotc/config/ScalaSettings.scala
Original file line number Diff line number Diff line change
Expand Up @@ -154,7 +154,6 @@ class ScalaSettings extends Settings.SettingGroup with CommonScalaSettings {
val YdebugError: Setting[Boolean] = BooleanSetting("-Ydebug-error", "Print the stack trace when any error is caught.", false)
val YtermConflict: Setting[String] = ChoiceSetting("-Yresolve-term-conflict", "strategy", "Resolve term conflicts", List("package", "object", "error"), "error")
val Ylog: Setting[List[String]] = PhasesSetting("-Ylog", "Log operations during")
val YemitTastyInClass: Setting[Boolean] = BooleanSetting("-Yemit-tasty-in-class", "Generate tasty in the .class file and add an empty *.hasTasty file.")
val YlogClasspath: Setting[Boolean] = BooleanSetting("-Ylog-classpath", "Output information about what classpath is being applied.")
val YdisableFlatCpCaching: Setting[Boolean] = BooleanSetting("-YdisableFlatCpCaching", "Do not cache flat classpath representation of classpath elements from jars across compiler instances.")

Expand Down
3 changes: 1 addition & 2 deletions compiler/src/dotty/tools/dotc/fromtasty/Debug.scala
Original file line number Diff line number Diff line change
Expand Up @@ -36,10 +36,9 @@ object Debug {

val fromTastyOut = Files.createDirectory(tmpOut.resolve("from-tasty"))

val extensions = List("tasty", "hasTasty").map(_.toLowerCase)
val tastyFiles =
Directory(fromSourcesOut).walk
.filter(x => x.isFile && extensions.exists(_ == x.extension.toLowerCase))
.filter(x => x.isFile && "tasty".equalsIgnoreCase(x.extension))
.map(_.toString)
.toList

Expand Down
16 changes: 4 additions & 12 deletions compiler/src/dotty/tools/dotc/interactive/InteractiveDriver.scala
Original file line number Diff line number Diff line change
Expand Up @@ -57,7 +57,7 @@ class InteractiveDriver(val settings: List[String]) extends Driver {

// Presence of a file with one of these suffixes indicates that the
// corresponding class has been pickled with TASTY.
private val tastySuffixes = List(".hasTasty", ".tasty")
private val tastySuffix = ".tasty"

// FIXME: All the code doing classpath handling is very fragile and ugly,
// improving this requires changing the dotty classpath APIs to handle our usecases.
Expand Down Expand Up @@ -220,11 +220,8 @@ class InteractiveDriver(val settings: List[String]) extends Driver {
while (entries.hasMoreElements) {
val entry = entries.nextElement()
val name = entry.getName
tastySuffixes.find(name.endsWith) match {
case Some(tastySuffix) =>
buffer += name.replace("/", ".").stripSuffix(tastySuffix).toTypeName
case _ =>
}
if name.endsWith(tastySuffix) then
buffer += name.replace("/", ".").stripSuffix(tastySuffix).toTypeName
}
}
finally zipFile.close()
Expand All @@ -237,13 +234,8 @@ class InteractiveDriver(val settings: List[String]) extends Driver {
override def visitFile(path: Path, attrs: BasicFileAttributes) = {
if (!attrs.isDirectory) {
val name = path.getFileName.toString
for {
tastySuffix <- tastySuffixes
if name.endsWith(tastySuffix)
}
{
if name.endsWith(tastySuffix) then
buffer += dir.relativize(path).toString.replace("/", ".").stripSuffix(tastySuffix).toTypeName
}
}
FileVisitResult.CONTINUE
}
Expand Down
2 changes: 1 addition & 1 deletion compiler/test/dotty/tools/dotc/CompilationTests.scala
Original file line number Diff line number Diff line change
Expand Up @@ -232,7 +232,7 @@ class CompilationTests {
Properties.compilerInterface, Properties.scalaLibrary, Properties.scalaAsm,
Properties.dottyInterfaces, Properties.jlineTerminal, Properties.jlineReader,
).mkString(File.pathSeparator),
Array("-Ycheck-reentrant", "-Yemit-tasty-in-class", "-language:postfixOps", "-Ysemanticdb")
Array("-Ycheck-reentrant", "-language:postfixOps", "-Ysemanticdb")
)

val libraryDirs = List(Paths.get("library/src"), Paths.get("library/src-bootstrapped"))
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 @@ -1369,5 +1369,5 @@ object ParallelTesting {
}

def isTastyFile(f: JFile): Boolean =
f.getName.endsWith(".hasTasty") || f.getName.endsWith(".tasty")
f.getName.endsWith(".tasty")
}
11 changes: 7 additions & 4 deletions sbt-dotty/src/dotty/tools/sbtplugin/DottyPlugin.scala
Original file line number Diff line number Diff line change
Expand Up @@ -136,15 +136,18 @@ object DottyPlugin extends AutoPlugin {
override def requires: Plugins = plugins.JvmPlugin
override def trigger = allRequirements

/** Patches the IncOptions so that .tasty and .hasTasty files are pruned as needed.
/** Patches the IncOptions so that .tasty files are pruned as needed.
*
* This code is adapted from `scalaJSPatchIncOptions` in Scala.js, which needs
* to do the exact same thing but for classfiles.
* to do the exact same thing but for .sjsir files.
*
* This complicated logic patches the ClassfileManager factory of the given
* IncOptions with one that is aware of .tasty and .hasTasty files emitted by the Dotty
* IncOptions with one that is aware of .tasty files emitted by the Dotty
* compiler. This makes sure that, when a .class file must be deleted, the
* corresponding .tasty or .hasTasty file is also deleted.
* corresponding .tasty file is also deleted.
*
* To support older versions of dotty, this also takes care of .hasTasty
* files, although they are not used anymore.
*/
def dottyPatchIncOptions(incOptions: IncOptions): IncOptions = {
val tastyFileManager = new TastyFileManager
Expand Down
7 changes: 5 additions & 2 deletions sbt-dotty/src/dotty/tools/sbtplugin/TastyFileManager.scala
Original file line number Diff line number Diff line change
Expand Up @@ -9,15 +9,18 @@ import xsbti.compile.ClassFileManager
import scala.collection.mutable


/** A class file manger that prunes .tasty and .hasTasty as needed.
/** A class file manger that prunes .tasty as needed.
*
* This makes sure that, when a .class file must be deleted, the
* corresponding .tasty or .hasTasty file is also deleted.
* corresponding .tasty file is also deleted.
*
* This code is adapted from Zinc `TransactionalClassFileManager`.
* We need to duplicate the logic since forwarding to the default class
* file manager doesn't work: we need to backup tasty files in a different
* temporary directory as class files.
*
* To support older versions of dotty, this also takes care of .hasTasty
* files, although they are not used anymore.
*/
final class TastyFileManager extends ClassFileManager {
private[this] var _tempDir: File = null
Expand Down

0 comments on commit dbc1457

Please sign in to comment.