Skip to content

Commit 33b7bc3

Browse files
committed
Fix array erasure
1 parent af30139 commit 33b7bc3

File tree

3 files changed

+15
-10
lines changed

3 files changed

+15
-10
lines changed

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

Lines changed: 6 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -247,15 +247,15 @@ object TypeErasure {
247247
def isUnboundedGeneric(tp: Type)(using Context): Boolean = tp.dealias match {
248248
case tp: TypeRef if !tp.symbol.isOpaqueAlias =>
249249
!tp.symbol.isClass &&
250-
!classify(tp).derivesFrom(defn.ObjectClass) &&
250+
!classify(tp).derivesFrom(defn.ObjectClass, afterErasure = true) &&
251251
!tp.symbol.is(JavaDefined)
252252
case tp: TypeParamRef =>
253-
!classify(tp).derivesFrom(defn.ObjectClass) &&
253+
!classify(tp).derivesFrom(defn.ObjectClass, afterErasure = true) &&
254254
!tp.binder.resultType.isJavaMethod
255255
case tp: TypeAlias => isUnboundedGeneric(tp.alias)
256256
case tp: TypeBounds =>
257257
val upper = classify(tp.hi)
258-
!upper.derivesFrom(defn.ObjectClass) &&
258+
!upper.derivesFrom(defn.ObjectClass, afterErasure = true) &&
259259
!upper.isPrimitiveValueType
260260
case tp: TypeProxy => isUnboundedGeneric(tp.translucentSuperType)
261261
case tp: AndType => isUnboundedGeneric(tp.tp1) && isUnboundedGeneric(tp.tp2)
@@ -292,8 +292,8 @@ object TypeErasure {
292292
// We need to short-circuit this case here because the regular lub logic below
293293
// relies on the class hierarchy, which doesn't properly capture `Null`s subtyping
294294
// behaviour.
295-
if (tp1.isBottomTypeAfterErasure && tp2.derivesFrom(defn.ObjectClass)) return tp2
296-
if (tp2.isBottomTypeAfterErasure && tp1.derivesFrom(defn.ObjectClass)) return tp1
295+
if (tp1.isBottomTypeAfterErasure && tp2.derivesFrom(defn.ObjectClass, afterErasure = true)) return tp2
296+
if (tp2.isBottomTypeAfterErasure && tp1.derivesFrom(defn.ObjectClass, afterErasure = true)) return tp1
297297
tp1 match {
298298
case JavaArrayType(elem1) =>
299299
import dotty.tools.dotc.transform.TypeUtils._
@@ -516,8 +516,7 @@ class TypeErasure(isJava: Boolean, semiEraseVCs: Boolean, isConstructor: Boolean
516516
}
517517

518518
private def eraseArray(tp: Type)(using Context) = {
519-
val defn.ArrayOf(elemtp0) = tp
520-
val elemtp = if ctx.explicitNulls then elemtp0.stripNull else elemtp0
519+
val defn.ArrayOf(elemtp) = tp
521520
if classify(elemtp).derivesFrom(defn.NullClass) then JavaArrayType(defn.ObjectType)
522521
else if isUnboundedGeneric(elemtp) && !isJava then defn.ObjectType
523522
else JavaArrayType(erasureFn(isJava, semiEraseVCs = false, isConstructor, wildcardOK)(elemtp))

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

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -256,7 +256,7 @@ object Types {
256256
/** True if this type is an instance of the given `cls` or an instance of
257257
* a non-bottom subclass of `cls`.
258258
*/
259-
final def derivesFrom(cls: Symbol)(using Context): Boolean = {
259+
final def derivesFrom(cls: Symbol, afterErasure: Boolean = false)(using Context): Boolean = {
260260
def loop(tp: Type): Boolean = tp match {
261261
case tp: TypeRef =>
262262
val sym = tp.symbol
@@ -274,7 +274,7 @@ object Types {
274274
// and `T` derivesFrom the class, then the OrType derivesFrom the class.
275275
// Otherwise, we need to check both sides derivesFrom the class.
276276
def isLowerBottomType(tp: Type) =
277-
tp.isBottomType
277+
(if afterErasure then t.isBottomTypeAfterErasure else t.isBottomType)
278278
&& (tp.hasClassSymbol(defn.NothingClass)
279279
|| cls != defn.NothingClass && !cls.isValueClass)
280280
if isLowerBottomType(tp.tp1) then
@@ -1035,7 +1035,7 @@ object Types {
10351035
|| matchLoosely && {
10361036
val this1 = widenNullary(this)
10371037
val that1 = widenNullary(that)
1038-
((this1 `ne` this) || (that1 `ne` that))
1038+
((this1 `ne` this) || (that1 `ne` that))
10391039
&& this1.overrides(that1, false, checkClassInfo, relaxedNulls)
10401040
}
10411041
}
Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
object Test {
2+
def main(args: Array[String]): Unit = {
3+
val v: Vector[String | Null] = Vector("a", "b")
4+
println(v)
5+
}
6+
}

0 commit comments

Comments
 (0)