diff --git a/compiler/src/dotty/tools/dotc/core/TypeErasure.scala b/compiler/src/dotty/tools/dotc/core/TypeErasure.scala index d9a8ffae0673..c29b971f1a5a 100644 --- a/compiler/src/dotty/tools/dotc/core/TypeErasure.scala +++ b/compiler/src/dotty/tools/dotc/core/TypeErasure.scala @@ -443,7 +443,12 @@ object TypeErasure { } // We are not interested in anything that is not a supertype of tp2 - val tp2superclasses = tp1.baseClasses.filter(cls2.derivesFrom) + val tp2superclasses = tp1.baseClasses + // We filter out Pure from the base classes since CC should not affect binary compatibitlity + // and the algorithm here sometimes will take the erasure of Pure + // The root problem is described here: https://github.com/scala/scala3/issues/24148 + .filter(_ != defn.PureClass) + .filter(cls2.derivesFrom) // From the spec, "Linearization also satisfies the property that a // linearization of a class always contains the linearization of its @@ -672,6 +677,13 @@ class TypeErasure(sourceLanguage: SourceLanguage, semiEraseVCs: Boolean, isConst WildcardType case tp: TypeProxy => this(tp.underlying) + // When erasing something that is `A & Pure` or `Pure & A`, we should take the erasure of A + // This also work for [T <: Pure] `T & A` or `A & T` + // The root problem is described here: https://github.com/scala/scala3/issues/24113 + case AndType(tp1, tp2) if tp1.dealias.classSymbol == defn.PureClass => + this(tp2) + case AndType(tp1, tp2) if tp2.dealias.classSymbol == defn.PureClass => + this(tp1) case tp @ AndType(tp1, tp2) => if sourceLanguage.isJava then this(tp1) diff --git a/tests/run/i23882.check b/tests/run/i23882.check new file mode 100644 index 000000000000..4a26984466a2 --- /dev/null +++ b/tests/run/i23882.check @@ -0,0 +1,6 @@ +public void Foo.foo(java.lang.Object) +public void Foo.foo(scala.Equals) +public void Foo.bar(Bar) +public void Foo.bar2(Bar) +public void Foo.bar3(Bar) +public void Foo.bar4(Bar) diff --git a/tests/run/i23882.scala b/tests/run/i23882.scala new file mode 100644 index 000000000000..767771709db0 --- /dev/null +++ b/tests/run/i23882.scala @@ -0,0 +1,18 @@ +// scalajs: --skip + +import scala.collection.* +import scala.caps.Pure + +trait Bar + +class Foo: + def foo[T](x: Seq[T] | Set[T]): Unit = ??? // erases to a weird thing: scala.Equals + def foo[T](x: Array[T]): Unit = ??? // erases to Object + def bar(x: Bar & Pure): Unit = ??? // erases to Bar + def bar2(x: Pure & Bar): Unit = ??? // erases to Bar + def bar3[T <: Pure](x: Bar & T): Unit = ??? // erases to Bar + def bar4[T <: Pure](x: T & Bar): Unit = ??? // erases to Bar + +@main def Test = + for mtd <- classOf[Foo].getDeclaredMethods do + println(mtd)