Skip to content

Commit 3b9fed5

Browse files
committed
ResolveSuper: add missing methods overrides for disambiguation
In mixin-overrides.scala, when we compute the overrides for QInt in ResolveSuper, we need to add an override for Baz#op because it overrides the concrete method Bar#op (otherwise we'll get a "Conflicting default methods" error at runtime). Before this commit, this did not happen because Baz#op was not considered to match Bar#op, because one refers to Baz.this.A and the other to Bar.thiz.A. We fix this by calling `matchingDenotation` with a `targetType` corresponding to the current class (`QInt` here) instead of each base class where the denotation is defined.
1 parent caac6b9 commit 3b9fed5

File tree

3 files changed

+24
-5
lines changed

3 files changed

+24
-5
lines changed

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

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1125,10 +1125,10 @@ object SymDenotations {
11251125
final def memberCanMatchInheritedSymbols(implicit ctx: Context): Boolean =
11261126
!isConstructor && !is(Private)
11271127

1128-
/** The symbol, in class `inClass`, that is overridden by this denotation. */
1129-
final def overriddenSymbol(inClass: ClassSymbol)(implicit ctx: Context): Symbol =
1128+
/** The symbol, in class `inClass`, that is overridden by this denotation in class `siteClass`.*/
1129+
final def overriddenSymbol(inClass: ClassSymbol, siteClass: ClassSymbol = owner.asClass)(implicit ctx: Context): Symbol =
11301130
if (!canMatchInheritedSymbols && (owner ne inClass)) NoSymbol
1131-
else matchingDecl(inClass, owner.thisType)
1131+
else matchingDecl(inClass, siteClass.thisType)
11321132

11331133
/** All symbols overridden by this denotation. */
11341134
final def allOverriddenSymbols(implicit ctx: Context): Iterator[Symbol] =
@@ -1142,7 +1142,7 @@ object SymDenotations {
11421142

11431143
private def overriddenFromType(tp: Type)(implicit ctx: Context): Iterator[Symbol] =
11441144
tp.baseClasses match {
1145-
case _ :: inherited => inherited.iterator map overriddenSymbol filter (_.exists)
1145+
case _ :: inherited => inherited.iterator.map(overriddenSymbol(_)).filter(_.exists)
11461146
case Nil => Iterator.empty
11471147
}
11481148

compiler/src/dotty/tools/dotc/transform/MixinOps.scala

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -104,7 +104,7 @@ class MixinOps(cls: ClassSymbol, thisPhase: DenotTransformer)(implicit ctx: Cont
104104
private def competingMethodsIterator(meth: Symbol): Iterator[Symbol] = {
105105
cls.baseClasses.iterator
106106
.filter(_ ne meth.owner)
107-
.map(meth.overriddenSymbol)
107+
.map(base => meth.overriddenSymbol(base, cls))
108108
.filter(_.exists)
109109
}
110110
}

tests/run/mixin-overrides.scala

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
trait Foo[A] {
2+
def op(x: A): Int
3+
}
4+
trait Bar[A] extends Foo[A] {
5+
override def op(x: A): Int = 1
6+
}
7+
trait Baz[A] extends Foo[A] {
8+
override def op(x: A): Int = 2
9+
}
10+
trait Qux[A] extends Bar[A] with Baz[A]
11+
12+
class QInt extends Qux[Int]
13+
14+
object Test {
15+
def main(args: Array[String]): Unit = {
16+
val qint = new QInt
17+
assert(qint.op(1) == 2) // Used to fail with java.lang.IncompatibleClassChangeError: Conflicting default methods: Bar.op Baz.op
18+
}
19+
}

0 commit comments

Comments
 (0)