diff options
author | Paul Phillips <paulp@improving.org> | 2012-09-26 12:14:13 -0700 |
---|---|---|
committer | Paul Phillips <paulp@improving.org> | 2012-09-26 12:24:45 -0700 |
commit | e6f10b07d44f0ddde26246b4a41527a84eede81c (patch) | |
tree | 2268de6b9dccf22e3355b0ee1bcf63d7e7f10738 /src | |
parent | 83b5d4c0c9af462fc562c571f17dfcd00f47255d (diff) | |
download | scala-e6f10b07d44f0ddde26246b4a41527a84eede81c.tar.gz scala-e6f10b07d44f0ddde26246b4a41527a84eede81c.tar.bz2 scala-e6f10b07d44f0ddde26246b4a41527a84eede81c.zip |
Fixed SI-5604, selections on package objects.
mkAttributedSelect, which creates a Select tree based on
a symbol, has been a major source of package object bugs,
because it has not been accurately identifying selections
on package objects. When selecting foo.bar, if foo turns
out to be a package object, the created Select tree must be
foo.`package`.bar
However mkAttributedSelect was only examining the owner of
the symbol, which means it would work if the package object
defined bar directly, but not if it inherited it.
Diffstat (limited to 'src')
-rw-r--r-- | src/reflect/scala/reflect/internal/TreeGen.scala | 25 |
1 files changed, 22 insertions, 3 deletions
diff --git a/src/reflect/scala/reflect/internal/TreeGen.scala b/src/reflect/scala/reflect/internal/TreeGen.scala index ebf0998573..c1753fc5a1 100644 --- a/src/reflect/scala/reflect/internal/TreeGen.scala +++ b/src/reflect/scala/reflect/internal/TreeGen.scala @@ -172,10 +172,29 @@ abstract class TreeGen extends macros.TreeBuilder { if (qual.symbol != null && (qual.symbol.isEffectiveRoot || qual.symbol.isEmptyPackage)) mkAttributedIdent(sym) else { + // Have to recognize anytime a selection is made on a package + // so it can be rewritten to foo.bar.`package`.name rather than + // foo.bar.name if name is in the package object. + // TODO - factor out the common logic between this and + // the Typers method "isInPackageObject", used in typedIdent. + val qualsym = ( + if (qual.tpe ne null) qual.tpe.typeSymbol + else if (qual.symbol ne null) qual.symbol + else NoSymbol + ) + val needsPackageQualifier = ( + (sym ne null) + && qualsym.isPackage + && !sym.isDefinedInPackage + ) val pkgQualifier = - if (sym != null && sym.owner.isPackageObjectClass && sym.effectiveOwner == qual.tpe.typeSymbol) { - val obj = sym.owner.sourceModule - Select(qual, nme.PACKAGE) setSymbol obj setType singleType(qual.tpe, obj) + if (needsPackageQualifier) { + // The owner of a symbol which requires package qualification may be the + // package object iself, but it also could be any superclass of the package + // object. In the latter case, we must go through the qualifier's info + // to obtain the right symbol. + val packageObject = if (sym.owner.isModuleClass) sym.owner.sourceModule else qual.tpe member nme.PACKAGE + Select(qual, nme.PACKAGE) setSymbol packageObject setType singleType(qual.tpe, packageObject) } else qual |