Skip to content

[sbt-bridge] Bump Zinc to 1.4.3 and upgrade to CompilerInterface2 #10607

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 3 commits into from
Dec 12, 2020
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
8 changes: 5 additions & 3 deletions bench/src/main/scala/Benchmarks.scala
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,8 @@ import scala.collection.JavaConverters._
import scala.io.Source
import scala.util.Using

import dotty.tools.io.AbstractFile

object Bench {
val COMPILE_OPTS_FILE = "compile.txt"

Expand Down Expand Up @@ -93,11 +95,11 @@ class CompilerOptions {

class Worker extends Driver {
// override to avoid printing summary information
override def doCompile(compiler: Compiler, fileNames: List[String])(implicit ctx: Context): Reporter =
if (fileNames.nonEmpty)
override def doCompile(compiler: Compiler, files: List[AbstractFile])(implicit ctx: Context): Reporter =
if (files.nonEmpty)
try {
val run = compiler.newRun
run.compile(fileNames)
run.compile(files)
ctx.reporter
}
catch {
Expand Down
5 changes: 3 additions & 2 deletions compiler/src/dotty/tools/dotc/Bench.scala
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ package dotc

import core.Contexts._
import reporting.Reporter
import io.AbstractFile

import scala.annotation.internal.sharable

Expand All @@ -19,12 +20,12 @@ object Bench extends Driver:

@sharable private var times: Array[Int] = _

override def doCompile(compiler: Compiler, fileNames: List[String])(using Context): Reporter =
override def doCompile(compiler: Compiler, files: List[AbstractFile])(using Context): Reporter =
times = new Array[Int](numRuns)
var reporter: Reporter = emptyReporter
for i <- 0 until numRuns do
val start = System.nanoTime()
reporter = super.doCompile(compiler, fileNames)
reporter = super.doCompile(compiler, files)
times(i) = ((System.nanoTime - start) / 1000000).toInt
println(s"time elapsed: ${times(i)}ms")
if ctx.settings.Xprompt.value then
Expand Down
105 changes: 49 additions & 56 deletions compiler/src/dotty/tools/dotc/Driver.scala
Original file line number Diff line number Diff line change
Expand Up @@ -9,10 +9,11 @@ import core.Contexts._
import core.{MacroClassLoader, Mode, TypeError}
import core.StdNames.nme
import dotty.tools.dotc.ast.Positioned
import dotty.tools.io.File
import dotty.tools.io.AbstractFile
import reporting._
import core.Decorators._
import config.Feature
import util.SourceFile

import scala.util.control.NonFatal
import fromtasty.{TASTYCompiler, TastyFileUtil}
Expand All @@ -31,41 +32,39 @@ class Driver {

protected def emptyReporter: Reporter = new StoreReporter(null)

protected def doCompile(compiler: Compiler, fileNames: List[String])(using Context): Reporter =
if (fileNames.nonEmpty)
protected def doCompile(compiler: Compiler, files: List[AbstractFile])(using Context): Reporter =
if files.nonEmpty then
try
val run = compiler.newRun
run.compile(fileNames)

def finish(run: Run)(using Context): Unit =
run.printSummary()
if !ctx.reporter.errorsReported && run.suspendedUnits.nonEmpty then
val suspendedUnits = run.suspendedUnits.toList
if (ctx.settings.XprintSuspension.value)
report.echo(i"compiling suspended $suspendedUnits%, %")
val run1 = compiler.newRun
for unit <- suspendedUnits do unit.suspended = false
run1.compileUnits(suspendedUnits)
finish(run1)(using MacroClassLoader.init(ctx.fresh))

finish(run)
run.compile(files)
finish(compiler, run)
catch
case ex: FatalError =>
case ex: FatalError =>
report.error(ex.getMessage) // signals that we should fail compilation.
case ex: TypeError =>
println(s"${ex.toMessage} while compiling ${fileNames.mkString(", ")}")
println(s"${ex.toMessage} while compiling ${files.map(_.path).mkString(", ")}")
throw ex
case ex: Throwable =>
println(s"$ex while compiling ${fileNames.mkString(", ")}")
println(s"$ex while compiling ${files.map(_.path).mkString(", ")}")
throw ex
ctx.reporter
end doCompile

protected def finish(compiler: Compiler, run: Run)(using Context): Unit =
run.printSummary()
if !ctx.reporter.errorsReported && run.suspendedUnits.nonEmpty then
val suspendedUnits = run.suspendedUnits.toList
if (ctx.settings.XprintSuspension.value)
report.echo(i"compiling suspended $suspendedUnits%, %")
val run1 = compiler.newRun
for unit <- suspendedUnits do unit.suspended = false
run1.compileUnits(suspendedUnits)
finish(compiler, run1)(using MacroClassLoader.init(ctx.fresh))

protected def initCtx: Context = (new ContextBase).initialCtx

protected def sourcesRequired: Boolean = true

def setup(args: Array[String], rootCtx: Context): (List[String], Context) = {
def setup(args: Array[String], rootCtx: Context): (List[AbstractFile], Context) = {
val ictx = rootCtx.fresh
val summary = CompilerCommand.distill(args)(using ictx)
ictx.setSettings(summary.sstate)
Expand All @@ -76,43 +75,37 @@ class Driver {
if !ctx.settings.YdropComments.value || ctx.mode.is(Mode.ReadComments) then
ictx.setProperty(ContextDoc, new ContextDocstrings)
val fileNames = CompilerCommand.checkUsage(summary, sourcesRequired)
fromTastySetup(fileNames, ctx)
val files = fileNames.map(ctx.getFile)
(files, fromTastySetup(files))
}
}

/** Setup extra classpath and figure out class names for tasty file inputs */
protected def fromTastySetup(fileNames0: List[String], ctx0: Context): (List[String], Context) =
given Context = ctx0
if (ctx0.settings.fromTasty.value) {
val fromTastyIgnoreList = ctx0.settings.YfromTastyIgnoreList.value.toSet
// Resolve classpath and class names of tasty files
val (classPaths, classNames) = fileNames0.flatMap { name =>
val path = Paths.get(name)
if !Files.exists(path) then
report.error(s"File does not exist: $name")
Nil
else if name.endsWith(".jar") then
new dotty.tools.io.Jar(File(name)).toList.collect {
case e if e.getName.endsWith(".tasty") && !fromTastyIgnoreList(e.getName) =>
(name, e.getName.stripSuffix(".tasty").replace("/", "."))
}
else if name.endsWith(".tasty") then
TastyFileUtil.getClassName(path) match
case Some(res) => res :: Nil
/** Setup extra classpath of tasty and jar files */
protected def fromTastySetup(files: List[AbstractFile])(using Context): Context =
if ctx.settings.fromTasty.value then
val newEntries: List[String] = files
.flatMap { file =>
if !file.exists then
report.error(s"File does not exist: ${file.path}")
None
else file.extension match
case "jar" => Some(file.path)
case "tasty" =>
TastyFileUtil.getClassPath(file) match
case Some(classpath) => Some(classpath)
case _ =>
report.error(s"Could not load classname from: ${file.path}")
None
case _ =>
report.error(s"Could not load classname from: $name")
Nil
else
report.error(s"File extension is not `tasty` or `jar`: $name")
Nil
}.unzip
val ctx1 = ctx0.fresh
val classPaths1 = classPaths.distinct.filter(_ != "")
val fullClassPath = (classPaths1 :+ ctx1.settings.classpath.value(using ctx1)).mkString(java.io.File.pathSeparator)
report.error(s"File extension is not `tasty` or `jar`: ${file.path}")
None
}
.distinct
val ctx1 = ctx.fresh
val fullClassPath =
(newEntries :+ ctx.settings.classpath.value).mkString(java.io.File.pathSeparator)
ctx1.setSetting(ctx1.settings.classpath, fullClassPath)
(classNames, ctx1)
}
else (fileNames0, ctx0)
else ctx

/** Entry point to the compiler that can be conveniently used with Java reflection.
*
Expand Down Expand Up @@ -189,8 +182,8 @@ class Driver {
* if compilation succeeded.
*/
def process(args: Array[String], rootCtx: Context): Reporter = {
val (fileNames, compileCtx) = setup(args, rootCtx)
doCompile(newCompiler(using compileCtx), fileNames)(using compileCtx)
val (files, compileCtx) = setup(args, rootCtx)
doCompile(newCompiler(using compileCtx), files)(using compileCtx)
}

def main(args: Array[String]): Unit = {
Expand Down
4 changes: 2 additions & 2 deletions compiler/src/dotty/tools/dotc/Resident.scala
Original file line number Diff line number Diff line change
Expand Up @@ -40,8 +40,8 @@ class Resident extends Driver {

final override def process(args: Array[String], rootCtx: Context): Reporter = {
@tailrec def loop(args: Array[String], prevCtx: Context): Reporter = {
var (fileNames, ctx) = setup(args, prevCtx)
inContext(ctx){doCompile(residentCompiler, fileNames)}
var (files, ctx) = setup(args, prevCtx)
inContext(ctx) { doCompile(residentCompiler, files) }
var nextCtx = ctx
var line = getLine()
while (line == reset) {
Expand Down
22 changes: 11 additions & 11 deletions compiler/src/dotty/tools/dotc/Run.scala
Original file line number Diff line number Diff line change
Expand Up @@ -124,16 +124,15 @@ class Run(comp: Compiler, ictx: Context) extends ImplicitRunInfo with Constraint
/** Actions that need to be performed at the end of the current compilation run */
private var finalizeActions = mutable.ListBuffer[() => Unit]()

def compile(fileNames: List[String]): Unit = try {
val sources = fileNames.map(runContext.getSource(_))
compileSources(sources)
}
catch {
case NonFatal(ex) =>
if units != null then report.echo(i"exception occurred while compiling $units%, %")
else report.echo(s"exception occurred while compiling ${fileNames.mkString(", ")}")
throw ex
}
def compile(files: List[AbstractFile]): Unit =
try
val sources = files.map(runContext.getSource(_))
compileSources(sources)
catch
case NonFatal(ex) =>
if units != null then report.echo(i"exception occurred while compiling $units%, %")
else report.echo(s"exception occurred while compiling ${files.map(_.name).mkString(", ")}")
throw ex

/** TODO: There's a fundamental design problem here: We assemble phases using `fusePhases`
* when we first build the compiler. But we modify them with -Yskip, -Ystop
Expand All @@ -147,6 +146,7 @@ class Run(comp: Compiler, ictx: Context) extends ImplicitRunInfo with Constraint
compileUnits()
}


def compileUnits(us: List[CompilationUnit]): Unit = {
units = us
compileUnits()
Expand Down Expand Up @@ -218,7 +218,7 @@ class Run(comp: Compiler, ictx: Context) extends ImplicitRunInfo with Constraint
if (!files.contains(file) && !lateFiles.contains(file)) {
lateFiles += file

val unit = CompilationUnit(ctx.getSource(file.path))
val unit = CompilationUnit(ctx.getSource(file))
val unitCtx = runContext.fresh
.setCompilationUnit(unit)
.withRootImports
Expand Down
11 changes: 6 additions & 5 deletions compiler/src/dotty/tools/dotc/config/CompilerCommand.scala
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,12 @@ object CompilerCommand {

def versionMsg: String = s"Scala compiler $versionString -- $copyrightString"

def shouldStopWithInfo(using Context): Boolean = {
val settings = ctx.settings
import settings._
Set(help, Xhelp, Yhelp, showPlugins, XshowPhases) exists (_.value)
}

/** Distill arguments into summary detailing settings, errors and files to compiler */
def distill(args: Array[String])(using Context): ArgsSummary = {
/**
Expand Down Expand Up @@ -110,11 +116,6 @@ object CompilerCommand {
def xusageMessage = createUsageMsg("Possible advanced", shouldExplain = true, isAdvanced)
def yusageMessage = createUsageMsg("Possible private", shouldExplain = true, isPrivate)

def shouldStopWithInfo = {
import settings._
Set(help, Xhelp, Yhelp, showPlugins, XshowPhases) exists (_.value)
}

def phasesMessage: String = {
(new Compiler()).phases.map {
case List(single) => single.phaseName
Expand Down
45 changes: 26 additions & 19 deletions compiler/src/dotty/tools/dotc/core/Contexts.scala
Original file line number Diff line number Diff line change
Expand Up @@ -266,25 +266,32 @@ object Contexts {
base.sources.getOrElseUpdate(file, new SourceFile(file, codec))
}

/** Sourcefile with given path name, memoized */
def getSource(path: TermName): SourceFile = base.sourceNamed.get(path) match {
case Some(source) =>
source
case None => try {
val f = new PlainFile(Path(path.toString))
val src = getSource(f)
base.sourceNamed(path) = src
src
} catch {
case ex: InvalidPathException =>
report.error(s"invalid file path: ${ex.getMessage}")
NoSource
}
}
/** SourceFile with given path name, memoized */
def getSource(path: TermName): SourceFile = getFile(path) match
case NoAbstractFile => NoSource
case file => getSource(file)

/** Sourcefile with given path, memoized */
/** SourceFile with given path, memoized */
def getSource(path: String): SourceFile = getSource(path.toTermName)

/** AbstraFile with given path name, memoized */
Copy link
Member

Choose a reason for hiding this comment

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

Is the memoization needed here? Does the Scala 2 compiler bridge do something similar?

Copy link
Member Author

@adpi2 adpi2 Dec 9, 2020

Choose a reason for hiding this comment

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

Following our private discussion I try to remove sourceNamed in b492fd8

def getFile(name: TermName): AbstractFile = base.files.get(name) match
case Some(file) =>
file
case None =>
try
val file = new PlainFile(Path(name.toString))
base.files(name) = file
file
catch
case ex: InvalidPathException =>
report.error(s"invalid file path: ${ex.getMessage}")
NoAbstractFile

/** AbstractFile with given path, memoized */
def getFile(name: String): AbstractFile = getFile(name.toTermName)


private var related: SimpleIdentityMap[Phase | SourceFile, Context] = null

private def lookup(key: Phase | SourceFile): Context =
Expand Down Expand Up @@ -841,9 +848,9 @@ object Contexts {
private var _nextSymId: Int = 0
def nextSymId: Int = { _nextSymId += 1; _nextSymId }

/** Sources that were loaded */
/** Sources and Files that were loaded */
val sources: util.HashMap[AbstractFile, SourceFile] = util.HashMap[AbstractFile, SourceFile]()
val sourceNamed: util.HashMap[TermName, SourceFile] = util.HashMap[TermName, SourceFile]()
val files: util.HashMap[TermName, AbstractFile] = util.HashMap()

// Types state
/** A table for hash consing unique types */
Expand Down Expand Up @@ -927,7 +934,7 @@ object Contexts {
emptyWildcardBounds = null
errorTypeMsg.clear()
sources.clear()
sourceNamed.clear()
files.clear()
comparers.clear() // forces re-evaluation of top and bottom classes in TypeComparer

// Test that access is single threaded
Expand Down
2 changes: 1 addition & 1 deletion compiler/src/dotty/tools/dotc/core/SymbolLoaders.scala
Original file line number Diff line number Diff line change
Expand Up @@ -173,7 +173,7 @@ object SymbolLoaders {
Nil)
}

val unit = CompilationUnit(ctx.getSource(src.path))
val unit = CompilationUnit(ctx.getSource(src))
enterScanned(unit)(using ctx.fresh.setCompilationUnit(unit))

/** The package objects of scala and scala.reflect should always
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import dotty.tools.dotc.core.Contexts._
import dotty.tools.dotc.core._
import dotty.tools.dotc.core.tasty.TastyHTMLPrinter
import dotty.tools.dotc.reporting._
import dotty.tools.io.AbstractFile

import scala.quoted.runtime.impl.QuotesImpl

Expand All @@ -25,13 +26,13 @@ class IDEDecompilerDriver(val settings: List[String]) extends dotc.Driver {

private val decompiler = new PartialTASTYDecompiler

def run(className: String): (String, String) = {
def run(tastyFile: AbstractFile): (String, String) = {
val reporter = new StoreReporter(null) with HideNonSensicalMessages

val run = decompiler.newRun(using myInitCtx.fresh.setReporter(reporter))

inContext(run.runContext) {
run.compile(List(className))
run.compile(List(tastyFile))
run.printSummary()
val unit = ctx.run.units.head

Expand Down
Loading