Skip to content

Commit 9aa800f

Browse files
committed
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.
1 parent fe5f4f3 commit 9aa800f

File tree

3 files changed

+29
-25
lines changed

3 files changed

+29
-25
lines changed

src/dotty/tools/dotc/core/Denotations.scala

Lines changed: 26 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -122,11 +122,11 @@ object Denotations {
122122
/** The signature of the denotation. */
123123
def signature(implicit ctx: Context): Signature
124124

125-
/** Resolve overloaded denotation to pick the one with the given signature
125+
/** Resolve overloaded denotation to pick the ones with the given signature
126126
* when seen from prefix `site`.
127127
* @param relaxed When true, consider only parameter signatures for a match.
128128
*/
129-
def atSignature(sig: Signature, site: Type = NoPrefix, relaxed: Boolean = false)(implicit ctx: Context): SingleDenotation
129+
def atSignature(sig: Signature, site: Type = NoPrefix, relaxed: Boolean = false)(implicit ctx: Context): Denotation
130130

131131
/** The variant of this denotation that's current in the given context, or
132132
* `NotDefinedHereDenotation` if this denotation does not exist at current phase, but
@@ -157,7 +157,10 @@ object Denotations {
157157
* or NoDenotation if no satisfying alternative exists.
158158
* @throws TypeError if there is at more than one alternative that satisfies `p`.
159159
*/
160-
def suchThat(p: Symbol => Boolean): SingleDenotation
160+
def suchThat(p: Symbol => Boolean)(implicit ctx: Context): SingleDenotation
161+
162+
/** If this is a SingleDenotation, return it, otherwise throw a TypeError */
163+
def checkUnique(implicit ctx: Context): SingleDenotation = suchThat(alwaysTrue)
161164

162165
/** Does this denotation have an alternative that satisfies the predicate `p`? */
163166
def hasAltWith(p: SingleDenotation => Boolean): Boolean
@@ -227,13 +230,17 @@ object Denotations {
227230
/** The alternative of this denotation that has a type matching `targetType` when seen
228231
* as a member of type `site`, `NoDenotation` if none exists.
229232
*/
230-
def matchingDenotation(site: Type, targetType: Type)(implicit ctx: Context): SingleDenotation =
231-
if (isOverloaded)
232-
atSignature(targetType.signature, site, relaxed = true).matchingDenotation(site, targetType)
233-
else if (exists && !site.memberInfo(symbol).matchesLoosely(targetType))
234-
NoDenotation
235-
else
236-
asSingleDenotation
233+
def matchingDenotation(site: Type, targetType: Type)(implicit ctx: Context): SingleDenotation = {
234+
def qualifies(sym: Symbol) = site.memberInfo(sym).matchesLoosely(targetType)
235+
if (isOverloaded) {
236+
atSignature(targetType.signature, site, relaxed = true) match {
237+
case sd: SingleDenotation => sd.matchingDenotation(site, targetType)
238+
case md => md.suchThat(qualifies(_))
239+
}
240+
}
241+
else if (exists && !qualifies(symbol)) NoDenotation
242+
else asSingleDenotation
243+
}
237244

238245
/** Form a denotation by conjoining with denotation `that`.
239246
*
@@ -420,23 +427,21 @@ object Denotations {
420427
final def validFor = denot1.validFor & denot2.validFor
421428
final def isType = false
422429
final def signature(implicit ctx: Context) = Signature.OverloadedSignature
423-
def atSignature(sig: Signature, site: Type, relaxed: Boolean)(implicit ctx: Context): SingleDenotation = {
424-
val atSig1 = denot1.atSignature(sig, site, relaxed)
425-
val atSig2 = denot2.atSignature(sig, site, relaxed)
426-
if (isDoubleDef(atSig1.symbol, atSig2.symbol)) doubleDefError(atSig1, atSig2, site)
427-
atSig1.orElse(atSig2)
428-
}
430+
def atSignature(sig: Signature, site: Type, relaxed: Boolean)(implicit ctx: Context): Denotation =
431+
derivedMultiDenotation(denot1.atSignature(sig, site, relaxed), denot2.atSignature(sig, site, relaxed))
429432
def currentIfExists(implicit ctx: Context): Denotation =
430433
derivedMultiDenotation(denot1.currentIfExists, denot2.currentIfExists)
431434
def current(implicit ctx: Context): Denotation =
432435
derivedMultiDenotation(denot1.current, denot2.current)
433436
def altsWith(p: Symbol => Boolean): List[SingleDenotation] =
434437
denot1.altsWith(p) ++ denot2.altsWith(p)
435-
def suchThat(p: Symbol => Boolean): SingleDenotation = {
438+
def suchThat(p: Symbol => Boolean)(implicit ctx: Context): SingleDenotation = {
436439
val sd1 = denot1.suchThat(p)
437440
val sd2 = denot2.suchThat(p)
438441
if (sd1.exists)
439-
if (sd2.exists) throw new TypeError(s"failure to disambiguate overloaded reference $this")
442+
if (sd2.exists)
443+
if (isDoubleDef(denot1.symbol, denot2.symbol)) doubleDefError(denot1, denot2)
444+
else throw new TypeError(s"failure to disambiguate overloaded reference $this")
440445
else sd1
441446
else sd2
442447
}
@@ -486,7 +491,7 @@ object Denotations {
486491
def altsWith(p: Symbol => Boolean): List[SingleDenotation] =
487492
if (exists && p(symbol)) this :: Nil else Nil
488493

489-
def suchThat(p: Symbol => Boolean): SingleDenotation =
494+
def suchThat(p: Symbol => Boolean)(implicit ctx: Context): SingleDenotation =
490495
if (exists && p(symbol)) this else NoDenotation
491496

492497
def hasAltWith(p: SingleDenotation => Boolean): Boolean =
@@ -906,14 +911,14 @@ object Denotations {
906911
*/
907912
case class NoQualifyingRef(alts: List[SingleDenotation])(implicit ctx: Context) extends ErrorDenotation
908913

909-
/** A double defifinition
914+
/** A double definition
910915
*/
911916
def isDoubleDef(sym1: Symbol, sym2: Symbol)(implicit ctx: Context): Boolean =
912917
(sym1.exists && sym2.exists &&
913918
(sym1 ne sym2) && (sym1.owner eq sym2.owner) &&
914919
!sym1.is(Bridge) && !sym2.is(Bridge))
915920

916-
def doubleDefError(denot1: SingleDenotation, denot2: SingleDenotation, pre: Type)(implicit ctx: Context): Unit = {
921+
def doubleDefError(denot1: Denotation, denot2: Denotation, pre: Type = NoPrefix)(implicit ctx: Context): Nothing = {
917922
val sym1 = denot1.symbol
918923
val sym2 = denot2.symbol
919924
def fromWhere = if (pre == NoPrefix) "" else i"\nwhen seen as members of $pre"
@@ -927,7 +932,6 @@ object Denotations {
927932
denot2.info, denot2.info)
928933
}
929934

930-
931935
// --------------- PreDenotations -------------------------------------------------
932936

933937
/** A PreDenotation represents a group of single denotations

src/dotty/tools/dotc/core/Types.scala

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1437,7 +1437,7 @@ object Types {
14371437
asMemberOf(prefix) match {
14381438
case NoDenotation => d.current
14391439
case newd: SingleDenotation => newd
1440-
case newd => newd.atSignature(d.signature).orElse(d.current)
1440+
case newd => newd.atSignature(d.signature).checkUnique.orElse(d.current)
14411441
}
14421442

14431443
private def denotOfSym(sym: Symbol)(implicit ctx: Context): Denotation = {
@@ -1729,7 +1729,7 @@ object Types {
17291729
override def loadDenot(implicit ctx: Context): Denotation = {
17301730
val d = super.loadDenot
17311731
if (sig eq Signature.OverloadedSignature) d
1732-
else d.atSignature(sig)
1732+
else d.atSignature(sig).checkUnique
17331733
}
17341734

17351735
override def newLikeThis(prefix: Type)(implicit ctx: Context): TermRef = {

src/dotty/tools/dotc/transform/Splitter.scala

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -46,7 +46,7 @@ class Splitter extends MiniPhaseTransform { thisTransform =>
4646
val mbr = tp.member(name)
4747
if (!mbr.isOverloaded) mbr.asSingleDenotation
4848
else tree.tpe match {
49-
case tref: TermRefWithSignature => mbr.atSignature(tref.sig)
49+
case tref: TermRefWithSignature => mbr.atSignature(tref.sig).checkUnique
5050
case _ =>
5151
def alts = mbr.alternatives.map(alt => i"$alt: ${alt.info}").mkString(", ")
5252
ctx.error(s"cannot disambiguate overloaded members $alts", tree.pos)

0 commit comments

Comments
 (0)