From 9c8e247d8900f3fb6f497bc5e269b68f6bc967b7 Mon Sep 17 00:00:00 2001 From: Martin Odersky Date: Tue, 29 Sep 2015 17:29:53 +0200 Subject: Matching denotations should take infos into account Whenchecking whether two denotations match it is not enough to look at the signatures. The signatures might match (on the parameters) but the actual parametre types might be different. The change always tests infos after signatures, effectively turning the signature test into a pre-filter. --- src/dotty/tools/dotc/core/Denotations.scala | 77 +++++++++++++++-------------- 1 file changed, 41 insertions(+), 36 deletions(-) (limited to 'src/dotty/tools/dotc/core/Denotations.scala') diff --git a/src/dotty/tools/dotc/core/Denotations.scala b/src/dotty/tools/dotc/core/Denotations.scala index 16a151e89..cd46918cf 100644 --- a/src/dotty/tools/dotc/core/Denotations.scala +++ b/src/dotty/tools/dotc/core/Denotations.scala @@ -268,50 +268,52 @@ object Denotations { } case denot1: SingleDenotation => if (denot1 eq denot2) denot1 - else if (denot1.signature matches denot2.signature) { + else { val info1 = denot1.info val info2 = denot2.info - val sym1 = denot1.symbol - val sym2 = denot2.symbol - val sym2Accessible = sym2.isAccessibleFrom(pre) - - /** Does `sym1` come before `sym2` in the linearization of `pre`? */ - def precedes(sym1: Symbol, sym2: Symbol) = { - def precedesIn(bcs: List[ClassSymbol]): Boolean = bcs match { - case bc :: bcs1 => (sym1 eq bc) || !(sym2 eq bc) && precedesIn(bcs1) - case Nil => true + if (denot1.signature.matches(denot2.signature) && + denot1.info.matches(denot2.info)) { + val sym1 = denot1.symbol + val sym2 = denot2.symbol + val sym2Accessible = sym2.isAccessibleFrom(pre) + + /** Does `sym1` come before `sym2` in the linearization of `pre`? */ + def precedes(sym1: Symbol, sym2: Symbol) = { + def precedesIn(bcs: List[ClassSymbol]): Boolean = bcs match { + case bc :: bcs1 => (sym1 eq bc) || !(sym2 eq bc) && precedesIn(bcs1) + case Nil => true + } + sym1.derivesFrom(sym2) || + !sym2.derivesFrom(sym1) && precedesIn(pre.baseClasses) } - sym1.derivesFrom(sym2) || - !sym2.derivesFrom(sym1) && precedesIn(pre.baseClasses) - } - /** Preference according to partial pre-order (isConcrete, precedes) */ - def preferSym(sym1: Symbol, sym2: Symbol) = - sym1.eq(sym2) || - sym1.isAsConcrete(sym2) && - (!sym2.isAsConcrete(sym1) || precedes(sym1.owner, sym2.owner)) + /** Preference according to partial pre-order (isConcrete, precedes) */ + def preferSym(sym1: Symbol, sym2: Symbol) = + sym1.eq(sym2) || + sym1.isAsConcrete(sym2) && + (!sym2.isAsConcrete(sym1) || precedes(sym1.owner, sym2.owner)) - /** Sym preference provided types also override */ - def prefer(sym1: Symbol, sym2: Symbol, info1: Type, info2: Type) = - preferSym(sym1, sym2) && info1.overrides(info2) + /** Sym preference provided types also override */ + def prefer(sym1: Symbol, sym2: Symbol, info1: Type, info2: Type) = + preferSym(sym1, sym2) && info1.overrides(info2) - if (sym2Accessible && prefer(sym2, sym1, info2, info1)) denot2 - else { - val sym1Accessible = sym1.isAccessibleFrom(pre) - if (sym1Accessible && prefer(sym1, sym2, info1, info2)) denot1 - else if (sym1Accessible && sym2.exists && !sym2Accessible) denot1 - else if (sym2Accessible && sym1.exists && !sym1Accessible) denot2 + if (sym2Accessible && prefer(sym2, sym1, info2, info1)) denot2 else { - val sym = - if (!sym1.exists) sym2 - else if (!sym2.exists) sym1 - else if (preferSym(sym2, sym1)) sym2 - else sym1 - new JointRefDenotation(sym, info1 & info2, denot1.validFor & denot2.validFor) + val sym1Accessible = sym1.isAccessibleFrom(pre) + if (sym1Accessible && prefer(sym1, sym2, info1, info2)) denot1 + else if (sym1Accessible && sym2.exists && !sym2Accessible) denot1 + else if (sym2Accessible && sym1.exists && !sym1Accessible) denot2 + else { + val sym = + if (!sym1.exists) sym2 + else if (!sym2.exists) sym1 + else if (preferSym(sym2, sym1)) sym2 + else sym1 + new JointRefDenotation(sym, info1 & info2, denot1.validFor & denot2.validFor) + } } - } + } else NoDenotation } - else NoDenotation } if (this eq that) this @@ -333,7 +335,7 @@ object Denotations { def | (that: Denotation, pre: Type)(implicit ctx: Context): Denotation = { def unionDenot(denot1: SingleDenotation, denot2: SingleDenotation): Denotation = - if (denot1.signature matches denot2.signature) { + if (denot1.matches(denot2)) { val sym1 = denot1.symbol val sym2 = denot2.symbol val info1 = denot1.info @@ -472,6 +474,9 @@ object Denotations { if (sig matches situated.signature) this else NoDenotation } + def matches(other: SingleDenotation)(implicit ctx: Context): Boolean = + signature.matches(other.signature) && info.matches(other.info) + // ------ Forming types ------------------------------------------- /** The TypeRef representing this type denotation at its original location. */ -- cgit v1.2.3