aboutsummaryrefslogtreecommitdiff
path: root/src/dotty/tools/dotc/core/Denotations.scala
diff options
context:
space:
mode:
authorMartin Odersky <odersky@gmail.com>2016-05-02 19:57:57 +0200
committerMartin Odersky <odersky@gmail.com>2016-05-18 19:43:22 +0200
commit9aa800f8a9905de059b6e34554cb166a9776dff3 (patch)
tree824650b825bd28b747c107d2746df45c8c0090eb /src/dotty/tools/dotc/core/Denotations.scala
parentfe5f4f3963d2d6b2f6514a362fb312bc2e7d7f94 (diff)
downloaddotty-9aa800f8a9905de059b6e34554cb166a9776dff3.tar.gz
dotty-9aa800f8a9905de059b6e34554cb166a9776dff3.tar.bz2
dotty-9aa800f8a9905de059b6e34554cb166a9776dff3.zip
Refined handling of atSignature
We cannot throw a merge error if atSignature does not give a unique single denotation. Counter example is compiling dotty itself, where we get a false negative during bridge generation. Instead, atSigature needs to return a normal denotation, and we need to check separately where required that a denotation is in fact a SingleDenotation.
Diffstat (limited to 'src/dotty/tools/dotc/core/Denotations.scala')
-rw-r--r--src/dotty/tools/dotc/core/Denotations.scala48
1 files changed, 26 insertions, 22 deletions
diff --git a/src/dotty/tools/dotc/core/Denotations.scala b/src/dotty/tools/dotc/core/Denotations.scala
index 0bcb3198b..080e8a39b 100644
--- a/src/dotty/tools/dotc/core/Denotations.scala
+++ b/src/dotty/tools/dotc/core/Denotations.scala
@@ -122,11 +122,11 @@ object Denotations {
/** The signature of the denotation. */
def signature(implicit ctx: Context): Signature
- /** Resolve overloaded denotation to pick the one with the given signature
+ /** Resolve overloaded denotation to pick the ones with the given signature
* when seen from prefix `site`.
* @param relaxed When true, consider only parameter signatures for a match.
*/
- def atSignature(sig: Signature, site: Type = NoPrefix, relaxed: Boolean = false)(implicit ctx: Context): SingleDenotation
+ def atSignature(sig: Signature, site: Type = NoPrefix, relaxed: Boolean = false)(implicit ctx: Context): Denotation
/** The variant of this denotation that's current in the given context, or
* `NotDefinedHereDenotation` if this denotation does not exist at current phase, but
@@ -157,7 +157,10 @@ object Denotations {
* or NoDenotation if no satisfying alternative exists.
* @throws TypeError if there is at more than one alternative that satisfies `p`.
*/
- def suchThat(p: Symbol => Boolean): SingleDenotation
+ def suchThat(p: Symbol => Boolean)(implicit ctx: Context): SingleDenotation
+
+ /** If this is a SingleDenotation, return it, otherwise throw a TypeError */
+ def checkUnique(implicit ctx: Context): SingleDenotation = suchThat(alwaysTrue)
/** Does this denotation have an alternative that satisfies the predicate `p`? */
def hasAltWith(p: SingleDenotation => Boolean): Boolean
@@ -227,13 +230,17 @@ object Denotations {
/** The alternative of this denotation that has a type matching `targetType` when seen
* as a member of type `site`, `NoDenotation` if none exists.
*/
- def matchingDenotation(site: Type, targetType: Type)(implicit ctx: Context): SingleDenotation =
- if (isOverloaded)
- atSignature(targetType.signature, site, relaxed = true).matchingDenotation(site, targetType)
- else if (exists && !site.memberInfo(symbol).matchesLoosely(targetType))
- NoDenotation
- else
- asSingleDenotation
+ def matchingDenotation(site: Type, targetType: Type)(implicit ctx: Context): SingleDenotation = {
+ def qualifies(sym: Symbol) = site.memberInfo(sym).matchesLoosely(targetType)
+ if (isOverloaded) {
+ atSignature(targetType.signature, site, relaxed = true) match {
+ case sd: SingleDenotation => sd.matchingDenotation(site, targetType)
+ case md => md.suchThat(qualifies(_))
+ }
+ }
+ else if (exists && !qualifies(symbol)) NoDenotation
+ else asSingleDenotation
+ }
/** Form a denotation by conjoining with denotation `that`.
*
@@ -420,23 +427,21 @@ object Denotations {
final def validFor = denot1.validFor & denot2.validFor
final def isType = false
final def signature(implicit ctx: Context) = Signature.OverloadedSignature
- def atSignature(sig: Signature, site: Type, relaxed: Boolean)(implicit ctx: Context): SingleDenotation = {
- val atSig1 = denot1.atSignature(sig, site, relaxed)
- val atSig2 = denot2.atSignature(sig, site, relaxed)
- if (isDoubleDef(atSig1.symbol, atSig2.symbol)) doubleDefError(atSig1, atSig2, site)
- atSig1.orElse(atSig2)
- }
+ def atSignature(sig: Signature, site: Type, relaxed: Boolean)(implicit ctx: Context): Denotation =
+ derivedMultiDenotation(denot1.atSignature(sig, site, relaxed), denot2.atSignature(sig, site, relaxed))
def currentIfExists(implicit ctx: Context): Denotation =
derivedMultiDenotation(denot1.currentIfExists, denot2.currentIfExists)
def current(implicit ctx: Context): Denotation =
derivedMultiDenotation(denot1.current, denot2.current)
def altsWith(p: Symbol => Boolean): List[SingleDenotation] =
denot1.altsWith(p) ++ denot2.altsWith(p)
- def suchThat(p: Symbol => Boolean): SingleDenotation = {
+ def suchThat(p: Symbol => Boolean)(implicit ctx: Context): SingleDenotation = {
val sd1 = denot1.suchThat(p)
val sd2 = denot2.suchThat(p)
if (sd1.exists)
- if (sd2.exists) throw new TypeError(s"failure to disambiguate overloaded reference $this")
+ if (sd2.exists)
+ if (isDoubleDef(denot1.symbol, denot2.symbol)) doubleDefError(denot1, denot2)
+ else throw new TypeError(s"failure to disambiguate overloaded reference $this")
else sd1
else sd2
}
@@ -486,7 +491,7 @@ object Denotations {
def altsWith(p: Symbol => Boolean): List[SingleDenotation] =
if (exists && p(symbol)) this :: Nil else Nil
- def suchThat(p: Symbol => Boolean): SingleDenotation =
+ def suchThat(p: Symbol => Boolean)(implicit ctx: Context): SingleDenotation =
if (exists && p(symbol)) this else NoDenotation
def hasAltWith(p: SingleDenotation => Boolean): Boolean =
@@ -906,14 +911,14 @@ object Denotations {
*/
case class NoQualifyingRef(alts: List[SingleDenotation])(implicit ctx: Context) extends ErrorDenotation
- /** A double defifinition
+ /** A double definition
*/
def isDoubleDef(sym1: Symbol, sym2: Symbol)(implicit ctx: Context): Boolean =
(sym1.exists && sym2.exists &&
(sym1 ne sym2) && (sym1.owner eq sym2.owner) &&
!sym1.is(Bridge) && !sym2.is(Bridge))
- def doubleDefError(denot1: SingleDenotation, denot2: SingleDenotation, pre: Type)(implicit ctx: Context): Unit = {
+ def doubleDefError(denot1: Denotation, denot2: Denotation, pre: Type = NoPrefix)(implicit ctx: Context): Nothing = {
val sym1 = denot1.symbol
val sym2 = denot2.symbol
def fromWhere = if (pre == NoPrefix) "" else i"\nwhen seen as members of $pre"
@@ -927,7 +932,6 @@ object Denotations {
denot2.info, denot2.info)
}
-
// --------------- PreDenotations -------------------------------------------------
/** A PreDenotation represents a group of single denotations