Skip to content

Commit

Permalink
Merge branch 'pr-5008'
Browse files Browse the repository at this point in the history
  • Loading branch information
jsotuyod committed May 14, 2024
2 parents f1701df + 4472521 commit 03f5f1a
Show file tree
Hide file tree
Showing 3 changed files with 44 additions and 4 deletions.
1 change: 1 addition & 0 deletions docs/pages/release_notes.md
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@ Since this release, PMD will also expose any getter returning a collection of an
* [#4973](https://github.com/pmd/pmd/pull/4973): \[java] Stop parsing Java for CPD
* [#4980](https://github.com/pmd/pmd/issues/4980): \[java] Bad intersection, unrelated class types java.lang.Object\[] and java.lang.Number
* [#4988](https://github.com/pmd/pmd/pull/4988): \[java] Fix impl of ASTVariableId::isResourceDeclaration / VariableId/@<!-- -->ResourceDeclaration
* [#5006](https://github.com/pmd/pmd/issues/5006): \[java] Bad intersection, unrelated class types Child and Parent<? extends Child>
* java-bestpractices
* [#4278](https://github.com/pmd/pmd/issues/4278): \[java] UnusedPrivateMethod FP with Junit 5 @MethodSource and default factory method name
* [#4852](https://github.com/pmd/pmd/issues/4852): \[java] ReplaceVectorWithList false-positive (neither Vector nor List usage)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -340,10 +340,21 @@ static JTypeMirror glb(TypeSystem ts, Collection<? extends JTypeMirror> types) {
JTypeMirror componentGlb = glb(ts, setOf(((JArrayType) ci).getComponentType(),
((JArrayType) primaryBound).getComponentType()));
primaryBound = ts.arrayType(componentGlb);

} else {
throw new IllegalArgumentException(
"Bad intersection, unrelated class types " + ci + " and " + primaryBound + " in " + types
);
// We have two primary bounds. This may happen during capture
// of recursive F-bounded types. Here we do a last resort check
// to see if one of the bounds is a subtype (unchecked) of the other.
// In that case we pick this as primary bound as it is more specific.

int cmp = compareRelatedness(ci.getErasure(), primaryBound.getErasure());
if (cmp == 0) {
throw new IllegalArgumentException(
"Bad intersection, unrelated class types " + ci + " and " + primaryBound + " in " + types
);
} else if (cmp < 0) {
primaryBound = ci;
}
}
} else {
bounds.add(ci);
Expand All @@ -366,6 +377,15 @@ static JTypeMirror glb(TypeSystem ts, Collection<? extends JTypeMirror> types) {
return new JIntersectionType(ts, primaryBound, bounds);
}

private static int compareRelatedness(JTypeMirror t, JTypeMirror s) {
if (TypeOps.isConvertiblePure(t, s.getErasure()).withoutWarnings()) {
return -1;
} else if (TypeOps.isConvertiblePure(s, t.getErasure()).withoutWarnings()) {
return 1;
}
return 0;
}

private static void checkGlbComponent(Collection<? extends JTypeMirror> types, JTypeMirror ci) {
if (ci.isPrimitive() || ci instanceof JWildcardType || ci instanceof JIntersectionType) {
throw new IllegalArgumentException("Bad intersection type component: " + ci + " in " + types);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,11 +9,12 @@ import io.kotest.core.spec.style.FunSpec
import io.kotest.matchers.shouldBe
import net.sourceforge.pmd.lang.java.symbols.internal.asm.createUnresolvedAsmSymbol
import net.sourceforge.pmd.lang.java.types.TypeConversion.*
import net.sourceforge.pmd.lang.test.ast.IntelliMarker

/**
* @author Clément Fournier
*/
class CaptureTest : FunSpec({
class CaptureTest : IntelliMarker, FunSpec({

with(TypeDslOf(testTypeSystem)) {
with(gen) {
Expand Down Expand Up @@ -69,6 +70,24 @@ class CaptureTest : FunSpec({
}
}

test("Capture of recursive types #5006") {
val acu = javaParser.parse("""
class Parent<T extends Parent<T>> {} // Recursive type T

class Child extends Parent<Child> {}

class Box<T extends Parent<T>> {
public void foo(Box<? extends Child> box) {} // <-- The bug is triggered by this line
}
""".trimIndent())

val (_, child, box) = acu.declaredTypeSignatures()

val type = acu.methodDeclarations().first()!!.formalParameters.get(0).typeMirror

capture(type) shouldBe box[captureMatcher(`?` extends child)]
}

}
}

Expand Down

0 comments on commit 03f5f1a

Please sign in to comment.