From bd10895b444e7b8d5906f241aa7799ca7cd6d9a1 Mon Sep 17 00:00:00 2001 From: Martin Odersky Date: Mon, 16 Jan 2017 19:35:08 +1100 Subject: [PATCH 1/3] Fix #1905: Duplicate bridge The problem with #1905 was that we checked "new" overriding relationships are phase erasure + 1. This is wrong when we have ErasedValueTypes because these do not compare correctly ith their underlying type. So we get spurious mismatches which force in turn spurious bridge generation. The fix is to compute newly overridden symbols at phase elimErasedValueTypes + 1, i.e. one phase later. --- compiler/src/dotty/tools/dotc/transform/Erasure.scala | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/compiler/src/dotty/tools/dotc/transform/Erasure.scala b/compiler/src/dotty/tools/dotc/transform/Erasure.scala index 71ecb5c65cc7..6af956a6d029 100644 --- a/compiler/src/dotty/tools/dotc/transform/Erasure.scala +++ b/compiler/src/dotty/tools/dotc/transform/Erasure.scala @@ -600,6 +600,7 @@ object Erasure extends TypeTestsCasts{ // this implementation doesn't check for bridge clashes with value types! def addBridges(oldStats: List[untpd.Tree], newStats: List[tpd.Tree])(implicit ctx: Context): List[tpd.Tree] = { val beforeCtx = ctx.withPhase(ctx.erasurePhase) + val afterCtx = ctx.withPhase(ctx.elimErasedValueTypePhase.next) def traverse(after: List[Tree], before: List[untpd.Tree], emittedBridges: ListBuffer[tpd.DefDef] = ListBuffer[tpd.DefDef]()): List[tpd.DefDef] = { after match { @@ -613,7 +614,7 @@ object Erasure extends TypeTestsCasts{ val newSymbol = member.symbol(ctx) assert(oldSymbol.name(beforeCtx) == newSymbol.name, s"${oldSymbol.name(beforeCtx)} bridging with ${newSymbol.name}") - val newOverridden = oldSymbol.denot.allOverriddenSymbols.toSet // TODO: clarify new <-> old in a comment; symbols are swapped here + val newOverridden = oldSymbol.denot.allOverriddenSymbols(afterCtx).toSet // TODO: clarify new <-> old in a comment; symbols are swapped here val oldOverridden = newSymbol.allOverriddenSymbols(beforeCtx).toSet // TODO: can we find a more efficient impl? newOverridden does not have to be a set! def stillInBaseClass(sym: Symbol) = ctx.owner derivesFrom sym.owner val neededBridges = (oldOverridden -- newOverridden).filter(stillInBaseClass) From c6d1cce7b9fac75225d3f811b582d9afa9d6b9f9 Mon Sep 17 00:00:00 2001 From: Martin Odersky Date: Mon, 16 Jan 2017 19:40:37 +1100 Subject: [PATCH 2/3] Add test case --- tests/run/iarray.scala | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) create mode 100644 tests/run/iarray.scala diff --git a/tests/run/iarray.scala b/tests/run/iarray.scala new file mode 100644 index 000000000000..e0e648273164 --- /dev/null +++ b/tests/run/iarray.scala @@ -0,0 +1,17 @@ +import scala.reflect.ClassTag + +class Arr[T](private val underlying: scala.Array[T]) extends AnyVal + +trait SeqMonoTransforms[+A, +Repr] extends Any { + protected[this] def fromIterableWithSameElemType(): Repr +} + +class ArrOps[A](val xs: Arr[A]) extends AnyRef with SeqMonoTransforms[A, Arr[A]] { + def fromIterableWithSameElemType(): Arr[A] = xs +} + +object Test { + def main(args: Array[String]) = + println(new ArrOps(new Arr(Array(1, 2, 3))).fromIterableWithSameElemType) +} + From d1f1726955cbd353531b90216b43df9cca22d20c Mon Sep 17 00:00:00 2001 From: Martin Odersky Date: Mon, 16 Jan 2017 19:42:58 +1100 Subject: [PATCH 3/3] Fix test case --- tests/run/iarray.scala | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/tests/run/iarray.scala b/tests/run/iarray.scala index e0e648273164..d91bc71365ff 100644 --- a/tests/run/iarray.scala +++ b/tests/run/iarray.scala @@ -1,6 +1,8 @@ import scala.reflect.ClassTag -class Arr[T](private val underlying: scala.Array[T]) extends AnyVal +class Arr[T](private val underlying: scala.Array[T]) extends AnyVal { + def toList = underlying.toList +} trait SeqMonoTransforms[+A, +Repr] extends Any { protected[this] def fromIterableWithSameElemType(): Repr @@ -12,6 +14,7 @@ class ArrOps[A](val xs: Arr[A]) extends AnyRef with SeqMonoTransforms[A, Arr[A]] object Test { def main(args: Array[String]) = - println(new ArrOps(new Arr(Array(1, 2, 3))).fromIterableWithSameElemType) + assert(new ArrOps(new Arr(Array(1, 2, 3))).fromIterableWithSameElemType.toList == + List(1, 2, 3)) }