Skip to content

Commit 4e695fb

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 making `preferSym` consistent with `infoMeet`. 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 4e695fb

File tree

3 files changed

+32
-1
lines changed

3 files changed

+32
-1
lines changed

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

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -490,7 +490,9 @@ object Denotations {
490490
* 4. The access boundary of sym2 is properly contained in the access
491491
* boundary of sym1. For protected access, we count the enclosing
492492
* package as access boundary.
493-
* 5. sym1 a method but sym2 is not.
493+
* 5. sym1 is a method but sym2 is not.
494+
* 6. sym1 is a non-polymorphic method but sym2 is a polymorphic method.
495+
* (to be consistent with infoMeet, see #4819)
494496
* The aim of these criteria is to give some disambiguation on access which
495497
* - does not depend on textual order or other arbitrary choices
496498
* - minimizes raising of doubleDef errors
@@ -505,6 +507,7 @@ object Denotations {
505507
accessBoundary(sym2).isProperlyContainedIn(accessBoundary(sym1)) ||
506508
sym2.is(Bridge) && !sym1.is(Bridge) ||
507509
sym1.is(Method) && !sym2.is(Method)) ||
510+
sym1.info.isInstanceOf[MethodType] && sym2.info.isInstanceOf[PolyType] ||
508511
sym1.info.isErroneous)
509512

510513
/** Sym preference provided types also override */

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)