From 8063ce953459afa878da719904fcf824b90ba0e6 Mon Sep 17 00:00:00 2001 From: Martin Odersky Date: Thu, 4 Jan 2018 13:49:45 +0100 Subject: [PATCH 1/5] Fix #3187: Don't crash in requiredClass if class is missing Also, issue stacktraces for missing refs only if Y-debug-missing-refs is set. The test case issues error messages without positions, so it is left in `pos`. --- compiler/src/dotty/tools/dotc/config/ScalaSettings.scala | 1 + compiler/src/dotty/tools/dotc/core/Denotations.scala | 4 ++-- compiler/src/dotty/tools/dotc/core/Symbols.scala | 5 ++++- tests/pos/i3187.scala | 3 +++ 4 files changed, 10 insertions(+), 3 deletions(-) create mode 100644 tests/pos/i3187.scala diff --git a/compiler/src/dotty/tools/dotc/config/ScalaSettings.scala b/compiler/src/dotty/tools/dotc/config/ScalaSettings.scala index 9d8471bc178d..8437db43fb3b 100644 --- a/compiler/src/dotty/tools/dotc/config/ScalaSettings.scala +++ b/compiler/src/dotty/tools/dotc/config/ScalaSettings.scala @@ -77,6 +77,7 @@ class ScalaSettings extends Settings.SettingGroup { val Ydebug = BooleanSetting("-Ydebug", "Increase the quantity of debugging output.") val YdebugTrace = BooleanSetting("-Ydebug-trace", "Trace core operations") val YdebugFlags = BooleanSetting("-Ydebug-flags", "Print all flags of definitions") + val YdebugMissingRefs = BooleanSetting("-Ydebug-missing-refs", "Print a stacktrace when a required symbol is missing") val YdebugNames = BooleanSetting("-Ydebug-names", "Show internal representation of names") val YdebugOwners = BooleanSetting("-Ydebug-owners", "Print all owners of definitions (requires -Yprint-syms)") val YtermConflict = ChoiceSetting("-Yresolve-term-conflict", "strategy", "Resolve term conflicts", List("package", "object", "error"), "error") diff --git a/compiler/src/dotty/tools/dotc/core/Denotations.scala b/compiler/src/dotty/tools/dotc/core/Denotations.scala index 70517a5ec7ad..3c8ae589da9c 100644 --- a/compiler/src/dotty/tools/dotc/core/Denotations.scala +++ b/compiler/src/dotty/tools/dotc/core/Denotations.scala @@ -277,7 +277,7 @@ object Denotations { disambiguate(p) match { case m @ MissingRef(ownerd, name) => if (generateStubs) { - m.ex.printStackTrace() + if (ctx.settings.YdebugMissingRefs.value) m.ex.printStackTrace() ctx.newStubSymbol(ownerd.symbol, name, source) } else NoSymbol @@ -1115,7 +1115,7 @@ object Denotations { * Produced by staticRef, consumed by requiredSymbol. */ case class MissingRef(val owner: SingleDenotation, name: Name)(implicit ctx: Context) extends ErrorDenotation { - val ex: Exception = new Exception + val ex: Exception = new Exception // DEBUG } /** An error denotation that provides more info about alternatives diff --git a/compiler/src/dotty/tools/dotc/core/Symbols.scala b/compiler/src/dotty/tools/dotc/core/Symbols.scala index e1998ca12833..98b3f4cc7182 100644 --- a/compiler/src/dotty/tools/dotc/core/Symbols.scala +++ b/compiler/src/dotty/tools/dotc/core/Symbols.scala @@ -369,7 +369,10 @@ trait Symbols { this: Context => def requiredPackageRef(path: PreName): TermRef = requiredPackage(path).termRef def requiredClass(path: PreName): ClassSymbol = - base.staticRef(path.toTypeName).requiredSymbol(_.isClass).asClass + base.staticRef(path.toTypeName).requiredSymbol(_.isClass) match { + case cls: ClassSymbol => cls + case sym => defn.AnyClass + } def requiredClassRef(path: PreName): TypeRef = requiredClass(path).typeRef diff --git a/tests/pos/i3187.scala b/tests/pos/i3187.scala new file mode 100644 index 000000000000..77568cc3f08d --- /dev/null +++ b/tests/pos/i3187.scala @@ -0,0 +1,3 @@ +package scala + +object collection From 20713eca891919f8f67e7630cfdbbf3ba7a0bbe1 Mon Sep 17 00:00:00 2001 From: Martin Odersky Date: Thu, 4 Jan 2018 16:06:51 +0100 Subject: [PATCH 2/5] Move test to neg --- tests/neg/i3187.scala | 23 +++++++++++++++++++++++ tests/pos/i3187.scala | 3 --- 2 files changed, 23 insertions(+), 3 deletions(-) create mode 100644 tests/neg/i3187.scala delete mode 100644 tests/pos/i3187.scala diff --git a/tests/neg/i3187.scala b/tests/neg/i3187.scala new file mode 100644 index 000000000000..25e098326bd1 --- /dev/null +++ b/tests/neg/i3187.scala @@ -0,0 +1,23 @@ +package scala + +// nopos-error +// nopos-error +// nopos-error +// nopos-error +// nopos-error +// nopos-error +// nopos-error +// nopos-error +// nopos-error +// nopos-error + +// nopos-error +// nopos-error +// nopos-error +// nopos-error +// nopos-error +// nopos-error +// nopos-error +// nopos-error + +object collection diff --git a/tests/pos/i3187.scala b/tests/pos/i3187.scala deleted file mode 100644 index 77568cc3f08d..000000000000 --- a/tests/pos/i3187.scala +++ /dev/null @@ -1,3 +0,0 @@ -package scala - -object collection From 8dcb2845c3ab4d691769718c50ba21a2d3d88a65 Mon Sep 17 00:00:00 2001 From: Martin Odersky Date: Sun, 7 Jan 2018 11:53:53 +0100 Subject: [PATCH 3/5] Use -YdebugMissingRefs in unpickler --- .../dotty/tools/dotc/core/unpickleScala2/Scala2Unpickler.scala | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/compiler/src/dotty/tools/dotc/core/unpickleScala2/Scala2Unpickler.scala b/compiler/src/dotty/tools/dotc/core/unpickleScala2/Scala2Unpickler.scala index 4247cb4fdfb9..dbbeb004eff7 100644 --- a/compiler/src/dotty/tools/dotc/core/unpickleScala2/Scala2Unpickler.scala +++ b/compiler/src/dotty/tools/dotc/core/unpickleScala2/Scala2Unpickler.scala @@ -179,7 +179,7 @@ class Scala2Unpickler(bytes: Array[Byte], classRoot: ClassDenotation, moduleClas val ex = new BadSignature( i"""error reading Scala signature of $classRoot from $source: |error occurred at position $readIndex: $msg""") - if (ctx.debug || true) original.getOrElse(ex).printStackTrace() // temporarily enable printing of original failure signature to debug failing builds + if (ctx.settings.YdebugMissingRefs.value) original.getOrElse(ex).printStackTrace() throw ex } From 2f0d0921d61a9d8b1ae4af3826cb9f3409e7a0e3 Mon Sep 17 00:00:00 2001 From: Martin Odersky Date: Sat, 27 Jan 2018 13:01:51 +0100 Subject: [PATCH 4/5] Address reviewer comments --- .../dotty/tools/dotc/core/unpickleScala2/Scala2Unpickler.scala | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/compiler/src/dotty/tools/dotc/core/unpickleScala2/Scala2Unpickler.scala b/compiler/src/dotty/tools/dotc/core/unpickleScala2/Scala2Unpickler.scala index dbbeb004eff7..609226feda47 100644 --- a/compiler/src/dotty/tools/dotc/core/unpickleScala2/Scala2Unpickler.scala +++ b/compiler/src/dotty/tools/dotc/core/unpickleScala2/Scala2Unpickler.scala @@ -415,7 +415,7 @@ class Scala2Unpickler(bytes: Array[Byte], classRoot: ClassDenotation, moduleClas owner.info.decls.checkConsistent() if (slowSearch(name).exists) System.err.println(i"**** slow search found: ${slowSearch(name)}") - if (ctx.debug) Thread.dumpStack() + if (ctx.settings.YdebugMissingRefs.value) Thread.dumpStack() ctx.newStubSymbol(owner, name, source) } } From df28080d5ceec2d8bd716351b7f2859a2f3eeed1 Mon Sep 17 00:00:00 2001 From: Olivier Blanvillain Date: Wed, 31 Jan 2018 15:33:00 +0100 Subject: [PATCH 5/5] Remove ShowClassTests This tests was already mostly disabled. The part that was left is also outdated: it checked that the dotty package creates less than 5 stubs, when in current states it creates 0 stubs. --- .../src/dotty/tools/dotc/core/Symbols.scala | 3 - .../test/dotty/tools/ShowClassTests.scala | 154 ------------------ compiler/test/dotty/tools/showClass.scala | 17 -- 3 files changed, 174 deletions(-) delete mode 100644 compiler/test/dotty/tools/ShowClassTests.scala delete mode 100644 compiler/test/dotty/tools/showClass.scala diff --git a/compiler/src/dotty/tools/dotc/core/Symbols.scala b/compiler/src/dotty/tools/dotc/core/Symbols.scala index 98b3f4cc7182..dc7c5c00dd0b 100644 --- a/compiler/src/dotty/tools/dotc/core/Symbols.scala +++ b/compiler/src/dotty/tools/dotc/core/Symbols.scala @@ -235,7 +235,6 @@ trait Symbols { this: Context => case name: TypeName => newClassSymbol(normalizedOwner, name, EmptyFlags, stubCompleter, assocFile = file) } - stubs = stub :: stubs stub } @@ -695,8 +694,6 @@ object Symbols { /** The current class */ def currentClass(implicit ctx: Context): ClassSymbol = ctx.owner.enclosingClass.asClass - @sharable var stubs: List[Symbol] = Nil // diagnostic only - /* Mutable map from symbols any T */ class MutableSymbolMap[T](private[Symbols] val value: java.util.IdentityHashMap[Symbol, T]) extends AnyVal { diff --git a/compiler/test/dotty/tools/ShowClassTests.scala b/compiler/test/dotty/tools/ShowClassTests.scala deleted file mode 100644 index 12a86dc5d764..000000000000 --- a/compiler/test/dotty/tools/ShowClassTests.scala +++ /dev/null @@ -1,154 +0,0 @@ -package dotty -package tools - -import dotc.core._ -import dotc.core.Contexts._ -import dotc.core.Symbols._ -import dotc.core.Flags._ -import dotc.core.Types._ -import dotc.printing.Texts._ -import NameOps._ -import dotc.core.Decorators._ -import org.junit.Test - -class ShowClassTests extends DottyTest { - ctx = { - val base = new ContextBase - import base.settings._ - val ctx = base.initialCtx.fresh - ctx.setSetting(ctx.settings.encoding, "UTF8") - ctx.setSetting( - ctx.settings.classpath, - Jars.dottyLib + ":" + Jars.dottyInterfaces - ) - base.initialize()(ctx) - ctx - } - - def debug_println(msg: => Any) = { - if (sys.props.isDefinedAt("test.ShowClassTests.verbose")) - println(msg) - } - - private val blackList = List( - // the following classes cannot be read correctly because they - // contain illegally pickled @throws annotations - "scala.actors.remote.Proxy", - "scala.actors.remote.Serializer", - "scala.actors.remote.JavaSerializer", - "scala.build.genprod", - "scala.tools.nsc.symtab.classfile.AbstractFileReader", - "scala.remoting.Channel", - "scala.runtime.remoting.RegistryDelegate", - "scala.concurrent.Future", - "scala.concurrent.impl.Future", - "scala.concurrent.Await", - "scala.concurrent.Awaitable", - "scala.concurrent.impl.Promise", - // the following class cannot be read because it does not exist anymore - "scala.reflect.macros.Context", - // the following packages and classes cannot be read because - // they refer to external libraries which are not available - // (apache.ant, usually) - "scala.tools.ant", - "scala.tools.partest.PartestTask", - "dotty.tools.dotc.core.pickling.AbstractFileReader") - - def doTwice(test: Context => Unit)(implicit ctx: Context): Unit = { - test(ctx.fresh.setSetting(ctx.base.settings.Ydebug, true)) - test(ctx.fresh.setSetting(ctx.base.settings.Ydebug, false)) - } - - def showPackage(pkg: TermSymbol)(implicit ctx: Context): Unit = { - val path = pkg.fullName.toString - if (blackList contains path) - debug_println(s"blacklisted package: $path") - else { - pkg.info.decls - .filter(sym => sym.owner == pkg.moduleClass && !(sym.name.toString contains '$')) - .foreach { sym => - debug_println(s"showing $sym in ${pkg.fullName}") - if (sym is PackageVal) showPackage(sym.asTerm) - else if (sym.isClass && !(sym is Module)) showClass(sym) - else if (sym is ModuleVal) showClass(sym.moduleClass) - } - } - } - - def showPackage(path: String, expectedStubs: Int)(implicit ctx: Context): Unit = doTwice { implicit ctx => - showPackage(ctx.requiredPackage(path)) - val nstubs = Symbols.stubs.length - debug_println(s"$nstubs stubs") - assert(nstubs <= expectedStubs, s"stubs found: $nstubs, expected: $expectedStubs\nstubs: ${Symbols.stubs.mkString(",")}") - } - - def showClass(cls: Symbol)(implicit ctx: Context) = { - val path = cls.fullName.stripModuleClassSuffix.toString - if (blackList contains path) - debug_println(s"blacklisted: $path") - else { - debug_println(s"showing $path -> ${cls.denot}") - val cinfo = cls.info - val infoStr = if (cinfo.exists) cinfo.show else " is missing" - debug_println("======================================") - debug_println(cls.show + infoStr) - } - } - - def showClasses(path: String)(implicit ctx: Context): Unit = doTwice { implicit ctx => - debug_println(s"showing file $path") - val cls = ctx.requiredClass(path.toTypeName) - showClass(cls) - showClass(cls.linkedClass) - } -/* - @Test - def loadSimpleClasses() = { - showClasses("scala.Array") - showClasses("scala.math.Ordering") - } - - @Test - def loadMoreClasses() = { - showClasses("scala.collection.JavaConversions") - showClasses("scala.collection.convert.Wrappers") - showClasses("scala.collection.mutable.WeakHashMap") - showClasses("scala.collection.GenIterable") - showClasses("scala.collection.Traversable") - showClasses("scala.collection.LinearSeqLike") - showClasses("scala.collection.immutable.List") - showClasses("scala.collection.convert.Wrappers") - showClasses("scala.collection.generic.package") - showClasses("scala.collection.MapLike") - showClasses("scala.Function1") - } - - @Test - def loadScalaReflect() = { - showPackage(ctx.requiredPackage("scala.reflect")) - } - - @Test - def loadScalaCollection() = { - showPackage(ctx.requiredPackage("scala.collection")) - } -*/ - /*@Test - def showScala() = { - showPackage("scala", 1) - } */ - // ping @odersky dotty.tools.dotc.core.Types$CyclicReference: cyclic reference involving class AnyVals, took 1.303 sec - // - - @Test - def loadDotty() = { - showPackage("dotty", 5) - } - - - /* - * @Test - def showReflectAliases() = { // tests for cycles during findMember - showClasses("scala.reflect.macros.runtime.Aliases") - }*/ -} diff --git a/compiler/test/dotty/tools/showClass.scala b/compiler/test/dotty/tools/showClass.scala deleted file mode 100644 index 012f5f59eac7..000000000000 --- a/compiler/test/dotty/tools/showClass.scala +++ /dev/null @@ -1,17 +0,0 @@ -package dotty.tools - -import dotc.core.Decorators._ - -object showClass extends ShowClassTests { - - def main(args: Array[String]) = { - for (arg <- args) showPackage(ctx.requiredPackage(arg)) -// showClasses("test.SyncOps") -// showClasses("scala.concurrent.forkjoin.LinkedTransferQueue") -// showPackage("scala.reflect") -// showPackage("scala.collection") - - showPackage("dotty", 1) - showPackage("scala", 2) - } -}