From 8e380b67366ab83d81fd401632af17d7cc0c2205 Mon Sep 17 00:00:00 2001 From: Paul Phillips Date: Thu, 10 Feb 2011 20:49:30 +0000 Subject: Created invisible setting to expose empty packa... Created invisible setting to expose empty package members outside of the empty package, so the repl can use packages without going blind to the empty package. This commit also eliminates a deadlock which hits when the compiler starts logging before a lazy val has pulled its head from the noose. Closes #4228, review by odersky. --- src/compiler/scala/tools/nsc/interpreter/IMain.scala | 18 +++++++++++++++--- .../scala/tools/nsc/settings/AbsSettings.scala | 7 ++++++- .../scala/tools/nsc/settings/MutableSettings.scala | 6 ++---- .../scala/tools/nsc/settings/ScalaSettings.scala | 2 ++ src/compiler/scala/tools/nsc/typechecker/Typers.scala | 19 ++++++++++++++++--- test/files/presentation/simple-tests.check | 7 +++++-- 6 files changed, 46 insertions(+), 13 deletions(-) diff --git a/src/compiler/scala/tools/nsc/interpreter/IMain.scala b/src/compiler/scala/tools/nsc/interpreter/IMain.scala index 02016d746b..c3cc0f9e03 100644 --- a/src/compiler/scala/tools/nsc/interpreter/IMain.scala +++ b/src/compiler/scala/tools/nsc/interpreter/IMain.scala @@ -94,6 +94,9 @@ class IMain(val settings: Settings, protected val out: PrintWriter) { * on the future. */ private val _compiler: Global = newCompiler(settings, reporter) + private var _initializeComplete = false + def isInitializeComplete = _initializeComplete + private def _initialize(): Boolean = { val source = """ |// this is assembled to force the loading of approximately the @@ -104,7 +107,7 @@ class IMain(val settings: Settings, protected val out: PrintWriter) { |} |""".stripMargin - try { + val result = try { new _compiler.Run() compileSources List(new BatchSourceFile("", source)) if (isReplDebug || settings.debug.value) { // Can't use printMessage here, it deadlocks @@ -129,6 +132,9 @@ class IMain(val settings: Settings, protected val out: PrintWriter) { ) false } + + try result + finally _initializeComplete = result } // set up initialization future @@ -225,6 +231,7 @@ class IMain(val settings: Settings, protected val out: PrintWriter) { * change the compiler class used by this interpreter. */ protected def newCompiler(settings: Settings, reporter: Reporter) = { settings.outputDirs setSingleOutput virtualDirectory + settings.exposeEmptyPackage.value = true new Global(settings, reporter) } @@ -1167,8 +1174,13 @@ object IMain { class ReplReporter(intp: IMain) extends ConsoleReporter(intp.settings, null, new ReplStrippingWriter(intp)) { override def printMessage(msg: String) { - if (intp.totalSilence) () - else super.printMessage(msg) + // Avoiding deadlock when the compiler starts logging before + // the lazy val is done. + if (intp.isInitializeComplete) { + if (intp.totalSilence) () + else super.printMessage(msg) + } + else Console.println(msg) } } } diff --git a/src/compiler/scala/tools/nsc/settings/AbsSettings.scala b/src/compiler/scala/tools/nsc/settings/AbsSettings.scala index a797cefef3..2e065a936c 100644 --- a/src/compiler/scala/tools/nsc/settings/AbsSettings.scala +++ b/src/compiler/scala/tools/nsc/settings/AbsSettings.scala @@ -82,7 +82,12 @@ trait AbsSettings { def respondsTo(label: String) = (name == label) || (abbreviations contains label) /** If the setting should not appear in help output, etc. */ - def isInternalOnly = false + private var internalSetting = false + def isInternalOnly = internalSetting + def internalOnly(): this.type = { + internalSetting = true + this + } /** Issue error and return */ def errorAndValue[T](msg: String, x: T): T = { errorFn(msg) ; x } diff --git a/src/compiler/scala/tools/nsc/settings/MutableSettings.scala b/src/compiler/scala/tools/nsc/settings/MutableSettings.scala index 3a6c1ccaa7..a5cc9ef3c7 100644 --- a/src/compiler/scala/tools/nsc/settings/MutableSettings.scala +++ b/src/compiler/scala/tools/nsc/settings/MutableSettings.scala @@ -226,11 +226,9 @@ class MutableSettings(val errorFn: String => Unit) extends AbsSettings with Scal def PhasesSetting(name: String, descr: String) = add(new PhasesSetting(name, descr)) def StringSetting(name: String, arg: String, descr: String, default: String) = add(new StringSetting(name, arg, descr, default)) def PathSetting(name: String, descr: String, default: String): PathSetting = { - val prepend = new StringSetting(name + "/p", "", "", "") with InternalSetting - val append = new StringSetting(name + "/a", "", "", "") with InternalSetting + val prepend = StringSetting(name + "/p", "", "", "").internalOnly() + val append = StringSetting(name + "/a", "", "", "").internalOnly() - add[StringSetting](prepend) - add[StringSetting](append) add(new PathSetting(name, descr, default, prepend, append)) } diff --git a/src/compiler/scala/tools/nsc/settings/ScalaSettings.scala b/src/compiler/scala/tools/nsc/settings/ScalaSettings.scala index 85bcefeb4c..8151da3869 100644 --- a/src/compiler/scala/tools/nsc/settings/ScalaSettings.scala +++ b/src/compiler/scala/tools/nsc/settings/ScalaSettings.scala @@ -147,6 +147,8 @@ trait ScalaSettings extends AbsScalaSettings with StandardScalaSettings { val noSelfCheck = BooleanSetting ("-Yno-self-type-checks", "Suppress check for self-type conformance among inherited members.") val YvirtClasses = false // too embryonic to even expose as a -Y //BooleanSetting ("-Yvirtual-classes", "Support virtual classes") + val exposeEmptyPackage = BooleanSetting("-Yexpose-empty-package", "Internal only: expose the empty package.").internalOnly() + /** * Warnings */ diff --git a/src/compiler/scala/tools/nsc/typechecker/Typers.scala b/src/compiler/scala/tools/nsc/typechecker/Typers.scala index 396bb5ca0e..d805a33940 100644 --- a/src/compiler/scala/tools/nsc/typechecker/Typers.scala +++ b/src/compiler/scala/tools/nsc/typechecker/Typers.scala @@ -3575,6 +3575,14 @@ trait Typers extends Modes { // for being inaccessible; used for error reporting var inaccessibleExplanation: String = "" + // If a special setting is given, the empty package will be checked as a + // last ditch effort before failing. This method sets defSym and returns + // true if a member of the given name exists. + def checkEmptyPackage(): Boolean = { + defSym = EmptyPackageClass.tpe.nonPrivateMember(name) + defSym != NoSymbol + } + // A symbol qualifies if it exists and is not stale. Stale symbols // are made to disappear here. In addition, // if we are in a constructor of a pattern, we ignore all definitions @@ -3679,15 +3687,20 @@ trait Typers extends Modes { if (!(shortenImports && qual0.symbol.isPackage)) // optimization: don't write out package prefixes qual = atPos(tree.pos.focusStart)(resetPos(qual0.duplicate)) pre = qual.tpe - } else { + } + else if (settings.exposeEmptyPackage.value && checkEmptyPackage()) + log("Allowing empty package member " + name + " due to settings.") + else { if (settings.debug.value) { log(context.imports)//debug } if (inaccessibleSym eq NoSymbol) { error(tree.pos, "not found: "+decodeWithNamespace(name)) - } else accessError( + } + else accessError( tree, inaccessibleSym, context.enclClass.owner.thisType, - inaccessibleExplanation) + inaccessibleExplanation + ) defSym = context.owner.newErrorSymbol(name) } } diff --git a/test/files/presentation/simple-tests.check b/test/files/presentation/simple-tests.check index 67d8ac7269..8cc891af4b 100644 --- a/test/files/presentation/simple-tests.check +++ b/test/files/presentation/simple-tests.check @@ -3,7 +3,7 @@ askTypeCompletion at Tester.scala(16,25) ================================================================================ [response] aksTypeCompletion at (16,25) -retreived 75 members +retreived 77 members TypeMember(method !=,(x$1: AnyRef)Boolean,true,true,) TypeMember(method !=,(x$1: Any)Boolean,true,true,) TypeMember(method ==,(x$1: AnyRef)Boolean,true,true,) @@ -46,6 +46,8 @@ TypeMember(method formatted,(fmtstr: String)String,true,false,method any2stringa TypeMember(method hashCode,()Int,true,true,) TypeMember(value helpDescription,String,false,true,) TypeMember(method helpSyntax,=> String,true,true,) +TypeMember(method internalOnly,()Tester.this.settings.verbose.type,true,true,) +TypeMember(variable internalSetting,Boolean,false,true,) TypeMember(method isAdvanced,=> Boolean,true,true,) TypeMember(method isDefault,=> Boolean,true,true,) TypeMember(method isForDebug,=> Boolean,true,true,) @@ -132,7 +134,7 @@ askTypeCompletion at Tester.scala(27,23) ================================================================================ [response] aksTypeCompletion at (27,23) -retreived 195 members +retreived 196 members TypeMember(method !=,(x$1: AnyRef)Boolean,true,true,) TypeMember(method !=,(x$1: Any)Boolean,true,true,) TypeMember(method ==,(x$1: AnyRef)Boolean,true,true,) @@ -255,6 +257,7 @@ TypeMember(method equals,(that: Any)Boolean,true,true,) TypeMember(value errorFn,(String) => Unit,false,false,) TypeMember(value explaintypes,Tester.this.settings.BooleanSetting,false,true,) TypeMember(variable explicitParentLoader,Option[java.lang.ClassLoader],false,true,) +TypeMember(value exposeEmptyPackage,Tester.this.settings.BooleanSetting,false,true,) TypeMember(value extdirs,Tester.this.settings.PathSetting,false,true,) TypeMember(method finalize,()Unit,false,true,) TypeMember(method formatted,(fmtstr: String)String,true,false,method any2stringadd) -- cgit v1.2.3