Fix TypeOps::mostSpecific in the case of possible unchecked conversion

This commit is contained in:
Clément Fournier
2024-04-05 12:16:28 +02:00
parent f2a586c6f2
commit 7bd37cd79d
4 changed files with 38 additions and 2 deletions

View File

@ -1733,8 +1733,15 @@ public final class TypeOps {
vLoop:
for (JTypeMirror v : set) {
for (JTypeMirror w : set) {
if (!w.equals(v) && !hasUnresolvedSymbol(w) && isSubtypePure(w, v).bySubtyping()) {
continue vLoop;
if (!w.equals(v) && !hasUnresolvedSymbol(w)) {
Convertibility isConvertible = isSubtypePure(w, v);
if (isConvertible.bySubtyping()
// This last case covers unchecked conversion. It is made antisymmetric by the
// test for a symbol. eg |G| <~> G<?> so it would fail.
// However, |G| ~> S if |G| <: |S|, so we should consider |G| more specific than S.
|| isConvertible.somehow() && !Objects.equals(w.getSymbol(), v.getSymbol())) {
continue vLoop;
}
}
}
result.add(v);

View File

@ -46,5 +46,8 @@ public class LubTestData {
public static class GenericSub2<T> extends GenericSuper<T> implements I2<I3>, I4 {
}
public interface EnumSuperItf {}
public enum Enum1 implements EnumSuperItf {}
public enum Enum2 implements EnumSuperItf {}
}

View File

@ -10,6 +10,7 @@ import io.kotest.matchers.collections.shouldContainExactly
import io.kotest.matchers.nulls.shouldBeNull
import io.kotest.matchers.shouldBe
import io.kotest.property.checkAll
import io.mockk.InternalPlatformDsl.toArray
import net.sourceforge.pmd.lang.test.ast.shouldBeA
import net.sourceforge.pmd.lang.java.symbols.internal.asm.createUnresolvedAsmSymbol
@ -71,6 +72,14 @@ class GlbTest : FunSpec({
}
test("Test GLB of arrays") {
glb(ts.SERIALIZABLE.toArray(), t_ArrayList.toArray()) shouldBe t_ArrayList.toArray()
glb(t_ArrayList.toArray(), ts.SERIALIZABLE.toArray()) shouldBe t_ArrayList.toArray()
glb(t_List.toArray(), `t_List{?}`.toArray()) shouldBe `t_List{?}`.toArray()
}
test("Test lub of zero types") {
shouldThrow<IllegalArgumentException> {

View File

@ -8,6 +8,7 @@ import io.kotest.assertions.throwables.shouldThrow
import io.kotest.core.spec.style.FunSpec
import io.kotest.matchers.shouldBe
import io.kotest.property.checkAll
import net.sourceforge.pmd.lang.java.types.testdata.LubTestData
import net.sourceforge.pmd.lang.java.types.testdata.LubTestData.*
/**
@ -140,6 +141,22 @@ class LubTest : FunSpec({
lub(t_List[Sub1::class.decl], t_List[Sub2::class.decl]) shouldBe result
}
test("Test lub of related arrays") {
// the component type
lub(
Enum1::class.decl,
Enum2::class.decl,
) shouldBe t_Enum[`?` extends t_Enum[`?`] * EnumSuperItf::class.decl] * EnumSuperItf::class.decl
// let's try arrays
lub(
Enum1::class.decl.toArray(),
Enum2::class.decl.toArray(),
) shouldBe t_Enum[`?` extends t_Enum[`?`] * EnumSuperItf::class.decl] * EnumSuperItf::class.decl
}
}
}