Skip to content

Commit 8a52da5

Browse files
committed
Exclude mixin forwarders from double definition checks
With the new applied type scheme, we can generate mixin forwarders for the same method at different base types which end up with different types if the base types have different type arguments. This can lead to spurious "double definition with same erased type" failures, if these instantiations do not have matching types.
1 parent 490b937 commit 8a52da5

File tree

1 file changed

+9
-8
lines changed

1 file changed

+9
-8
lines changed

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

Lines changed: 9 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -86,20 +86,21 @@ class ElimErasedValueType extends MiniPhaseTransform with InfoTransformer {
8686
val site = root.thisType
8787
val info1 = site.memberInfo(sym1)
8888
val info2 = site.memberInfo(sym2)
89-
if (!info1.matchesLoosely(info2) &&
90-
info1.signature != info2.signature)
91-
// there is a problem here that sometimes we generate too many forwarders. For instance,
92-
// in compileStdLib, compiling scala.immutable.SetProxy, line 29:
89+
def isDefined(sym: Symbol) = sym.initialDenot.validFor.firstPhaseId <= ctx.phaseId
90+
if (isDefined(sym1) && isDefined(sym2) && !info1.matchesLoosely(info2))
91+
// The reason for the `isDefined` condition is that we need to exclude mixin forwarders
92+
// from the tests. For instance, in compileStdLib, compiling scala.immutable.SetProxy, line 29:
9393
// new AbstractSet[B] with SetProxy[B] { val self = newSelf }
94-
// double definition:
94+
// This generates two forwarders, one in AbstractSet, the other in the anonymous class itself.
95+
// Their signatures are:
9596
// method map: [B, That]
9697
// (f: B => B)(implicit bf: scala.collection.generic.CanBuildFrom[scala.collection.immutable.Set[B], B, That]): That override <method> <touched> in anonymous class scala.collection.AbstractSet[B] with scala.collection.immutable.SetProxy[B]{...} and
9798
// method map: [B, That](f: B => B)(implicit bf: scala.collection.generic.CanBuildFrom[scala.collection.Set[B], B, That]): That override <method> <touched> in class AbstractSet
98-
// have same type after erasure: (f: Function1, bf: scala.collection.generic.CanBuildFrom): Object
99+
// These have same type after erasure:
100+
// (f: Function1, bf: scala.collection.generic.CanBuildFrom): Object
99101
//
100102
// The problem is that `map` was forwarded twice, with different instantiated types.
101-
// It's unclear how to fix this at present (maybe move mixin forwarding after erasure?)
102-
// The added 2nd condition is a rather crude patch.
103+
// Maybe we should move mixin forwarding after erasure to avoid redundant forwarders like these.
103104
ctx.error(
104105
em"""double definition:
105106
|$sym1: $info1 ${sym1.flags} in ${sym1.owner} and

0 commit comments

Comments
 (0)