Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
24 changes: 23 additions & 1 deletion compiler/src/dotty/tools/dotc/core/TypeComparer.scala
Original file line number Diff line number Diff line change
Expand Up @@ -993,7 +993,29 @@ class TypeComparer(@constructorOnly initctx: Context) extends ConstraintHandling
(sym1 eq NullClass) && isNullable(tp2)
}
case tp1 @ AppliedType(tycon1, args1) =>
compareAppliedType1(tp1, tycon1, args1)
// Special case: Java arrays are covariant.
// When checking overrides (frozenConstraint), allow B[] <: A[] if B <: A
// for Java-defined types.
def checkJavaArrayCovariance: Boolean = tp2 match {
case AppliedType(tycon2, arg2 :: Nil)
if frozenConstraint // for override checking (frozen_<:)
&& tycon1.typeSymbol == defn.ArrayClass
&& tycon2.typeSymbol == defn.ArrayClass
&& args1.length == 1 =>
// Check if element types are Java-defined to detect Java arrays
val elem1Sym = args1.head.typeSymbol
val elem2Sym = arg2.typeSymbol
Copy link
Member Author

@tanishiking tanishiking Nov 11, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ah, it doesn't work if the elemnt type is defined in Scala :/
We need to somehow check AppliedType(ArrayClass, args)s are JavaArray or not 🤔

if elem1Sym.exists && elem2Sym.exists
&& elem1Sym.is(JavaDefined) && elem2Sym.is(JavaDefined)
then
// Arrays are covariant in Java: B[] <: A[] if B <: A
isSubType(args1.head, arg2)
else
false
case _ => false
}

checkJavaArrayCovariance || compareAppliedType1(tp1, tycon1, args1)
case tp1: SingletonType =>
def comparePaths = tp2 match
case tp2: (TermRef | ThisType) =>
Expand Down
17 changes: 17 additions & 0 deletions tests/pos/i24074/JavaPart.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
public class JavaPart {
public interface A { }
public interface B extends A {
int onlyInB();
}

public interface Lvl1 {
A[] getData();
}

public interface Lvl2 extends Lvl1 {
@Override
B[] getData();
}

public interface Lvl3 extends Lvl2, Lvl1 { }
}
6 changes: 6 additions & 0 deletions tests/pos/i24074/Test.scala
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
// trait Test extends JavaPart.Lvl3
// object TestImpl extends Test:
// def getData(): Array[JavaPart.B] = ???
object Test:
def test(lvl3: JavaPart.Lvl3): Unit =
lvl3.getData.head.onlyInB()
Loading