From 8231a48780fd692c120b038bb67330b9623bebc5 Mon Sep 17 00:00:00 2001 From: odersky Date: Sun, 25 Jun 2023 16:37:26 +0200 Subject: [PATCH 1/2] Avoid crash in erasure when reference cannot be emitted Fixes #17391 --- compiler/src/dotty/tools/dotc/transform/Erasure.scala | 2 +- tests/neg/i17391/Bar.java | 7 +++++++ tests/neg/i17391/test.scala | 11 +++++++++++ 3 files changed, 19 insertions(+), 1 deletion(-) create mode 100644 tests/neg/i17391/Bar.java create mode 100644 tests/neg/i17391/test.scala diff --git a/compiler/src/dotty/tools/dotc/transform/Erasure.scala b/compiler/src/dotty/tools/dotc/transform/Erasure.scala index f068a48cdba4..e20a16c9e60e 100644 --- a/compiler/src/dotty/tools/dotc/transform/Erasure.scala +++ b/compiler/src/dotty/tools/dotc/transform/Erasure.scala @@ -869,7 +869,7 @@ object Erasure { app(fun1) case t => - if ownArgs.isEmpty then fun1 + if ownArgs.isEmpty || t.isError then fun1 else throw new MatchError(i"tree $tree has unexpected type of function $fun/$fun1: $t, was $origFunType, args = $ownArgs") end typedApply diff --git a/tests/neg/i17391/Bar.java b/tests/neg/i17391/Bar.java new file mode 100644 index 000000000000..6d432926bde2 --- /dev/null +++ b/tests/neg/i17391/Bar.java @@ -0,0 +1,7 @@ +package mypkg; + +class Base { + public void retainAll(String x) {} +} + +public class Bar extends Base {} diff --git a/tests/neg/i17391/test.scala b/tests/neg/i17391/test.scala new file mode 100644 index 000000000000..dbcc0ec39de8 --- /dev/null +++ b/tests/neg/i17391/test.scala @@ -0,0 +1,11 @@ +def test(): Unit = +{ + val x: Foo[mypkg.Bar[String]] = ??? + val y: mypkg.Bar[String] = ??? + + y.retainAll("fd") // works + x.f.retainAll("fd"); // error + +} + +class Foo[T](val f: T) From 996bb15289e61ba8d8305039052b0b6237c5e642 Mon Sep 17 00:00:00 2001 From: odersky Date: Mon, 26 Jun 2023 22:17:38 +0200 Subject: [PATCH 2/2] Compute the original qualifier type before erasure The original qualifier type was computed in the wrong context. For the logic to make sense, it needs to compute the type before erasure and then erase that type. That fixes #17391 by now compiling it correctly, the same way Scala 2 does. --- compiler/src/dotty/tools/dotc/transform/Erasure.scala | 4 +++- tests/{neg => pos}/i17391/Bar.java | 0 tests/{neg => pos}/i17391/test.scala | 0 3 files changed, 3 insertions(+), 1 deletion(-) rename tests/{neg => pos}/i17391/Bar.java (100%) rename tests/{neg => pos}/i17391/test.scala (100%) diff --git a/compiler/src/dotty/tools/dotc/transform/Erasure.scala b/compiler/src/dotty/tools/dotc/transform/Erasure.scala index e20a16c9e60e..8e355175c176 100644 --- a/compiler/src/dotty/tools/dotc/transform/Erasure.scala +++ b/compiler/src/dotty/tools/dotc/transform/Erasure.scala @@ -764,7 +764,9 @@ object Erasure { val symIsPrimitive = sym.owner.isPrimitiveValueClass def originalQual: Type = - erasure(tree.qualifier.typeOpt.widen.finalResultType) + erasure( + inContext(preErasureCtx): + tree.qualifier.typeOpt.widen.finalResultType) if (qualIsPrimitive && !symIsPrimitive || qual.tpe.widenDealias.isErasedValueType) recur(box(qual)) diff --git a/tests/neg/i17391/Bar.java b/tests/pos/i17391/Bar.java similarity index 100% rename from tests/neg/i17391/Bar.java rename to tests/pos/i17391/Bar.java diff --git a/tests/neg/i17391/test.scala b/tests/pos/i17391/test.scala similarity index 100% rename from tests/neg/i17391/test.scala rename to tests/pos/i17391/test.scala