summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPaul Phillips <paulp@improving.org>2012-01-13 14:16:18 -0800
committerPaul Phillips <paulp@improving.org>2012-01-13 15:44:58 -0800
commitd7981e784e11e8a5a9a761f28d90725d721c9475 (patch)
tree28f506c89eebfe3bb9d3e96227e9d7c047cd09f0
parent66a3623d59a261830076c7ad2b04fbb82e415547 (diff)
downloadscala-d7981e784e11e8a5a9a761f28d90725d721c9475.tar.gz
scala-d7981e784e11e8a5a9a761f28d90725d721c9475.tar.bz2
scala-d7981e784e11e8a5a9a761f28d90725d721c9475.zip
Fix for spurious implicit ambiguity with package objects.
Closes SI-3999. Review by @odersky.
-rw-r--r--src/compiler/scala/reflect/internal/Symbols.scala18
-rw-r--r--test/files/pos/t3999/a_1.scala9
-rw-r--r--test/files/pos/t3999/b_2.scala7
3 files changed, 29 insertions, 5 deletions
diff --git a/src/compiler/scala/reflect/internal/Symbols.scala b/src/compiler/scala/reflect/internal/Symbols.scala
index d969cb43bb..e34189657e 100644
--- a/src/compiler/scala/reflect/internal/Symbols.scala
+++ b/src/compiler/scala/reflect/internal/Symbols.scala
@@ -454,9 +454,9 @@ trait Symbols extends api.Symbols { self: SymbolTable =>
final def isAnonOrRefinementClass = isAnonymousClass || isRefinementClass
// A package object or its module class
- final def isPackageObjectOrClass = name == nme.PACKAGE || name == tpnme.PACKAGE
- final def isPackageObject = name == nme.PACKAGE && owner.isPackageClass
- final def isPackageObjectClass = name == tpnme.PACKAGE && owner.isPackageClass
+ final def isPackageObjectOrClass = (this ne NoSymbol) && owner.isPackageClass && (name == nme.PACKAGE || name == tpnme.PACKAGE)
+ final def isPackageObject = (this ne NoSymbol) && owner.isPackageClass && name == nme.PACKAGE
+ final def isPackageObjectClass = (this ne NoSymbol) && owner.isPackageClass && name == tpnme.PACKAGE
final def isDefinedInPackage = effectiveOwner.isPackageClass
final def isJavaInterface = isJavaDefined && isTrait
@@ -467,7 +467,7 @@ trait Symbols extends api.Symbols { self: SymbolTable =>
/** The owner, skipping package objects.
*/
- def effectiveOwner = owner.skipPackageObject
+ def effectiveOwner = if (owner.isPackageObjectClass) owner.skipPackageObject else owner
/** If this is a package object or its implementing class, its owner: otherwise this.
*/
@@ -2432,7 +2432,15 @@ trait Symbols extends api.Symbols { self: SymbolTable =>
if ((implicitMembersCacheKey1 ne tp) || (implicitMembersCacheKey2 ne tp.decls.elems)) {
implicitMembersCacheKey1 = tp
implicitMembersCacheKey2 = tp.decls.elems
- implicitMembersCacheValue = tp.implicitMembers
+ // When a package object which defines an implicit, it may turn up here in two
+ // forms which are not recognized as the same implicit definition, creating a
+ // spurious ambiguity (see pos/t3999). Since I haven't figured out package objects
+ // well enough to fix this at the root, I am filtering here by applying the
+ // property that a member's owner must be unique.
+ if (isPackageClass)
+ implicitMembersCacheValue = tp.implicitMembers filter (_.owner eq this)
+ else
+ implicitMembersCacheValue = tp.implicitMembers
}
implicitMembersCacheValue
}
diff --git a/test/files/pos/t3999/a_1.scala b/test/files/pos/t3999/a_1.scala
new file mode 100644
index 0000000000..25366ee9c4
--- /dev/null
+++ b/test/files/pos/t3999/a_1.scala
@@ -0,0 +1,9 @@
+package foo
+
+class Outside
+
+package object bar {
+ class Val(b: Boolean)
+ implicit def boolean2Val(b: Boolean) = new Val(b)
+ implicit def boolean2Outside(b: Boolean) = new Outside
+} \ No newline at end of file
diff --git a/test/files/pos/t3999/b_2.scala b/test/files/pos/t3999/b_2.scala
new file mode 100644
index 0000000000..1af82c8c5b
--- /dev/null
+++ b/test/files/pos/t3999/b_2.scala
@@ -0,0 +1,7 @@
+package foo
+package bar
+
+class A {
+ val s: Val = false
+ val o: Outside = false
+} \ No newline at end of file