Skip to content

Commit 8ace7f0

Browse files
committed
fix: discard scala.caps.Pure in the erasure of union and intersection types
1 parent 5b02216 commit 8ace7f0

File tree

3 files changed

+37
-1
lines changed

3 files changed

+37
-1
lines changed

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

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -443,7 +443,12 @@ object TypeErasure {
443443
}
444444

445445
// We are not interested in anything that is not a supertype of tp2
446-
val tp2superclasses = tp1.baseClasses.filter(cls2.derivesFrom)
446+
val tp2superclasses = tp1.baseClasses
447+
// We filter out Pure from the base classes since CC should not affect binary compatibitlity
448+
// and the algorithm here sometimes will take the erasure of Pure
449+
// The root problem is described here: https://github.com/scala/scala3/issues/24148
450+
.filter(_ != defn.PureClass)
451+
.filter(cls2.derivesFrom)
447452

448453
// From the spec, "Linearization also satisfies the property that a
449454
// linearization of a class always contains the linearization of its
@@ -672,6 +677,13 @@ class TypeErasure(sourceLanguage: SourceLanguage, semiEraseVCs: Boolean, isConst
672677
WildcardType
673678
case tp: TypeProxy =>
674679
this(tp.underlying)
680+
// When erasing something that is `A & Pure` or `Pure & A`, we should take the erasure of A
681+
// This also work for [T <: Pure] `T & A` or `A & T`
682+
// The root problem is described here: https://github.com/scala/scala3/issues/24113
683+
case AndType(tp1, tp2) if tp1.dealias.classSymbol == defn.PureClass =>
684+
this(tp2)
685+
case AndType(tp1, tp2) if tp2.dealias.classSymbol == defn.PureClass =>
686+
this(tp1)
675687
case tp @ AndType(tp1, tp2) =>
676688
if sourceLanguage.isJava then
677689
this(tp1)

tests/run/i23882.check

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
public void Foo.foo(java.lang.Object)
2+
public void Foo.foo(scala.Equals)
3+
public void Foo.bar(Bar)
4+
public void Foo.bar2(Bar)
5+
public void Foo.bar3(Bar)
6+
public void Foo.bar4(Bar)

tests/run/i23882.scala

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
// scalajs: --skip
2+
3+
import scala.collection.*
4+
import scala.caps.Pure
5+
6+
trait Bar
7+
8+
class Foo:
9+
def foo[T](x: Seq[T] | Set[T]): Unit = ??? // erases to a weird thing: scala.Equals
10+
def foo[T](x: Array[T]): Unit = ??? // erases to Object
11+
def bar(x: Bar & Pure): Unit = ??? // erases to Bar
12+
def bar2(x: Pure & Bar): Unit = ??? // erases to Bar
13+
def bar3[T <: Pure](x: Bar & T): Unit = ??? // erases to Bar
14+
def bar4[T <: Pure](x: T & Bar): Unit = ??? // erases to Bar
15+
16+
@main def Test =
17+
for mtd <- classOf[Foo].getDeclaredMethods do
18+
println(mtd)

0 commit comments

Comments
 (0)