From 213116631aa2e338e09b6f6de93f8e9ef216ce14 Mon Sep 17 00:00:00 2001 From: Den Shabalin Date: Fri, 16 Aug 2013 12:17:22 +0200 Subject: SI-7757 disallow constructor annotations on traits Previously it was possible to define constructor annotations on traits with really weird side-effects (parser lost the body of the trait). Now constructor annotations on traits will cause appropriate syntax errors. --- src/compiler/scala/tools/nsc/ast/parser/Parsers.scala | 2 +- test/files/neg/t7757.check | 4 ++++ test/files/neg/t7757.scala | 1 + 3 files changed, 6 insertions(+), 1 deletion(-) create mode 100644 test/files/neg/t7757.check create mode 100644 test/files/neg/t7757.scala diff --git a/src/compiler/scala/tools/nsc/ast/parser/Parsers.scala b/src/compiler/scala/tools/nsc/ast/parser/Parsers.scala index d0b0c09d59..a4093f9afa 100644 --- a/src/compiler/scala/tools/nsc/ast/parser/Parsers.scala +++ b/src/compiler/scala/tools/nsc/ast/parser/Parsers.scala @@ -2665,7 +2665,7 @@ self => syntaxError("traits cannot have type parameters with context bounds `: ...' nor view bounds `<% ...'", skipIt = false) classContextBounds = List() } - val constrAnnots = constructorAnnotations() + val constrAnnots = if (!mods.isTrait) constructorAnnotations() else Nil val (constrMods, vparamss) = if (mods.isTrait) (Modifiers(Flags.TRAIT), List()) else (accessModifierOpt(), paramClauses(name, classContextBounds, ofCaseClass = mods.isCase)) diff --git a/test/files/neg/t7757.check b/test/files/neg/t7757.check new file mode 100644 index 0000000000..8790cbc428 --- /dev/null +++ b/test/files/neg/t7757.check @@ -0,0 +1,4 @@ +t7757.scala:1: error: ';' expected but '@' found. +trait Foo @annot + ^ +one error found diff --git a/test/files/neg/t7757.scala b/test/files/neg/t7757.scala new file mode 100644 index 0000000000..24f6c16cb4 --- /dev/null +++ b/test/files/neg/t7757.scala @@ -0,0 +1 @@ +trait Foo @annot \ No newline at end of file -- cgit v1.2.3 From a721df7e030b2ba69e7a51d4821bc3622e4c6774 Mon Sep 17 00:00:00 2001 From: Den Shabalin Date: Fri, 16 Aug 2013 13:41:46 +0200 Subject: SI-7757 add additional test case with annotation on the next line --- test/files/neg/t7757.check | 4 ---- test/files/neg/t7757.scala | 1 - test/files/neg/t7757a.check | 4 ++++ test/files/neg/t7757a.scala | 1 + test/files/neg/t7757b.check | 4 ++++ test/files/neg/t7757b.scala | 2 ++ 6 files changed, 11 insertions(+), 5 deletions(-) delete mode 100644 test/files/neg/t7757.check delete mode 100644 test/files/neg/t7757.scala create mode 100644 test/files/neg/t7757a.check create mode 100644 test/files/neg/t7757a.scala create mode 100644 test/files/neg/t7757b.check create mode 100644 test/files/neg/t7757b.scala diff --git a/test/files/neg/t7757.check b/test/files/neg/t7757.check deleted file mode 100644 index 8790cbc428..0000000000 --- a/test/files/neg/t7757.check +++ /dev/null @@ -1,4 +0,0 @@ -t7757.scala:1: error: ';' expected but '@' found. -trait Foo @annot - ^ -one error found diff --git a/test/files/neg/t7757.scala b/test/files/neg/t7757.scala deleted file mode 100644 index 24f6c16cb4..0000000000 --- a/test/files/neg/t7757.scala +++ /dev/null @@ -1 +0,0 @@ -trait Foo @annot \ No newline at end of file diff --git a/test/files/neg/t7757a.check b/test/files/neg/t7757a.check new file mode 100644 index 0000000000..de24e23004 --- /dev/null +++ b/test/files/neg/t7757a.check @@ -0,0 +1,4 @@ +t7757a.scala:1: error: ';' expected but '@' found. +trait Foo @annot + ^ +one error found diff --git a/test/files/neg/t7757a.scala b/test/files/neg/t7757a.scala new file mode 100644 index 0000000000..24f6c16cb4 --- /dev/null +++ b/test/files/neg/t7757a.scala @@ -0,0 +1 @@ +trait Foo @annot \ No newline at end of file diff --git a/test/files/neg/t7757b.check b/test/files/neg/t7757b.check new file mode 100644 index 0000000000..3e5a0f1fa6 --- /dev/null +++ b/test/files/neg/t7757b.check @@ -0,0 +1,4 @@ +t7757b.scala:2: error: expected start of definition +@annot2 + ^ +one error found diff --git a/test/files/neg/t7757b.scala b/test/files/neg/t7757b.scala new file mode 100644 index 0000000000..e9a537dba1 --- /dev/null +++ b/test/files/neg/t7757b.scala @@ -0,0 +1,2 @@ +trait Foo2 +@annot2 \ No newline at end of file -- cgit v1.2.3 From 3df1d77fc984b976efa68098206e801cf3b83a9e Mon Sep 17 00:00:00 2001 From: Jason Zaugg Date: Fri, 16 Aug 2013 14:18:20 +0200 Subject: SI-7756 Uncripple refchecks in case bodies In 65340ed4ad2e, parts of RefChecks were disabled when we traversed into the results of the new pattern matcher. Similar logic existed for the old pattern matcher, but in that case the Match / CaseDef nodes still existed in the tree. The new approach was too broad: important checks no longer scrutinized the body of cases. This commit turns the checks back on when it finds the remnants of a case body, which appears as an application to a label def. --- .../scala/tools/nsc/typechecker/RefChecks.scala | 35 +++++++++++++++++----- test/files/neg/t7756a.check | 7 +++++ test/files/neg/t7756a.scala | 11 +++++++ test/files/neg/t7756b.check | 6 ++++ test/files/neg/t7756b.flags | 1 + test/files/neg/t7756b.scala | 5 ++++ 6 files changed, 57 insertions(+), 8 deletions(-) create mode 100644 test/files/neg/t7756a.check create mode 100644 test/files/neg/t7756a.scala create mode 100644 test/files/neg/t7756b.check create mode 100644 test/files/neg/t7756b.flags create mode 100644 test/files/neg/t7756b.scala diff --git a/src/compiler/scala/tools/nsc/typechecker/RefChecks.scala b/src/compiler/scala/tools/nsc/typechecker/RefChecks.scala index 1b6963b598..30b923e2a1 100644 --- a/src/compiler/scala/tools/nsc/typechecker/RefChecks.scala +++ b/src/compiler/scala/tools/nsc/typechecker/RefChecks.scala @@ -113,6 +113,11 @@ abstract class RefChecks extends InfoTransform with scala.reflect.internal.trans var localTyper: analyzer.Typer = typer var currentApplication: Tree = EmptyTree var inPattern: Boolean = false + @inline final def savingInPattern[A](body: => A): A = { + val saved = inPattern + try body finally inPattern = saved + } + var checkedCombinations = Set[List[Type]]() // only one overloaded alternative is allowed to define default arguments @@ -1667,19 +1672,33 @@ abstract class RefChecks extends InfoTransform with scala.reflect.internal.trans case _ => tree } + // skip refchecks in patterns.... result = result match { case CaseDef(pat, guard, body) => - inPattern = true - val pat1 = transform(pat) - inPattern = false + val pat1 = savingInPattern { + inPattern = true + transform(pat) + } treeCopy.CaseDef(tree, pat1, transform(guard), transform(body)) case LabelDef(_, _, _) if treeInfo.hasSynthCaseSymbol(result) => - val old = inPattern - inPattern = true - val res = deriveLabelDef(result)(transform) - inPattern = old - res + savingInPattern { + inPattern = true + deriveLabelDef(result)(transform) + } + case Apply(fun, args) if fun.symbol.isLabel && treeInfo.isSynthCaseSymbol(fun.symbol) => + savingInPattern { + // SI-7756 If we were in a translated pattern, we can now switch out of pattern mode, as the label apply signals + // that we are in the user-supplied code in the case body. + // + // Relies on the translation of: + // (null: Any) match { case x: List[_] => x; x.reverse; case _ => }' + // to: + // val x2: List[_] = (x1.asInstanceOf[List[_]]: List[_]); + // matchEnd4({ x2; x2.reverse}) // case body is an argument to a label apply. + inPattern = false + super.transform(result) + } case _ => super.transform(result) } diff --git a/test/files/neg/t7756a.check b/test/files/neg/t7756a.check new file mode 100644 index 0000000000..8d42717e47 --- /dev/null +++ b/test/files/neg/t7756a.check @@ -0,0 +1,7 @@ +t7756a.scala:7: error: type arguments [Object] do not conform to trait TA's type parameter bounds [X <: CharSequence] + locally(null: TA[Object]) + ^ +t7756a.scala:7: error: type arguments [Object] do not conform to trait TA's type parameter bounds [X <: CharSequence] + locally(null: TA[Object]) + ^ +two errors found diff --git a/test/files/neg/t7756a.scala b/test/files/neg/t7756a.scala new file mode 100644 index 0000000000..4453e84963 --- /dev/null +++ b/test/files/neg/t7756a.scala @@ -0,0 +1,11 @@ +object Test { + def test: Unit = { + trait TA[X <: CharSequence] + 0 match { + case _ => + // the bounds violation isn't reported. RefChecks seems to be too broadly disabled under virtpatmat: see 65340ed4ad2e + locally(null: TA[Object]) + () + } + } +} diff --git a/test/files/neg/t7756b.check b/test/files/neg/t7756b.check new file mode 100644 index 0000000000..2817a7e230 --- /dev/null +++ b/test/files/neg/t7756b.check @@ -0,0 +1,6 @@ +t7756b.scala:3: warning: comparing values of types Int and String using `==' will always yield false + case _ => 0 == "" + ^ +error: No warnings can be incurred under -Xfatal-warnings. +one warning found +one error found diff --git a/test/files/neg/t7756b.flags b/test/files/neg/t7756b.flags new file mode 100644 index 0000000000..85d8eb2ba2 --- /dev/null +++ b/test/files/neg/t7756b.flags @@ -0,0 +1 @@ +-Xfatal-warnings diff --git a/test/files/neg/t7756b.scala b/test/files/neg/t7756b.scala new file mode 100644 index 0000000000..a2de29c8e7 --- /dev/null +++ b/test/files/neg/t7756b.scala @@ -0,0 +1,5 @@ +object Test { + 0 match { + case _ => 0 == "" + } +} -- cgit v1.2.3 From a0a2aa26762aa773dc3f0f20a574c9bf1e3c37e2 Mon Sep 17 00:00:00 2001 From: Jason Zaugg Date: Mon, 19 Aug 2013 10:56:06 +0200 Subject: SI-6797 Test case for already-fixed DelayedInit bug Progressed in b4fbb7be0e2, "translation for DelayedInit keeps more code in original class." --- test/files/pos/t6797.scala | 4 ++++ 1 file changed, 4 insertions(+) create mode 100644 test/files/pos/t6797.scala diff --git a/test/files/pos/t6797.scala b/test/files/pos/t6797.scala new file mode 100644 index 0000000000..ef1afa1eb3 --- /dev/null +++ b/test/files/pos/t6797.scala @@ -0,0 +1,4 @@ +object Test extends App /* workaround: don't extend App */ { + private class Matcher(aParam: Option[String] = None) + private val stringMatcher = new Matcher +} -- cgit v1.2.3 From 48d14aaaced95ef2577bf8bc799c4a74788e4663 Mon Sep 17 00:00:00 2001 From: Som Snytt Date: Mon, 19 Aug 2013 07:22:28 -0700 Subject: SI-7729 Fix broken windows build Fixing #ifdiff uncovered a latent bug in partest when it detects paths to normalize in test log output. It would not normalize file separators for test names with non-word characters. This commit normalizes the test name to the ticket number as a workaround until the next partest version is picked up. It also fixes partest in this repo in case we've not yet switched over to the new repo. A separate PR will be submitted to the new repo as necessary. --- src/partest/scala/tools/partest/nest/Runner.scala | 2 +- test/files/neg/javac-error.check | 10 ---------- test/files/neg/javac-error.flags | 1 - test/files/neg/javac-error/J.java | 5 ----- test/files/neg/javac-error/SUT_5.scala | 5 ----- test/files/neg/t6289.check | 10 ++++++++++ test/files/neg/t6289.flags | 1 + test/files/neg/t6289/J.java | 5 +++++ test/files/neg/t6289/SUT_5.scala | 5 +++++ 9 files changed, 22 insertions(+), 22 deletions(-) delete mode 100644 test/files/neg/javac-error.check delete mode 100644 test/files/neg/javac-error.flags delete mode 100644 test/files/neg/javac-error/J.java delete mode 100644 test/files/neg/javac-error/SUT_5.scala create mode 100644 test/files/neg/t6289.check create mode 100644 test/files/neg/t6289.flags create mode 100644 test/files/neg/t6289/J.java create mode 100644 test/files/neg/t6289/SUT_5.scala diff --git a/src/partest/scala/tools/partest/nest/Runner.scala b/src/partest/scala/tools/partest/nest/Runner.scala index fa2fb99f2f..470a2188de 100644 --- a/src/partest/scala/tools/partest/nest/Runner.scala +++ b/src/partest/scala/tools/partest/nest/Runner.scala @@ -357,7 +357,7 @@ class Runner(val testFile: File, fileManager: FileManager, val testRunParams: Te val ellipsis = "" //".../" // using * looks like a comment // no spaces in test file paths below root, because otherwise how to detect end of path string? - val pathFinder = raw"""(?i)\Q${elided}${File.separator}\E([\${File.separator}\w]*)""".r + val pathFinder = raw"""(?i)\Q${elided}${File.separator}\E([\${File.separator}\S]*)""".r def canonicalize(s: String): String = ( pathFinder replaceAllIn (s, m => ellipsis + squashSlashes(m group 1)) ) diff --git a/test/files/neg/javac-error.check b/test/files/neg/javac-error.check deleted file mode 100644 index e7d1ccc1a1..0000000000 --- a/test/files/neg/javac-error.check +++ /dev/null @@ -1,10 +0,0 @@ -#partest java6 -javac-error/J.java:2: method does not override or implement a method from a supertype - @Override public void foo() { } - ^ -1 error -#partest java7 -javac-error/J.java:2: error: method does not override or implement a method from a supertype - @Override public void foo() { } - ^ -1 error diff --git a/test/files/neg/javac-error.flags b/test/files/neg/javac-error.flags deleted file mode 100644 index 85d8eb2ba2..0000000000 --- a/test/files/neg/javac-error.flags +++ /dev/null @@ -1 +0,0 @@ --Xfatal-warnings diff --git a/test/files/neg/javac-error/J.java b/test/files/neg/javac-error/J.java deleted file mode 100644 index 83f50c9ae2..0000000000 --- a/test/files/neg/javac-error/J.java +++ /dev/null @@ -1,5 +0,0 @@ -public class J { - @Override public void foo() { } - - public void bar() { foo(); } -} diff --git a/test/files/neg/javac-error/SUT_5.scala b/test/files/neg/javac-error/SUT_5.scala deleted file mode 100644 index 0a996352c0..0000000000 --- a/test/files/neg/javac-error/SUT_5.scala +++ /dev/null @@ -1,5 +0,0 @@ - -/** The System Under Test. - * We bail on the earlier round that generates the first error. - */ -class SUT extends J diff --git a/test/files/neg/t6289.check b/test/files/neg/t6289.check new file mode 100644 index 0000000000..f6f43cabd3 --- /dev/null +++ b/test/files/neg/t6289.check @@ -0,0 +1,10 @@ +#partest java6 +t6289/J.java:2: method does not override or implement a method from a supertype + @Override public void foo() { } + ^ +1 error +#partest java7 +t6289/J.java:2: error: method does not override or implement a method from a supertype + @Override public void foo() { } + ^ +1 error diff --git a/test/files/neg/t6289.flags b/test/files/neg/t6289.flags new file mode 100644 index 0000000000..85d8eb2ba2 --- /dev/null +++ b/test/files/neg/t6289.flags @@ -0,0 +1 @@ +-Xfatal-warnings diff --git a/test/files/neg/t6289/J.java b/test/files/neg/t6289/J.java new file mode 100644 index 0000000000..83f50c9ae2 --- /dev/null +++ b/test/files/neg/t6289/J.java @@ -0,0 +1,5 @@ +public class J { + @Override public void foo() { } + + public void bar() { foo(); } +} diff --git a/test/files/neg/t6289/SUT_5.scala b/test/files/neg/t6289/SUT_5.scala new file mode 100644 index 0000000000..0a996352c0 --- /dev/null +++ b/test/files/neg/t6289/SUT_5.scala @@ -0,0 +1,5 @@ + +/** The System Under Test. + * We bail on the earlier round that generates the first error. + */ +class SUT extends J -- cgit v1.2.3 From fde88c76ceb1e575b89c813a039df1967c6f995c Mon Sep 17 00:00:00 2001 From: Paul Phillips Date: Mon, 19 Aug 2013 15:12:04 -0700 Subject: No longer crash on NoSymbol.owner. Historically calling NoSymbol.owner has crashed the compiler. With this commit, NoSymbol owns itself. This is consistent with the way ownership chains are handled elsewhere in the compiler (e.g. NoContext.owner is NoContext, NoSymbol.enclClass is NoSymbol, and so on) and frees every call site which handles symbols from having to perform precondition tests against NoSymbol. Since calling NoSymbol.owner sometimes (not always) indicates a bug which we'd like to catch sooner than later, I have introduced a couple more methods for selected call sites. def owner: Symbol // NoSymbol.owner is self, log if -Xdev def safeOwner: Symbol // NoSymbol.owner is self, ignore def assertOwner: Symbol // NoSymbol.owner is fatal The idea is that everyone can call sym.owner without undue anxiety or paranoid null-like tests. When compiling under -Xdev calls to `owner` are logged with a stack trace, so any call sites for which that is an expected occurrence should call safeOwner instead to communicate the intention and stay out of the log. Conversely, any call site where crashing on the owner call was a desirable behavior can opt into calling assertOwner. This commit also includes all the safeOwner calls necessary to give us a silent log when compiling scala. --- .../scala/reflect/macros/compiler/Validators.scala | 6 +++- src/compiler/scala/tools/nsc/Global.scala | 5 ++- src/compiler/scala/tools/nsc/ast/Trees.scala | 5 +-- .../scala/tools/nsc/backend/opt/Inliners.scala | 8 ++--- .../scala/tools/nsc/transform/AddInterfaces.scala | 26 -------------- .../scala/tools/nsc/transform/Erasure.scala | 3 +- .../scala/tools/nsc/transform/LambdaLift.scala | 2 +- src/compiler/scala/tools/nsc/transform/Mixin.scala | 5 +-- .../tools/nsc/transform/patmat/MatchAnalysis.scala | 8 ++--- .../tools/nsc/transform/patmat/MatchCodeGen.scala | 4 +-- .../nsc/transform/patmat/MatchTranslation.scala | 2 +- .../nsc/transform/patmat/MatchTreeMaking.scala | 3 +- .../scala/tools/nsc/typechecker/Contexts.scala | 13 +++---- .../scala/tools/nsc/typechecker/Duplicators.scala | 36 +++++++++---------- .../scala/tools/nsc/typechecker/Namers.scala | 4 +-- .../scala/tools/nsc/typechecker/RefChecks.scala | 4 +-- .../tools/nsc/typechecker/SuperAccessors.scala | 4 +-- .../tools/nsc/typechecker/TypeDiagnostics.scala | 2 +- .../scala/tools/nsc/typechecker/Typers.scala | 4 +++ .../scala/reflect/internal/Definitions.scala | 5 +-- .../scala/reflect/internal/SymbolTable.scala | 7 +++- src/reflect/scala/reflect/internal/Symbols.scala | 41 ++++++++++++++-------- src/reflect/scala/reflect/internal/Trees.scala | 4 +-- src/reflect/scala/reflect/internal/Types.scala | 2 +- .../scala/reflect/internal/tpe/TypeMaps.scala | 4 +-- src/repl/scala/tools/nsc/interpreter/IMain.scala | 14 ++------ .../tools/nsc/interpreter/MemberHandlers.scala | 2 +- 27 files changed, 96 insertions(+), 127 deletions(-) diff --git a/src/compiler/scala/reflect/macros/compiler/Validators.scala b/src/compiler/scala/reflect/macros/compiler/Validators.scala index fafd79d1d7..af17fd87c0 100644 --- a/src/compiler/scala/reflect/macros/compiler/Validators.scala +++ b/src/compiler/scala/reflect/macros/compiler/Validators.scala @@ -81,7 +81,11 @@ trait Validators { // Technically this can be just an alias to MethodType, but promoting it to a first-class entity // provides better encapsulation and convenient syntax for pattern matching. - private case class MacroImplSig(tparams: List[Symbol], paramss: List[List[Symbol]], ret: Type) + private case class MacroImplSig(tparams: List[Symbol], paramss: List[List[Symbol]], ret: Type) { + private def tparams_s = if (tparams.isEmpty) "" else tparams.map(_.defString).mkString("[", ", ", "]") + private def paramss_s = paramss map (ps => ps.map(s => s"${s.name}: ${s.tpe_*}").mkString("(", ", ", ")")) mkString "" + override def toString = "MacroImplSig(" + tparams_s + paramss_s + ret + ")" + } /** An actual macro implementation signature extracted from a macro implementation method. * diff --git a/src/compiler/scala/tools/nsc/Global.scala b/src/compiler/scala/tools/nsc/Global.scala index a6c69091c5..dcb41752f7 100644 --- a/src/compiler/scala/tools/nsc/Global.scala +++ b/src/compiler/scala/tools/nsc/Global.scala @@ -258,6 +258,9 @@ class Global(var currentSettings: Settings, var reporter: Reporter) if (settings.debug) body } + + override protected def isDeveloper = settings.developer || super.isDeveloper + /** This is for WARNINGS which should reach the ears of scala developers * whenever they occur, but are not useful for normal users. They should * be precise, explanatory, and infrequent. Please don't use this as a @@ -265,7 +268,7 @@ class Global(var currentSettings: Settings, var reporter: Reporter) * to make them visually distinct. */ @inline final override def devWarning(msg: => String) { - if (settings.developer || settings.debug) + if (isDeveloper) warning("!!! " + msg) else log("!!! " + msg) // such warnings always at least logged diff --git a/src/compiler/scala/tools/nsc/ast/Trees.scala b/src/compiler/scala/tools/nsc/ast/Trees.scala index 641ab9c279..381ffb1ed9 100644 --- a/src/compiler/scala/tools/nsc/ast/Trees.scala +++ b/src/compiler/scala/tools/nsc/ast/Trees.scala @@ -66,10 +66,7 @@ trait Trees extends scala.reflect.internal.Trees { self: Global => */ def ClassDef(sym: Symbol, constrMods: Modifiers, vparamss: List[List[ValDef]], body: List[Tree], superPos: Position): ClassDef = { // "if they have symbols they should be owned by `sym`" - assert( - mforall(vparamss)(p => (p.symbol eq NoSymbol) || (p.symbol.owner == sym)), - ((mmap(vparamss)(_.symbol), sym)) - ) + assert(mforall(vparamss)(_.symbol.owner == sym), (mmap(vparamss)(_.symbol), sym)) ClassDef(sym, gen.mkTemplate(sym.info.parents map TypeTree, diff --git a/src/compiler/scala/tools/nsc/backend/opt/Inliners.scala b/src/compiler/scala/tools/nsc/backend/opt/Inliners.scala index 56191cc981..09095879bf 100644 --- a/src/compiler/scala/tools/nsc/backend/opt/Inliners.scala +++ b/src/compiler/scala/tools/nsc/backend/opt/Inliners.scala @@ -78,10 +78,10 @@ abstract class Inliners extends SubComponent { assert(clazz != NoSymbol, "Walked up past Object.superClass looking for " + sym + ", most likely this reveals the TFA at fault (receiver and callee don't match).") if (sym.owner == clazz || isBottomType(clazz)) sym - else sym.overridingSymbol(clazz) match { - case NoSymbol => if (sym.owner.isTrait) sym else lookup(clazz.superClass) - case imp => imp - } + else sym.overridingSymbol(clazz) orElse ( + if (sym.owner.isTrait) sym + else lookup(clazz.superClass) + ) } if (needsLookup) { val concreteMethod = lookup(clazz) diff --git a/src/compiler/scala/tools/nsc/transform/AddInterfaces.scala b/src/compiler/scala/tools/nsc/transform/AddInterfaces.scala index 0dcf4d00b7..d9d08dde1e 100644 --- a/src/compiler/scala/tools/nsc/transform/AddInterfaces.scala +++ b/src/compiler/scala/tools/nsc/transform/AddInterfaces.scala @@ -367,29 +367,3 @@ abstract class AddInterfaces extends InfoTransform { self: Erasure => } } } -/* - val ensureNoEscapes = new TypeTraverser { - def ensureNoEscape(sym: Symbol) { - if (sym.hasFlag(PRIVATE)) { - var o = currentOwner; - while (o != NoSymbol && o != sym.owner && !o.isLocal && !o.hasFlag(PRIVATE)) - o = o.owner - if (o == sym.owner) sym.makeNotPrivate(base); - } - } - def traverse(t: Type): TypeTraverser = { - t match { - case TypeRef(qual, sym, args) => - ensureNoEscape(sym) - mapOver(t) - case ClassInfoType(parents, decls, clazz) => - parents foreach { p => traverse; () } - traverse(t.typeOfThis) - case _ => - mapOver(t) - } - this - } - } - -*/ diff --git a/src/compiler/scala/tools/nsc/transform/Erasure.scala b/src/compiler/scala/tools/nsc/transform/Erasure.scala index ee687e56b0..0a66ba8a32 100644 --- a/src/compiler/scala/tools/nsc/transform/Erasure.scala +++ b/src/compiler/scala/tools/nsc/transform/Erasure.scala @@ -525,8 +525,7 @@ abstract class Erasure extends AddInterfaces private def isDifferentErasedValueType(tpe: Type, other: Type) = isErasedValueType(tpe) && (tpe ne other) - private def isPrimitiveValueMember(sym: Symbol) = - sym != NoSymbol && isPrimitiveValueClass(sym.owner) + private def isPrimitiveValueMember(sym: Symbol) = isPrimitiveValueClass(sym.owner) @inline private def box(tree: Tree, target: => String): Tree = { val result = box1(tree) diff --git a/src/compiler/scala/tools/nsc/transform/LambdaLift.scala b/src/compiler/scala/tools/nsc/transform/LambdaLift.scala index ce495ca8ca..515fa66cfa 100644 --- a/src/compiler/scala/tools/nsc/transform/LambdaLift.scala +++ b/src/compiler/scala/tools/nsc/transform/LambdaLift.scala @@ -489,7 +489,7 @@ abstract class LambdaLift extends InfoTransform { treeCopy.Assign(tree, qual, rhs) case Ident(name) => val tree1 = - if (sym != NoSymbol && sym.isTerm && !sym.isLabel) + if (sym.isTerm && !sym.isLabel) if (sym.isMethod) atPos(tree.pos)(memberRef(sym)) else if (sym.isLocal && !isSameOwnerEnclosure(sym)) diff --git a/src/compiler/scala/tools/nsc/transform/Mixin.scala b/src/compiler/scala/tools/nsc/transform/Mixin.scala index 1c44e86aca..3ec4d16bf5 100644 --- a/src/compiler/scala/tools/nsc/transform/Mixin.scala +++ b/src/compiler/scala/tools/nsc/transform/Mixin.scala @@ -734,10 +734,7 @@ abstract class Mixin extends InfoTransform with ast.TreeDSL { sym } - if (sym ne NoSymbol) - sym - else - createBitmap + sym orElse createBitmap } def maskForOffset(offset: Int, sym: Symbol, kind: ClassSymbol): Tree = { diff --git a/src/compiler/scala/tools/nsc/transform/patmat/MatchAnalysis.scala b/src/compiler/scala/tools/nsc/transform/patmat/MatchAnalysis.scala index f089c8f5a5..dfd18d089e 100644 --- a/src/compiler/scala/tools/nsc/transform/patmat/MatchAnalysis.scala +++ b/src/compiler/scala/tools/nsc/transform/patmat/MatchAnalysis.scala @@ -222,7 +222,7 @@ trait MatchApproximation extends TreeAndTypeAnalysis with ScalaLogic with MatchT // so that we don't introduce new aliases for existing symbols, thus keeping the set of bound symbols minimal val (boundSubst, unboundSubst) = (subst.from zip subst.to) partition { case (f, t) => - t.isInstanceOf[Ident] && (t.symbol ne NoSymbol) && pointsToBound(f) + t.isInstanceOf[Ident] && t.symbol.exists && pointsToBound(f) } val (boundFrom, boundTo) = boundSubst.unzip val (unboundFrom, unboundTo) = unboundSubst.unzip @@ -624,9 +624,9 @@ trait MatchAnalysis extends MatchApproximation { private lazy val uniqueEqualTo = equalTo filterNot (subsumed => equalTo.exists(better => (better ne subsumed) && instanceOfTpImplies(better.tp, subsumed.tp))) private lazy val prunedEqualTo = uniqueEqualTo filterNot (subsumed => variable.staticTpCheckable <:< subsumed.tp) private lazy val ctor = (prunedEqualTo match { case List(TypeConst(tp)) => tp case _ => variable.staticTpCheckable }).typeSymbol.primaryConstructor - private lazy val ctorParams = if (ctor == NoSymbol || ctor.paramss.isEmpty) Nil else ctor.paramss.head - private lazy val cls = if (ctor == NoSymbol) NoSymbol else ctor.owner - private lazy val caseFieldAccs = if (cls == NoSymbol) Nil else cls.caseFieldAccessors + private lazy val ctorParams = if (ctor.paramss.isEmpty) Nil else ctor.paramss.head + private lazy val cls = ctor.safeOwner + private lazy val caseFieldAccs = cls.caseFieldAccessors def addField(symbol: Symbol, assign: VariableAssignment) { // SI-7669 Only register this field if if this class contains it. diff --git a/src/compiler/scala/tools/nsc/transform/patmat/MatchCodeGen.scala b/src/compiler/scala/tools/nsc/transform/patmat/MatchCodeGen.scala index 1e4c56529c..6f597bef39 100644 --- a/src/compiler/scala/tools/nsc/transform/patmat/MatchCodeGen.scala +++ b/src/compiler/scala/tools/nsc/transform/patmat/MatchCodeGen.scala @@ -173,13 +173,13 @@ trait MatchCodeGen extends Interface { // catchAll.isEmpty iff no synthetic default case needed (the (last) user-defined case is a default) // if the last user-defined case is a default, it will never jump to the next case; it will go immediately to matchEnd val catchAllDef = matchFailGen map { matchFailGen => - val scrutRef = if(scrutSym ne NoSymbol) REF(scrutSym) else EmptyTree // for alternatives + val scrutRef = scrutSym.fold(EmptyTree: Tree)(REF) // for alternatives LabelDef(_currCase, Nil, matchEnd APPLY (matchFailGen(scrutRef))) } toList // at most 1 element // scrutSym == NoSymbol when generating an alternatives matcher - val scrutDef = if(scrutSym ne NoSymbol) List(VAL(scrutSym) === scrut) else Nil // for alternatives + val scrutDef = scrutSym.fold(List[Tree]())(sym => (VAL(sym) === scrut) :: Nil) // for alternatives // the generated block is taken apart in TailCalls under the following assumptions // the assumption is once we encounter a case, the remainder of the block will consist of cases diff --git a/src/compiler/scala/tools/nsc/transform/patmat/MatchTranslation.scala b/src/compiler/scala/tools/nsc/transform/patmat/MatchTranslation.scala index fcee142932..9bc442467d 100644 --- a/src/compiler/scala/tools/nsc/transform/patmat/MatchTranslation.scala +++ b/src/compiler/scala/tools/nsc/transform/patmat/MatchTranslation.scala @@ -659,7 +659,7 @@ trait MatchTranslation { self: PatternMatching => object Bound { def unapply(t: Tree): Option[(Symbol, Tree)] = t match { - case t@Bind(n, p) if (t.symbol ne null) && (t.symbol ne NoSymbol) => // pos/t2429 does not satisfy these conditions + case t@Bind(n, p) if t.hasExistingSymbol => // pos/t2429 does not satisfy these conditions Some((t.symbol, p)) case _ => None } diff --git a/src/compiler/scala/tools/nsc/transform/patmat/MatchTreeMaking.scala b/src/compiler/scala/tools/nsc/transform/patmat/MatchTreeMaking.scala index baccdcf544..b0a7749908 100644 --- a/src/compiler/scala/tools/nsc/transform/patmat/MatchTreeMaking.scala +++ b/src/compiler/scala/tools/nsc/transform/patmat/MatchTreeMaking.scala @@ -587,9 +587,8 @@ trait MatchTreeMaking extends MatchCodeGen with Debugging { t.symbol.owner = currentOwner case d : DefTree if (d.symbol != NoSymbol) && ((d.symbol.owner == NoSymbol) || (d.symbol.owner == origOwner)) => // don't indiscriminately change existing owners! (see e.g., pos/t3440, pos/t3534, pos/unapplyContexts2) debug.patmat("def: "+ ((d, d.symbol.ownerChain, currentOwner.ownerChain))) - if(d.symbol.moduleClass ne NoSymbol) - d.symbol.moduleClass.owner = currentOwner + d.symbol.moduleClass andAlso (_.owner = currentOwner) d.symbol.owner = currentOwner // case _ if (t.symbol != NoSymbol) && (t.symbol ne null) => debug.patmat("untouched "+ ((t, t.getClass, t.symbol.ownerChain, currentOwner.ownerChain))) diff --git a/src/compiler/scala/tools/nsc/typechecker/Contexts.scala b/src/compiler/scala/tools/nsc/typechecker/Contexts.scala index f3a22a2cee..86a0d33737 100644 --- a/src/compiler/scala/tools/nsc/typechecker/Contexts.scala +++ b/src/compiler/scala/tools/nsc/typechecker/Contexts.scala @@ -269,7 +269,7 @@ trait Contexts { self: Analyzer => /** The next enclosing context (potentially `this`) that is owned by a class or method */ def enclClassOrMethod: Context = - if ((owner eq NoSymbol) || (owner.isClass) || (owner.isMethod)) this + if (!owner.exists || owner.isClass || owner.isMethod) this else outer.enclClassOrMethod /** The next enclosing context (potentially `this`) that has a `CaseDef` as a tree */ @@ -653,13 +653,8 @@ trait Contexts { self: Analyzer => lastAccessCheckDetails = "" // Console.println("isAccessible(%s, %s, %s)".format(sym, pre, superAccess)) - def accessWithinLinked(ab: Symbol) = { - val linked = ab.linkedClassOfClass - // don't have access if there is no linked class - // (before adding the `ne NoSymbol` check, this was a no-op when linked eq NoSymbol, - // since `accessWithin(NoSymbol) == true` whatever the symbol) - (linked ne NoSymbol) && accessWithin(linked) - } + // don't have access if there is no linked class (so exclude linkedClass=NoSymbol) + def accessWithinLinked(ab: Symbol) = ab.linkedClassOfClass.fold(false)(accessWithin) /* Are we inside definition of `ab`? */ def accessWithin(ab: Symbol) = { @@ -957,7 +952,7 @@ trait Contexts { self: Analyzer => // 2) sym.owner is inherited by the correct package object class // We try to establish 1) by inspecting the owners directly, and then we try // to rule out 2), and only if both those fail do we resort to looking in the info. - !sym.isPackage && (sym.owner ne NoSymbol) && ( + !sym.isPackage && sym.owner.exists && ( if (sym.owner.isPackageObjectClass) sym.owner.owner == pkgClass else diff --git a/src/compiler/scala/tools/nsc/typechecker/Duplicators.scala b/src/compiler/scala/tools/nsc/typechecker/Duplicators.scala index 0a2628b482..396f3407f3 100644 --- a/src/compiler/scala/tools/nsc/typechecker/Duplicators.scala +++ b/src/compiler/scala/tools/nsc/typechecker/Duplicators.scala @@ -74,22 +74,19 @@ abstract class Duplicators extends Analyzer { override def mapOver(tpe: Type): Type = tpe match { case TypeRef(NoPrefix, sym, args) if sym.isTypeParameterOrSkolem => - var sym1 = context.scope.lookup(sym.name) - if (sym1 eq NoSymbol) { - // try harder (look in outer scopes) - // with virtpatmat, this can happen when the sym is referenced in the scope of a LabelDef but is defined in the scope of an outer DefDef (e.g., in AbstractPartialFunction's andThen) - BodyDuplicator.super.silent(_.typedType(Ident(sym.name))) match { - case SilentResultValue(t) => - sym1 = t.symbol - debuglog("fixed by trying harder: "+((sym, sym1, context))) - case _ => - } - } -// assert(sym1 ne NoSymbol, tpe) - if ((sym1 ne NoSymbol) && (sym1 ne sym)) { - debuglog("fixing " + sym + " -> " + sym1) + val sym1 = ( + context.scope lookup sym.name orElse { + // try harder (look in outer scopes) + // with virtpatmat, this can happen when the sym is referenced in the scope of a LabelDef but + // is defined in the scope of an outer DefDef (e.g., in AbstractPartialFunction's andThen) + BodyDuplicator.super.silent(_ typedType Ident(sym.name)).fold(NoSymbol: Symbol)(_.symbol) + } filter (_ ne sym) + ) + if (sym1.exists) { + debuglog(s"fixing $sym -> $sym1") typeRef(NoPrefix, sym1, mapOverArgs(args, sym1.typeParams)) - } else super.mapOver(tpe) + } + else super.mapOver(tpe) case TypeRef(pre, sym, args) => val newsym = updateSym(sym) @@ -157,7 +154,7 @@ abstract class Duplicators extends Analyzer { case vdef @ ValDef(mods, name, _, rhs) if mods.hasFlag(Flags.LAZY) => debuglog("ValDef " + name + " sym.info: " + vdef.symbol.info) invalidSyms(vdef.symbol) = vdef - val newowner = if (owner != NoSymbol) owner else context.owner + val newowner = owner orElse context.owner val newsym = vdef.symbol.cloneSymbol(newowner) newsym.setInfo(fixType(vdef.symbol.info)) vdef.symbol = newsym @@ -362,12 +359,11 @@ abstract class Duplicators extends Analyzer { case _ => debuglog("Duplicators default case: " + tree.summaryString) debuglog(" ---> " + tree) - if (tree.hasSymbolField && tree.symbol != NoSymbol && (tree.symbol.owner == AnyClass)) { + if (tree.hasSymbolField && tree.symbol.safeOwner == AnyClass) tree.symbol = NoSymbol // maybe we can find a more specific member in a subclass of Any (see AnyVal members, like ==) - } + val ntree = castType(tree, pt) - val res = super.typed(ntree, mode, pt) - res + super.typed(ntree, mode, pt) } } diff --git a/src/compiler/scala/tools/nsc/typechecker/Namers.scala b/src/compiler/scala/tools/nsc/typechecker/Namers.scala index cac6bd2ef2..2bb2cc1ab4 100644 --- a/src/compiler/scala/tools/nsc/typechecker/Namers.scala +++ b/src/compiler/scala/tools/nsc/typechecker/Namers.scala @@ -390,9 +390,7 @@ trait Namers extends MethodSynthesis { * has been defined in a separate file. */ private def validateCompanionDefs(tree: ImplDef) { - val sym = tree.symbol - if (sym eq NoSymbol) return - + val sym = tree.symbol orElse { return } val ctx = if (context.owner.isPackageObjectClass) context.outer else context val module = if (sym.isModule) sym else ctx.scope lookupModule tree.name val clazz = if (sym.isClass) sym else ctx.scope lookupClass tree.name diff --git a/src/compiler/scala/tools/nsc/typechecker/RefChecks.scala b/src/compiler/scala/tools/nsc/typechecker/RefChecks.scala index 30b923e2a1..66dff792b6 100644 --- a/src/compiler/scala/tools/nsc/typechecker/RefChecks.scala +++ b/src/compiler/scala/tools/nsc/typechecker/RefChecks.scala @@ -216,7 +216,7 @@ abstract class RefChecks extends InfoTransform with scala.reflect.internal.trans val inherited = clazz.info.nonPrivateMemberAdmitting(member.name, VBRIDGE) // Delaying calling memberType as long as possible - if (inherited ne NoSymbol) { + if (inherited.exists) { val jtpe = toJavaRepeatedParam(self memberType member) // this is a bit tortuous: we look for non-private members or bridges // if we find a bridge everything is OK. If we find another member, @@ -1521,7 +1521,7 @@ abstract class RefChecks extends InfoTransform with scala.reflect.internal.trans checkCompileTimeOnly(sym, tree.pos) checkDelayedInitSelect(qual, sym, tree.pos) - if (sym eq NoSymbol) + if (!sym.exists) devWarning("Select node has NoSymbol! " + tree + " / " + tree.tpe) else if (sym.hasLocalFlag) varianceValidator.checkForEscape(sym, currentClass) diff --git a/src/compiler/scala/tools/nsc/typechecker/SuperAccessors.scala b/src/compiler/scala/tools/nsc/typechecker/SuperAccessors.scala index 6933b10a0a..12d6bb2e6a 100644 --- a/src/compiler/scala/tools/nsc/typechecker/SuperAccessors.scala +++ b/src/compiler/scala/tools/nsc/typechecker/SuperAccessors.scala @@ -269,8 +269,8 @@ abstract class SuperAccessors extends transform.Transform with transform.TypingT && sym.enclClass != currentClass && !sym.owner.isPackageClass // SI-7091 no accessor needed package owned (ie, top level) symbols && !sym.owner.isTrait - && (sym.owner.enclosingPackageClass != currentClass.enclosingPackageClass) - && (qual.symbol.info.member(sym.name) ne NoSymbol) + && sym.owner.enclosingPackageClass != currentClass.enclosingPackageClass + && qual.symbol.info.member(sym.name).exists && !needsProtectedAccessor(sym, tree.pos) ) if (shouldEnsureAccessor) { diff --git a/src/compiler/scala/tools/nsc/typechecker/TypeDiagnostics.scala b/src/compiler/scala/tools/nsc/typechecker/TypeDiagnostics.scala index b4a37f9943..0c5f798c23 100644 --- a/src/compiler/scala/tools/nsc/typechecker/TypeDiagnostics.scala +++ b/src/compiler/scala/tools/nsc/typechecker/TypeDiagnostics.scala @@ -143,7 +143,7 @@ trait TypeDiagnostics { def defaultMessage = moduleMessage + preResultString + tree.tpe def applyMessage = defaultMessage + tree.symbol.locationString - if ((sym eq null) || (sym eq NoSymbol)) { + if (!tree.hasExistingSymbol) { if (isTyperInPattern) patternMessage else exprMessage } diff --git a/src/compiler/scala/tools/nsc/typechecker/Typers.scala b/src/compiler/scala/tools/nsc/typechecker/Typers.scala index d2ff47626d..f0c0942e95 100644 --- a/src/compiler/scala/tools/nsc/typechecker/Typers.scala +++ b/src/compiler/scala/tools/nsc/typechecker/Typers.scala @@ -63,6 +63,10 @@ trait Typers extends Adaptations with Tags with TypersTracking { } sealed abstract class SilentResult[+T] { + @inline final def fold[U](none: => U)(f: T => U): U = this match { + case SilentResultValue(value) => f(value) + case _ => none + } @inline final def map[U](f: T => U): SilentResult[U] = this match { case SilentResultValue(value) => SilentResultValue(f(value)) case x: SilentTypeError => x diff --git a/src/reflect/scala/reflect/internal/Definitions.scala b/src/reflect/scala/reflect/internal/Definitions.scala index 6b7aa2dddf..6715a5d1a6 100644 --- a/src/reflect/scala/reflect/internal/Definitions.scala +++ b/src/reflect/scala/reflect/internal/Definitions.scala @@ -227,10 +227,7 @@ trait Definitions extends api.StandardDefinitions { scope } /** Is this symbol a member of Object or Any? */ - def isUniversalMember(sym: Symbol) = ( - (sym ne NoSymbol) - && (ObjectClass isSubClass sym.owner) - ) + def isUniversalMember(sym: Symbol) = ObjectClass isSubClass sym.owner /** Is this symbol unimportable? Unimportable symbols include: * - constructors, because is not a real name diff --git a/src/reflect/scala/reflect/internal/SymbolTable.scala b/src/reflect/scala/reflect/internal/SymbolTable.scala index c340670635..f0be0f7d05 100644 --- a/src/reflect/scala/reflect/internal/SymbolTable.scala +++ b/src/reflect/scala/reflect/internal/SymbolTable.scala @@ -60,6 +60,7 @@ abstract class SymbolTable extends macros.Universe def shouldLogAtThisPhase = false def isPastTyper = false + protected def isDeveloper: Boolean = settings.debug @deprecated("Give us a reason", "2.10.0") def abort(): Nothing = abort("unknown error") @@ -69,8 +70,12 @@ abstract class SymbolTable extends macros.Universe /** Override with final implementation for inlining. */ def debuglog(msg: => String): Unit = if (settings.debug) log(msg) - def devWarning(msg: => String): Unit = if (settings.debug) Console.err.println(msg) + def devWarning(msg: => String): Unit = if (isDeveloper) Console.err.println(msg) def throwableAsString(t: Throwable): String = "" + t + def throwableAsString(t: Throwable, maxFrames: Int): String = t.getStackTrace take maxFrames mkString "\n at " + + @inline final def devWarningDumpStack(msg: => String, maxFrames: Int): Unit = + devWarning(msg + "\n" + throwableAsString(new Throwable, maxFrames)) /** Prints a stack trace if -Ydebug or equivalent was given, otherwise does nothing. */ def debugStack(t: Throwable): Unit = devWarning(throwableAsString(t)) diff --git a/src/reflect/scala/reflect/internal/Symbols.scala b/src/reflect/scala/reflect/internal/Symbols.scala index e41038cafc..a8efa938c8 100644 --- a/src/reflect/scala/reflect/internal/Symbols.scala +++ b/src/reflect/scala/reflect/internal/Symbols.scala @@ -153,7 +153,10 @@ trait Symbols extends api.Symbols { self: SymbolTable => } def asNameType(n: Name): NameType - private[this] var _rawowner = initOwner // Syncnote: need not be protected, as only assignment happens in owner_=, which is not exposed to api + // Syncnote: need not be protected, as only assignment happens in owner_=, which is not exposed to api + // The null check is for NoSymbol, which can't pass a reference to itself to the constructor and also + // can't call owner_= due to an assertion it contains. + private[this] var _rawowner = if (initOwner eq null) this else initOwner private[this] var _rawflags: Long = _ def rawowner = _rawowner @@ -610,7 +613,7 @@ trait Symbols extends api.Symbols { self: SymbolTable => } final def isLazyAccessor = isLazy && lazyAccessor != NoSymbol - final def isOverridableMember = !(isClass || isEffectivelyFinal) && (this ne NoSymbol) && owner.isClass + final def isOverridableMember = !(isClass || isEffectivelyFinal) && safeOwner.isClass /** Does this symbol denote a wrapper created by the repl? */ final def isInterpreterWrapper = ( @@ -999,13 +1002,20 @@ trait Symbols extends api.Symbols { self: SymbolTable => // ------ owner attribute -------------------------------------------------------------- + /** In general when seeking the owner of a symbol, one should call `owner`. + * The other possibilities include: + * - call `safeOwner` if it is expected that the target may be NoSymbol + * - call `assertOwner` if it is an unrecoverable error if the target is NoSymbol + * + * `owner` behaves like `safeOwner`, but logs NoSymbol.owner calls under -Xdev. + * `assertOwner` aborts compilation immediately if called on NoSymbol. + */ def owner: Symbol = { if (Statistics.hotEnabled) Statistics.incCounter(ownerCount) rawowner } - - // Like owner, but NoSymbol.owner == NoSymbol instead of throwing an exception. - final def safeOwner: Symbol = if (this eq NoSymbol) NoSymbol else owner + final def safeOwner: Symbol = if (this eq NoSymbol) NoSymbol else owner + final def assertOwner: Symbol = if (this eq NoSymbol) abort("no-symbol does not have an owner") else owner // TODO - don't allow the owner to be changed without checking invariants, at least // when under some flag. Define per-phase invariants for owner/owned relationships, @@ -1781,10 +1791,6 @@ trait Symbols extends api.Symbols { self: SymbolTable => result } - @inline final def map(f: Symbol => Symbol): Symbol = if (this eq NoSymbol) this else f(this) - - final def toOption: Option[Symbol] = if (exists) Some(this) else None - // ------ cloneing ------------------------------------------------------------------- /** A clone of this symbol. */ @@ -2179,8 +2185,7 @@ trait Symbols extends api.Symbols { self: SymbolTable => * the recursive knot. */ private def canMatchInheritedSymbols = ( - (this ne NoSymbol) - && owner.isClass + owner.isClass && !this.isClass && !this.isConstructor ) @@ -2352,6 +2357,11 @@ trait Symbols extends api.Symbols { self: SymbolTable => @inline final def orElse(alt: => Symbol): Symbol = if (this ne NoSymbol) this else alt @inline final def andAlso(f: Symbol => Unit): Symbol = { if (this ne NoSymbol) f(this) ; this } + @inline final def fold[T](none: => T)(f: Symbol => T): T = if (this ne NoSymbol) f(this) else none + @inline final def map(f: Symbol => Symbol): Symbol = if (this eq NoSymbol) this else f(this) + + final def toOption: Option[Symbol] = if (exists) Some(this) else None + // ------ toString ------------------------------------------------------------------- @@ -3340,7 +3350,11 @@ trait Symbols extends api.Symbols { self: SymbolTable => override def enclosingPackageClass: Symbol = this override def enclMethod: Symbol = this override def associatedFile = NoAbstractFile - override def ownerChain: List[Symbol] = List() + override def owner: Symbol = { + devWarningDumpStack("NoSymbol.owner", 15) + this + } + override def ownerChain: List[Symbol] = Nil override def ownersIterator: Iterator[Symbol] = Iterator.empty override def alternatives: List[Symbol] = List() override def reset(completer: Type): this.type = this @@ -3350,9 +3364,6 @@ trait Symbols extends api.Symbols { self: SymbolTable => override def accessBoundary(base: Symbol): Symbol = enclosingRootClass def cloneSymbolImpl(owner: Symbol, newFlags: Long) = abort("NoSymbol.clone()") override def originalEnclosingMethod = this - - override def owner: Symbol = - abort("no-symbol does not have an owner") } protected def makeNoSymbol: NoSymbol = new NoSymbol diff --git a/src/reflect/scala/reflect/internal/Trees.scala b/src/reflect/scala/reflect/internal/Trees.scala index 02bee5e369..a5a78cb3b8 100644 --- a/src/reflect/scala/reflect/internal/Trees.scala +++ b/src/reflect/scala/reflect/internal/Trees.scala @@ -185,8 +185,8 @@ trait Trees extends api.Trees { self: SymbolTable => def replace(from: Tree, to: Tree): Tree = new TreeReplacer(from, to, positionAware = false) transform this - def hasSymbolWhich(f: Symbol => Boolean) = - (symbol ne null) && (symbol ne NoSymbol) && f(symbol) + def hasExistingSymbol = (symbol ne null) && (symbol ne NoSymbol) + def hasSymbolWhich(f: Symbol => Boolean) = hasExistingSymbol && f(symbol) def isErroneous = (tpe ne null) && tpe.isErroneous def isTyped = (tpe ne null) && !tpe.isErroneous diff --git a/src/reflect/scala/reflect/internal/Types.scala b/src/reflect/scala/reflect/internal/Types.scala index 71f46fedb7..cab2303dd0 100644 --- a/src/reflect/scala/reflect/internal/Types.scala +++ b/src/reflect/scala/reflect/internal/Types.scala @@ -3475,7 +3475,7 @@ trait Types def copyRefinedType(original: RefinedType, parents: List[Type], decls: Scope) = if ((parents eq original.parents) && (decls eq original.decls)) original else { - val owner = if (original.typeSymbol == NoSymbol) NoSymbol else original.typeSymbol.owner + val owner = original.typeSymbol.owner val result = refinedType(parents, owner) val syms1 = decls.toList for (sym <- syms1) diff --git a/src/reflect/scala/reflect/internal/tpe/TypeMaps.scala b/src/reflect/scala/reflect/internal/tpe/TypeMaps.scala index bebc419c7c..6662ec522a 100644 --- a/src/reflect/scala/reflect/internal/tpe/TypeMaps.scala +++ b/src/reflect/scala/reflect/internal/tpe/TypeMaps.scala @@ -524,7 +524,7 @@ private[internal] trait TypeMaps { private def correspondingTypeArgument(lhs: Type, rhs: Type): Type = { val TypeRef(_, lhsSym, lhsArgs) = lhs val TypeRef(_, rhsSym, rhsArgs) = rhs - require(lhsSym.safeOwner == rhsSym, s"$lhsSym is not a type parameter of $rhsSym") + require(lhsSym.owner == rhsSym, s"$lhsSym is not a type parameter of $rhsSym") // Find the type parameter position; we'll use the corresponding argument. // Why are we checking by name rather than by equality? Because for @@ -539,7 +539,7 @@ private[internal] trait TypeMaps { else { // It's easy to get here when working on hardcore type machinery (not to // mention when not doing so, see above) so let's provide a standout error. - def own_s(s: Symbol) = s.nameString + " in " + s.safeOwner.nameString + def own_s(s: Symbol) = s.nameString + " in " + s.owner.nameString def explain = sm"""| sought ${own_s(lhsSym)} | classSym ${own_s(rhsSym)} diff --git a/src/repl/scala/tools/nsc/interpreter/IMain.scala b/src/repl/scala/tools/nsc/interpreter/IMain.scala index ae318697ec..1723344306 100644 --- a/src/repl/scala/tools/nsc/interpreter/IMain.scala +++ b/src/repl/scala/tools/nsc/interpreter/IMain.scala @@ -297,19 +297,9 @@ class IMain(@BeanProperty val factory: ScriptEngineFactory, initialSettings: Set def flatPath(sym: Symbol): String = flatOp shift sym.javaClassName def translatePath(path: String) = { val sym = if (path endsWith "$") symbolOfTerm(path.init) else symbolOfIdent(path) - sym match { - case NoSymbol => None - case _ => Some(flatPath(sym)) - } - } - def translateEnclosingClass(n: String) = { - def enclosingClass(s: Symbol): Symbol = - if (s == NoSymbol || s.isClass) s else enclosingClass(s.owner) - enclosingClass(symbolOfTerm(n)) match { - case NoSymbol => None - case c => Some(flatPath(c)) - } + sym.toOption map flatPath } + def translateEnclosingClass(n: String) = symbolOfTerm(n).enclClass.toOption map flatPath private class TranslatingClassLoader(parent: ClassLoader) extends util.AbstractFileClassLoader(replOutput.dir, parent) { /** Overridden here to try translating a simple name to the generated diff --git a/src/repl/scala/tools/nsc/interpreter/MemberHandlers.scala b/src/repl/scala/tools/nsc/interpreter/MemberHandlers.scala index 085a7c6065..c1faf30385 100644 --- a/src/repl/scala/tools/nsc/interpreter/MemberHandlers.scala +++ b/src/repl/scala/tools/nsc/interpreter/MemberHandlers.scala @@ -71,7 +71,7 @@ trait MemberHandlers { override def definesImplicit = member.mods.isImplicit override def definesTerm: Option[TermName] = Some(name.toTermName) filter (_ => name.isTermName) override def definesType: Option[TypeName] = Some(name.toTypeName) filter (_ => name.isTypeName) - override def definedSymbols = if (symbol eq NoSymbol) Nil else List(symbol) + override def definedSymbols = if (symbol.exists) symbol :: Nil else Nil } /** Class to handle one member among all the members included -- cgit v1.2.3