diff options
author | Paul Phillips <paulp@improving.org> | 2013-08-19 15:12:04 -0700 |
---|---|---|
committer | Paul Phillips <paulp@improving.org> | 2013-08-19 15:12:04 -0700 |
commit | fde88c76ceb1e575b89c813a039df1967c6f995c (patch) | |
tree | a9210a6aa2165f69800a7471acc027dd42f01962 /src/compiler/scala/tools/nsc/typechecker/Contexts.scala | |
parent | a124ab7f48dfc1e49b203af7a14904eaa5029577 (diff) | |
download | scala-fde88c76ceb1e575b89c813a039df1967c6f995c.tar.gz scala-fde88c76ceb1e575b89c813a039df1967c6f995c.tar.bz2 scala-fde88c76ceb1e575b89c813a039df1967c6f995c.zip |
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.
Diffstat (limited to 'src/compiler/scala/tools/nsc/typechecker/Contexts.scala')
-rw-r--r-- | src/compiler/scala/tools/nsc/typechecker/Contexts.scala | 13 |
1 files changed, 4 insertions, 9 deletions
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 |