Skip to content

Commit 30718d8

Browse files
committed
Workaround #4819: Avoid creating incorrect JointRefDenotations
When merging a denotation with a PolyType and a denotation with a MethodType, `infoMeet` will return the MethodType info, but the symbol that is then used to create the `JointRefDenotation` can come from either denotation, if it comes from the PolyType one, the resulting denotation is inconsistent, this resulted in RefChecks errors. We fix this by simply returning either of the denotation when `infoMeet` returning either of their info. This is only a workaround and not a proper fix for #4819 as it doesn't allow tests/neg/i4819.scala to compile, see the comments in the file.
1 parent 89ab499 commit 30718d8

File tree

3 files changed

+36
-4
lines changed

3 files changed

+36
-4
lines changed

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

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -525,9 +525,6 @@ object Denotations {
525525
else if (sym2Accessible && sym1.exists && !sym1Accessible) denot2
526526
else if (isDoubleDef(sym1, sym2)) handleDoubleDef
527527
else {
528-
val sym =
529-
if (preferSym(sym2, sym1)) sym2
530-
else sym1
531528
val jointInfo =
532529
try infoMeet(info1, info2)
533530
catch {
@@ -542,7 +539,14 @@ object Denotations {
542539
// compare with way merge is performed in SymDenotation#computeMembersNamed
543540
else throw new MergeError(ex.sym1, ex.sym2, ex.tp1, ex.tp2, pre)
544541
}
545-
new JointRefDenotation(sym, jointInfo, denot1.validFor & denot2.validFor)
542+
if (jointInfo eq info1) denot1
543+
else if (jointInfo eq info2) denot2
544+
else {
545+
val sym =
546+
if (preferSym(sym2, sym1)) sym2
547+
else sym1
548+
new JointRefDenotation(sym, jointInfo, denot1.validFor & denot2.validFor)
549+
}
546550
}
547551
}
548552
}

tests/neg/i4819.scala

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
trait One[X] {
2+
def concat(suffix: Int): X = ???
3+
}
4+
5+
trait Two[Y <: Foo] {
6+
def concat[Dummy](suffix: Int): Y = ???
7+
}
8+
9+
class Foo extends One[Foo] with Two[Foo] {
10+
concat(0) // OK
11+
12+
// TODO: This does not typecheck because the polymorphic overload is masked
13+
// (we merge the denotations for both overloads into one and always prefer
14+
// MethodType to PolyType, instead we should return a MultiDenotation). See #4819.
15+
concat[Int](0) // error (that should actually not be an error)
16+
}

tests/pos/i4819.scala

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
trait One[X] {
2+
def concat(suffix: Int): X = ???
3+
}
4+
5+
trait Two[Y <: Foo] {
6+
def concat[Dummy](suffix: Int): Y = ???
7+
}
8+
9+
class Foo extends One[Foo] with Two[Foo] {
10+
concat(0) // OK
11+
// See also tests/neg/i4819.scala
12+
}

0 commit comments

Comments
 (0)