summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPaul Phillips <paulp@improving.org>2012-09-26 12:19:50 -0700
committerPaul Phillips <paulp@improving.org>2012-09-26 12:24:45 -0700
commit97ede5a64a60c739f03619f9c0d7e2bf88a97207 (patch)
tree8ef2d71c934e4c6a43c12cf23e7cca704c6cde16
parente6f10b07d44f0ddde26246b4a41527a84eede81c (diff)
downloadscala-97ede5a64a60c739f03619f9c0d7e2bf88a97207.tar.gz
scala-97ede5a64a60c739f03619f9c0d7e2bf88a97207.tar.bz2
scala-97ede5a64a60c739f03619f9c0d7e2bf88a97207.zip
Simplifications in typedIdent.
These accompany the changes to mkAttributedSelect in the prior commit, and document additional brokenness with package objects which stillr emains.
-rw-r--r--src/compiler/scala/tools/nsc/typechecker/Typers.scala93
1 files changed, 51 insertions, 42 deletions
diff --git a/src/compiler/scala/tools/nsc/typechecker/Typers.scala b/src/compiler/scala/tools/nsc/typechecker/Typers.scala
index 2344e71883..6e222459c9 100644
--- a/src/compiler/scala/tools/nsc/typechecker/Typers.scala
+++ b/src/compiler/scala/tools/nsc/typechecker/Typers.scala
@@ -605,23 +605,31 @@ trait Typers extends Modes with Adaptations with Tags {
}
/** Is `sym` defined in package object of package `pkg`?
+ * Since sym may be defined in some parent of the package object,
+ * we cannot inspect its owner only; we have to go through the
+ * info of the package object. However to avoid cycles we'll check
+ * what other ways we can before pushing that way.
*/
private def isInPackageObject(sym: Symbol, pkg: Symbol) = {
- def isInPkgObj(sym: Symbol) =
- !sym.owner.isPackage && {
- sym.owner.isPackageObjectClass &&
- sym.owner.owner == pkg ||
- pkg.isInitialized && {
- // need to be careful here to not get a cyclic reference during bootstrap
- val pkgobj = pkg.info.member(nme.PACKAGEkw)
- pkgobj.isInitialized &&
- (pkgobj.info.member(sym.name).alternatives contains sym)
- }
+ val pkgClass = if (pkg.isTerm) pkg.moduleClass else pkg
+ def matchesInfo = (
+ pkg.isInitialized && {
+ // need to be careful here to not get a cyclic reference during bootstrap
+ val module = pkg.info member nme.PACKAGEkw
+ module.isInitialized && (module.info.member(sym.name).alternatives contains sym)
}
- pkg.isPackageClass && {
+ )
+ def isInPkgObj(sym: Symbol) = (
+ !sym.isPackage
+ && !sym.owner.isPackageClass
+ && (sym.owner ne NoSymbol)
+ && (sym.owner.owner == pkgClass || matchesInfo)
+ )
+
+ pkgClass.isPackageClass && (
if (sym.isOverloaded) sym.alternatives forall isInPkgObj
else isInPkgObj(sym)
- }
+ )
}
/** Post-process an identifier or selection node, performing the following:
@@ -4768,6 +4776,22 @@ trait Typers extends Modes with Adaptations with Tags {
defSym = rootMirror.EmptyPackageClass.tpe.nonPrivateMember(name)
defSym != NoSymbol
}
+ def correctForPackageObject(sym: Symbol): Symbol = {
+ if (sym.isTerm && isInPackageObject(sym, pre.typeSymbol)) {
+ val sym1 = pre member sym.name
+ if ((sym1 eq NoSymbol) || (sym eq sym1)) sym else {
+ qual = gen.mkAttributedQualifier(pre)
+ log(s"""
+ | !!! Overloaded package object member resolved incorrectly.
+ | prefix: $pre
+ | Discarded: ${sym.defString}
+ | Using: ${sym1.defString}
+ """.stripMargin)
+ sym1
+ }
+ }
+ else sym
+ }
def startingIdentContext = (
// ignore current variable scope in patterns to enforce linearity
if ((mode & (PATTERNmode | TYPEPATmode)) == 0) context
@@ -4779,11 +4803,11 @@ trait Typers extends Modes with Adaptations with Tags {
// which are methods (note: if we don't do that
// case x :: xs in class List would return the :: method)
// unless they are stable or are accessors (the latter exception is for better error messages).
- def qualifies(sym: Symbol): Boolean = {
- sym.hasRawInfo && // this condition avoids crashing on self-referential pattern variables
- reallyExists(sym) &&
- ((mode & PATTERNmode | FUNmode) != (PATTERNmode | FUNmode) || !sym.isSourceMethod || sym.hasFlag(ACCESSOR))
- }
+ def qualifies(sym: Symbol): Boolean = (
+ sym.hasRawInfo // this condition avoids crashing on self-referential pattern variables
+ && reallyExists(sym)
+ && ((mode & PATTERNmode | FUNmode) != (PATTERNmode | FUNmode) || !sym.isSourceMethod || sym.hasFlag(ACCESSOR))
+ )
if (defSym == NoSymbol) {
var defEntry: ScopeEntry = null // the scope entry of defSym, if defined in a local scope
@@ -4791,32 +4815,17 @@ trait Typers extends Modes with Adaptations with Tags {
var cx = startingIdentContext
while (defSym == NoSymbol && cx != NoContext && (cx.scope ne null)) { // cx.scope eq null arises during FixInvalidSyms in Duplicators
pre = cx.enclClass.prefix
+ // !!! FIXME. This call to lookupEntry is at the root of all the
+ // bad behavior with overloading in package objects. lookupEntry
+ // just takes the first symbol it finds in scope, ignoring the rest.
+ // When a selection on a package object arrives here, the first
+ // overload is always chosen. "correctForPackageObject" exists to
+ // undo that decision. Obviously it would be better not to do it in
+ // the first place; however other things seem to be tied to obtaining
+ // that ScopeEntry, specifically calculating the nesting depth.
defEntry = cx.scope.lookupEntry(name)
- if ((defEntry ne null) && qualifies(defEntry.sym)) {
- // Right here is where SI-1987, overloading in package objects, can be
- // seen to go wrong. There is an overloaded symbol, but when referring
- // to the unqualified identifier from elsewhere in the package, only
- // the last definition is visible. So overloading mis-resolves and is
- // definition-order dependent, bad things. See run/t1987.scala.
- //
- // I assume the actual problem involves how/where these symbols are entered
- // into the scope. But since I didn't figure out how to fix it that way, I
- // catch it here by looking up package-object-defined symbols in the prefix.
- if (isInPackageObject(defEntry.sym, pre.typeSymbol)) {
- defSym = pre.member(defEntry.sym.name)
- if (defSym ne defEntry.sym) {
- qual = gen.mkAttributedQualifier(pre)
- log(s"""
- | !!! Overloaded package object member resolved incorrectly.
- | prefix: $pre
- | Discarded: ${defEntry.sym.defString}
- | Using: ${defSym.defString}
- """.stripMargin)
- }
- }
- else
- defSym = defEntry.sym
- }
+ if ((defEntry ne null) && qualifies(defEntry.sym))
+ defSym = correctForPackageObject(defEntry.sym)
else {
cx = cx.enclClass
val foundSym = pre.member(name) filter qualifies