Skip to content

Commit e6f10b0

Browse files
committed
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.
1 parent 83b5d4c commit e6f10b0

File tree

8 files changed

+111
-3
lines changed

8 files changed

+111
-3
lines changed

src/reflect/scala/reflect/internal/TreeGen.scala

Lines changed: 22 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -172,10 +172,29 @@ abstract class TreeGen extends macros.TreeBuilder {
172172
if (qual.symbol != null && (qual.symbol.isEffectiveRoot || qual.symbol.isEmptyPackage))
173173
mkAttributedIdent(sym)
174174
else {
175+
// Have to recognize anytime a selection is made on a package
176+
// so it can be rewritten to foo.bar.`package`.name rather than
177+
// foo.bar.name if name is in the package object.
178+
// TODO - factor out the common logic between this and
179+
// the Typers method "isInPackageObject", used in typedIdent.
180+
val qualsym = (
181+
if (qual.tpe ne null) qual.tpe.typeSymbol
182+
else if (qual.symbol ne null) qual.symbol
183+
else NoSymbol
184+
)
185+
val needsPackageQualifier = (
186+
(sym ne null)
187+
&& qualsym.isPackage
188+
&& !sym.isDefinedInPackage
189+
)
175190
val pkgQualifier =
176-
if (sym != null && sym.owner.isPackageObjectClass && sym.effectiveOwner == qual.tpe.typeSymbol) {
177-
val obj = sym.owner.sourceModule
178-
Select(qual, nme.PACKAGE) setSymbol obj setType singleType(qual.tpe, obj)
191+
if (needsPackageQualifier) {
192+
// The owner of a symbol which requires package qualification may be the
193+
// package object iself, but it also could be any superclass of the package
194+
// object. In the latter case, we must go through the qualifier's info
195+
// to obtain the right symbol.
196+
val packageObject = if (sym.owner.isModuleClass) sym.owner.sourceModule else qual.tpe member nme.PACKAGE
197+
Select(qual, nme.PACKAGE) setSymbol packageObject setType singleType(qual.tpe, packageObject)
179198
}
180199
else qual
181200

test/files/pos/t5604b/T_1.scala

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
// sandbox/t5604/T.scala
2+
package t6504
3+
4+
trait T {
5+
def foo: Boolean = false
6+
}

test/files/pos/t5604b/T_2.scala

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
// sandbox/t5604/T.scala
2+
package t6504
3+
4+
trait T {
5+
def foo: Boolean = false
6+
}

test/files/pos/t5604b/Test_1.scala

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
// sandbox/t5604/Test.scala
2+
package t6504
3+
4+
object Test {
5+
def blerg1(a: Any): Any = if (foo) blerg1(0)
6+
def blerg2(a: Any): Any = if (t6504.foo) blerg2(0)
7+
}

test/files/pos/t5604b/Test_2.scala

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
// sandbox/t5604/Test.scala
2+
package t6504
3+
4+
object Test {
5+
def blerg1(a: Any): Any = if (foo) blerg1(0)
6+
def blerg2(a: Any): Any = if (t6504.foo) blerg2(0)
7+
}

test/files/pos/t5604b/pack_1.scala

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
// sandbox/t5604/pack.scala
2+
package t6504
3+
4+
object `package` extends T {
5+
}

test/files/run/t5604.check

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
long
2+
double
3+
long
4+
double
5+
long
6+
double
7+
long
8+
double

test/files/run/t5604.scala

Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,50 @@
1+
// a.scala
2+
// Fri Jan 13 11:31:47 PST 2012
3+
4+
package foo {
5+
object regular extends Duh {
6+
def buh(n: Long) = println("long")
7+
def buh(n: Double) = println("double")
8+
}
9+
class regular {
10+
import regular._
11+
12+
duh(33L)
13+
duh(3.0d)
14+
foo.regular.duh(33L)
15+
foo.regular.duh(3.0d)
16+
buh(66L)
17+
buh(6.0d)
18+
foo.regular.buh(66L)
19+
foo.regular.buh(6.0d)
20+
}
21+
22+
trait Duh {
23+
def duh(n: Long) = println("long")
24+
def duh(n: Double) = println("double")
25+
}
26+
package object bar extends Duh {
27+
def buh(n: Long) = println("long")
28+
def buh(n: Double) = println("double")
29+
}
30+
package bar {
31+
object Main {
32+
def main(args:Array[String]) {
33+
duh(33L)
34+
duh(3.0d)
35+
foo.bar.duh(33L)
36+
foo.bar.duh(3.0d)
37+
buh(66L)
38+
buh(6.0d)
39+
foo.bar.buh(66L)
40+
foo.bar.buh(6.0d)
41+
}
42+
}
43+
}
44+
}
45+
46+
object Test {
47+
def main(args: Array[String]): Unit = {
48+
foo.bar.Main.main(null)
49+
}
50+
}

0 commit comments

Comments
 (0)