aboutsummaryrefslogtreecommitdiff
path: root/src/dotty/tools/dotc/core/Denotations.scala
diff options
context:
space:
mode:
authorMartin Odersky <odersky@gmail.com>2015-06-07 18:26:43 +0200
committerMartin Odersky <odersky@gmail.com>2015-06-07 18:26:53 +0200
commit5733fdbd3ed3e8036992ee690bbd8270a36471a2 (patch)
treef5e86a799c19feed6a7d7c4efd7e9b23ee5ebaae /src/dotty/tools/dotc/core/Denotations.scala
parentcb2d81df7ef98e79874bf74227045a64ce86e75f (diff)
downloaddotty-5733fdbd3ed3e8036992ee690bbd8270a36471a2.tar.gz
dotty-5733fdbd3ed3e8036992ee690bbd8270a36471a2.tar.bz2
dotty-5733fdbd3ed3e8036992ee690bbd8270a36471a2.zip
Fix mergeDenot one more time.
It's easy to get this wrong. What happened was that when computing deferred members of a class a deferred member was preferred over a concrete one because the types did not match. Thsi should not happen. We now change the scheme to always prefer concrete over abstract, and subclass-owned over superclass-owned. But we pick a denotation only if the overrides relationship on types coincides with the preference on symbols.
Diffstat (limited to 'src/dotty/tools/dotc/core/Denotations.scala')
-rw-r--r--src/dotty/tools/dotc/core/Denotations.scala27
1 files changed, 10 insertions, 17 deletions
diff --git a/src/dotty/tools/dotc/core/Denotations.scala b/src/dotty/tools/dotc/core/Denotations.scala
index 4d475fe2b..9cbac9115 100644
--- a/src/dotty/tools/dotc/core/Denotations.scala
+++ b/src/dotty/tools/dotc/core/Denotations.scala
@@ -274,24 +274,17 @@ object Denotations {
val sym1 = denot1.symbol
val sym2 = denot2.symbol
val sym2Accessible = sym2.isAccessibleFrom(pre)
- def shadows(sym1: Symbol, sym2: Symbol) = {
- val owner1 = sym1.owner
- val owner2 = sym2.owner
- owner1.derivesFrom(owner2) && owner1.ne(owner2)
+ def unshadowed(sym: Symbol, from: Symbol) = {
+ val symOwner = sym.owner
+ val fromOwner = from.owner
+ !fromOwner.derivesFrom(symOwner) || fromOwner.eq(symOwner)
}
- /** Preference according to order (overrides, isAsConcrete, shadows)*/
+ /** Preference according to partial pre-order (isConcrete, unshadowed) */
+ def preferSym(sym1: Symbol, sym2: Symbol) =
+ sym1.isAsConcrete(sym2) && (!sym2.isAsConcrete(sym1) || unshadowed(sym1, sym2))
+ /** Sym preference provided types also override */
def prefer(info1: Type, sym1: Symbol, info2: Type, sym2: Symbol) =
- info1.overrides(info2) && (
- // non-standard ordering of tests for efficiency -
- // overrides is costlier to compute than the others, so its 2nd test comes last.
- sym1.isAsConcrete(sym2) && (
- !sym2.isAsConcrete(sym1)
- ||
- shadows(sym1, sym2)
- )
- ||
- !info2.overrides(info1)
- )
+ preferSym(sym1, sym2) && info1.overrides(info2)
if (sym2Accessible && prefer(info2, sym2, info1, sym1)) denot2
else {
val sym1Accessible = sym1.isAccessibleFrom(pre)
@@ -302,7 +295,7 @@ object Denotations {
val sym =
if (!sym1.exists) sym2
else if (!sym2.exists) sym1
- else if (sym2 isAsConcrete sym1) sym2
+ else if (preferSym(sym2, sym1)) sym2
else sym1
new JointRefDenotation(sym, info1 & info2, denot1.validFor & denot2.validFor)
}