diff --git a/compiler/src/dotty/tools/dotc/core/TypeComparer.scala b/compiler/src/dotty/tools/dotc/core/TypeComparer.scala index 77fdc24a01cc..73e135633161 100644 --- a/compiler/src/dotty/tools/dotc/core/TypeComparer.scala +++ b/compiler/src/dotty/tools/dotc/core/TypeComparer.scala @@ -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 + 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) => diff --git a/tests/pos/i24074/JavaPart.java b/tests/pos/i24074/JavaPart.java new file mode 100644 index 000000000000..78065416caa8 --- /dev/null +++ b/tests/pos/i24074/JavaPart.java @@ -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 { } +} \ No newline at end of file diff --git a/tests/pos/i24074/Test.scala b/tests/pos/i24074/Test.scala new file mode 100644 index 000000000000..b64c3914ef38 --- /dev/null +++ b/tests/pos/i24074/Test.scala @@ -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() \ No newline at end of file