diff --git a/compiler/src/dotty/tools/dotc/Compiler.scala b/compiler/src/dotty/tools/dotc/Compiler.scala index 7e5ef0d7d2a3..c2e4fa0ad8cb 100644 --- a/compiler/src/dotty/tools/dotc/Compiler.scala +++ b/compiler/src/dotty/tools/dotc/Compiler.scala @@ -52,7 +52,6 @@ class Compiler { /** Phases dealing with TASTY tree pickling and unpickling */ protected def picklerPhases: List[List[Phase]] = List(new Pickler) :: // Generate TASTY info - List(new LinkAll) :: // Reload compilation units from TASTY for library code (if needed) List(new ReifyQuotes) :: // Turn quoted trees into explicit run-time data structures Nil diff --git a/compiler/src/dotty/tools/dotc/config/ScalaSettings.scala b/compiler/src/dotty/tools/dotc/config/ScalaSettings.scala index 313806ef880d..3261979a9c0c 100644 --- a/compiler/src/dotty/tools/dotc/config/ScalaSettings.scala +++ b/compiler/src/dotty/tools/dotc/config/ScalaSettings.scala @@ -144,8 +144,6 @@ class ScalaSettings extends Settings.SettingGroup { val YshowVarBounds = BooleanSetting("-Yshow-var-bounds", "Print type variables with their bounds") val YshowNoInline = BooleanSetting("-Yshow-no-inline", "Show inlined code without the 'inlined from' info") - /** Linker specific flags */ - val Xlink = BooleanSetting("-Xlink", "Recompile library code with the application.") val YnoDecodeStacktraces = BooleanSetting("-Yno-decode-stacktraces", "Show raw StackOverflow stacktraces, instead of decoding them into triggering operations.") /** Dottydoc specific settings */ diff --git a/compiler/src/dotty/tools/dotc/core/SymbolLoaders.scala b/compiler/src/dotty/tools/dotc/core/SymbolLoaders.scala index 87d810e9cb5e..75e53a0c4c43 100644 --- a/compiler/src/dotty/tools/dotc/core/SymbolLoaders.scala +++ b/compiler/src/dotty/tools/dotc/core/SymbolLoaders.scala @@ -390,7 +390,7 @@ class ClassfileLoader(val classfile: AbstractFile) extends SymbolLoader { } private def mayLoadTreesFromTasty(implicit ctx: Context): Boolean = - ctx.settings.YretainTrees.value || ctx.settings.Xlink.value || ctx.settings.fromTasty.value + ctx.settings.YretainTrees.value || ctx.settings.fromTasty.value } class SourcefileLoader(val srcfile: AbstractFile) extends SymbolLoader { diff --git a/compiler/src/dotty/tools/dotc/core/Symbols.scala b/compiler/src/dotty/tools/dotc/core/Symbols.scala index 44ef54256503..dfeb5c31d577 100644 --- a/compiler/src/dotty/tools/dotc/core/Symbols.scala +++ b/compiler/src/dotty/tools/dotc/core/Symbols.scala @@ -668,10 +668,8 @@ object Symbols { private[this] var myTree: TreeOrProvider = tpd.EmptyTree - /** If this is either: - * - a top-level class and `-Yretain-trees` is set - * - a top-level class loaded from TASTY and `-tasty` or `-Xlink` is set - * then return the TypeDef tree (possibly wrapped inside PackageDefs) for this class, otherwise EmptyTree. + /** If this is a top-level class and `-Yretain-trees` (or `-from-tasty`) is set. + * Returns the TypeDef tree (possibly wrapped inside PackageDefs) for this class, otherwise EmptyTree. * This will force the info of the class. */ def tree(implicit ctx: Context): Tree = treeContaining("") diff --git a/compiler/src/dotty/tools/dotc/transform/LinkAll.scala b/compiler/src/dotty/tools/dotc/transform/LinkAll.scala deleted file mode 100644 index 5fa9436f297a..000000000000 --- a/compiler/src/dotty/tools/dotc/transform/LinkAll.scala +++ /dev/null @@ -1,82 +0,0 @@ -package dotty.tools.dotc.transform - -import dotty.tools.dotc.CompilationUnit -import dotty.tools.dotc.ast.Trees._ -import dotty.tools.dotc.ast.tpd -import dotty.tools.dotc.core.Phases.Phase -import dotty.tools.dotc.core.Contexts._ -import dotty.tools.dotc.core.SymDenotations.ClassDenotation -import dotty.tools.dotc.core.Symbols._ -import dotty.tools.dotc.core.Flags._ -import dotty.tools.dotc.core.Mode - -/** Loads all potentially reachable trees from tasty. ▲ - * Only performed on whole world optimization mode. ▲ ▲ - * - * TODO: Next step is to only load compilation units reachable in the call graph - */ -class LinkAll extends Phase { - import tpd._ - import LinkAll._ - - def phaseName: String = LinkAll.name - - def run(implicit ctx: Context): Unit = () - - override def runOn(units: List[CompilationUnit])(implicit ctx: Context): List[CompilationUnit] = { - /** Loads and processes new compilation units, possibly loading more units. */ - def allUnits(processed: Set[CompilationUnit], unprocessed: Set[CompilationUnit], loadedClasses: Set[ClassDenotation])(implicit ctx: Context): List[CompilationUnit] = { - if (unprocessed.isEmpty) processed.toList - else { - val accum = new ClassesToLoadAccumulator - val classesToLoad = unprocessed.foldLeft(Set.empty[ClassDenotation])((acc, unit) => accum.apply(acc, unit.tpdTree)) -- loadedClasses - val loadedUnits = classesToLoad.flatMap(cls => loadCompilationUnit(cls)) - allUnits(processed ++ unprocessed, loadedUnits, loadedClasses ++ classesToLoad) - } - } - - if (ctx.settings.Xlink.value) allUnits(Set.empty, units.toSet, Set.empty) - else units - } - - /** Collects all class denotations that may need to be loaded. */ - private class ClassesToLoadAccumulator extends TreeAccumulator[Set[ClassDenotation]] { - private[this] var inParents = false - override def apply(acc: Set[ClassDenotation], tree: tpd.Tree)(implicit ctx: Context): Set[ClassDenotation] = tree match { - case New(tpt) => accum(acc, tpt.tpe.classSymbol) - case AppliedTypeTree(tpt, _) if inParents => accum(acc, tpt.symbol) - case tree: RefTree if inParents || tree.symbol.is(Module) => - foldOver(accum(acc, tree.symbol), tree) - case tree @ Template(constr, parents, self, _) => - val acc1 = this(acc, constr) - inParents = true - val acc2 = this(acc1, parents) - inParents = false - this(this(acc2, self), tree.body) - case _ => foldOver(acc, tree) - } - - /** Accumulate class denotation for `sym` if needed */ - private def accum(acc: Set[ClassDenotation], sym: Symbol)(implicit ctx: Context): Set[ClassDenotation] = { - val topClass = sym.topLevelClass.denot.asClass - if (topClass.is(JavaDefined) || topClass.is(Scala2x) || topClass.symbol == defn.ObjectClass) acc - else acc + topClass - } - } -} - -object LinkAll { - - val name = "linkAll" - - private[LinkAll] def loadCompilationUnit(clsd: ClassDenotation)(implicit ctx: Context): Option[CompilationUnit] = { - assert(ctx.settings.Xlink.value) - val tree = clsd.symbol.asClass.tree(ctx.addMode(Mode.ReadPositions)) - if (tree.isEmpty) None - else { - ctx.log("Loading compilation unit for: " + clsd) - Some(CompilationUnit.mkCompilationUnit(clsd, tree, forceTrees = false)) - } - } - -} diff --git a/compiler/src/dotty/tools/dotc/transform/ReifyQuotes.scala b/compiler/src/dotty/tools/dotc/transform/ReifyQuotes.scala index b30b65f45001..d5766bc2e23d 100644 --- a/compiler/src/dotty/tools/dotc/transform/ReifyQuotes.scala +++ b/compiler/src/dotty/tools/dotc/transform/ReifyQuotes.scala @@ -72,7 +72,7 @@ class ReifyQuotes extends MacroTransformWithImplicits { myMacroClassLoader } - override def phaseName: String = "reifyQuotes" + override def phaseName: String = ReifyQuotes.name override def checkPostCondition(tree: Tree)(implicit ctx: Context): Unit = { tree match { @@ -607,6 +607,8 @@ class ReifyQuotes extends MacroTransformWithImplicits { } object ReifyQuotes { + val name = "reifyQuotes" + def toValue(tree: Tree): Option[Any] = tree match { case Literal(Constant(c)) => Some(c) case Block(Nil, e) => toValue(e) diff --git a/compiler/test/dotty/tools/dotc/LinkTests.scala b/compiler/test/dotty/tools/dotc/LinkTests.scala deleted file mode 100644 index 29a81aed3593..000000000000 --- a/compiler/test/dotty/tools/dotc/LinkTests.scala +++ /dev/null @@ -1,95 +0,0 @@ -package dotty -package tools -package dotc - -import java.io.{File => JFile} -import java.nio.file.{Files, Path, Paths} - -import org.junit.{AfterClass, Test} -import org.junit.Assert._ -import vulpix._ - -import scala.concurrent.duration._ -import scala.collection.JavaConverters._ - -class LinkTests extends ParallelTesting { - import ParallelTesting._ - import TestConfiguration._ - import LinkTests._ - - // Test suite configuration -------------------------------------------------- - - def maxDuration = 30.seconds - def numberOfSlaves = 5 - def safeMode = Properties.testsSafeMode - def isInteractive = SummaryReport.isInteractive - def testFilter = Properties.testsFilter - - - // Disabled until strawman is fixed - // @Test - def linkTest: Unit = { - // Setup and compile libraries - val strawmanLibGroup = TestGroup("linkTest/strawmanLibrary") - val strawmanLibTestGroup = TestGroup(strawmanLibGroup + "/tests") - - val linkCustomLibGroup = TestGroup("linkTest/linkCustomLib") - val linkCustomLibTestGroup = TestGroup(linkCustomLibGroup + "/tests") - - val strawmanLibrary = compileDir("collection-strawman/collections/src/main", defaultOptions)(strawmanLibGroup) - val linkCustomLib = compileDir("tests/link/custom-lib", defaultOptions)(linkCustomLibGroup) - - val libraries = { - strawmanLibrary + - linkCustomLib - }.keepOutput.checkCompile() - - // Setup class paths - def mkLinkClassFlags(libPath: String) = - TestFlags(mkClassPath(libPath :: Jars.dottyTestDeps), mkClassPath(Jars.dottyTestDeps), basicDefaultOptions :+ "-Xlink") - val strawmanClassPath = mkLinkClassFlags(defaultOutputDir + strawmanLibGroup + "/main/") - val customLibClassFlags = mkLinkClassFlags(defaultOutputDir + linkCustomLibGroup + "/custom-lib") - - // Link tests - val linkDir = "tests/link" - val linkStramanDir = linkDir + "/strawman" - val linkCustomLibDir = linkDir + "/on-custom-lib" - - val linkStrawmanTest = compileFilesInDir(linkStramanDir, strawmanClassPath)(strawmanLibTestGroup) - val linkCustomLibTest = compileFilesInDir(linkCustomLibDir, customLibClassFlags)(linkCustomLibTestGroup) - - def classFileChecks(sourceDir: String, testName: String) = { - val checkExt = ".classcheck" - for (check <- new JFile(sourceDir).listFiles().filter(_.toString.endsWith(checkExt))) { - val outDir = { - def path(str: String) = str.substring(linkDir.length, str.length - checkExt.length) - defaultOutputDir + testName + path(check.toString) + "/" - } - val expectedClasses = scala.io.Source.fromFile(check).getLines().toSet - val actualClasses = Files.walk(Paths.get(outDir)).iterator().asScala.collect { - case f if f.toString.endsWith(".class") => f.toString.substring(outDir.length, f.toString.length - ".class".length) - }.toSet - assertEquals(check.toString, expectedClasses, actualClasses) - } - } - - // Run all tests - val tests = { - linkStrawmanTest + - linkCustomLibTest - }.keepOutput.checkRuns() - - try { - classFileChecks(linkStramanDir, strawmanLibTestGroup.name) - classFileChecks(linkCustomLibDir, linkCustomLibTestGroup.name) - } finally { - (libraries + tests).delete() - } - } - -} - -object LinkTests { - implicit val summaryReport: SummaryReporting = new SummaryReport - @AfterClass def cleanup(): Unit = summaryReport.echoSummary() -} diff --git a/docs/docs/reference/changed/compiler-plugins.md b/docs/docs/reference/changed/compiler-plugins.md index 6abda9f69a39..a10201c4c7d4 100644 --- a/docs/docs/reference/changed/compiler-plugins.md +++ b/docs/docs/reference/changed/compiler-plugins.md @@ -60,7 +60,7 @@ import dotty.tools.dotc.core.Decorators._ import dotty.tools.dotc.core.StdNames._ import dotty.tools.dotc.core.Symbols._ import dotty.tools.dotc.plugins.{PluginPhase, StandardPlugin} -import dotty.tools.dotc.transform.{LinkAll, Pickler} +import dotty.tools.dotc.transform.{Pickler, ReifyQuotes} class DivideZero extends StandardPlugin { val name: String = "divideZero" @@ -75,7 +75,7 @@ class DivideZeroPhase extends PluginPhase { val phaseName = "divideZero" override val runsAfter = Set(Pickler.name) - override val runsBefore = Set(LinkAll.name) + override val runsBefore = Set(ReifyQuotes.name) override def transformApply(tree: Apply)(implicit ctx: Context): Tree = { tree match { diff --git a/sbt-dotty/sbt-test/sbt-dotty/compiler-plugin/plugin/DivideZero.scala b/sbt-dotty/sbt-test/sbt-dotty/compiler-plugin/plugin/DivideZero.scala index c7558a041b0a..ad7b93a4f40c 100644 --- a/sbt-dotty/sbt-test/sbt-dotty/compiler-plugin/plugin/DivideZero.scala +++ b/sbt-dotty/sbt-test/sbt-dotty/compiler-plugin/plugin/DivideZero.scala @@ -10,7 +10,7 @@ import transform.MegaPhase.MiniPhase import Decorators._ import Symbols.Symbol import Constants.Constant -import transform.{LinkAll, Pickler} +import transform.{Pickler, ReifyQuotes} /** Compiler plugin that emits an error when compiling a division by zero */ class DivideZero extends PluginPhase with StandardPlugin { @@ -20,7 +20,7 @@ class DivideZero extends PluginPhase with StandardPlugin { val phaseName = name override val runsAfter = Set(Pickler.name) - override val runsBefore = Set(LinkAll.name) + override val runsBefore = Set(ReifyQuotes.name) def init(options: List[String]): List[PluginPhase] = this :: Nil diff --git a/tests/plugins/neg/divideZero/plugin_1.scala b/tests/plugins/neg/divideZero/plugin_1.scala index 0db0c2906bbb..f9ff7612b119 100644 --- a/tests/plugins/neg/divideZero/plugin_1.scala +++ b/tests/plugins/neg/divideZero/plugin_1.scala @@ -8,7 +8,7 @@ import transform.MegaPhase.MiniPhase import Decorators._ import Symbols.Symbol import Constants.Constant -import transform.{LinkAll, Pickler} +import transform.{Pickler, ReifyQuotes} import StdNames._ class DivideZero extends PluginPhase with StandardPlugin { @@ -18,7 +18,7 @@ class DivideZero extends PluginPhase with StandardPlugin { val phaseName = name override val runsAfter = Set(Pickler.name) - override val runsBefore = Set(LinkAll.name) + override val runsBefore = Set(ReifyQuotes.name) override def init(options: List[String]): List[PluginPhase] = this :: Nil