From 12732525b55ed31fbde44e3d42ab2c0ad6ff7459 Mon Sep 17 00:00:00 2001 From: Anders Schack-Mulligen Date: Fri, 18 Jul 2025 11:45:45 +0200 Subject: [PATCH 1/3] Java: Allow 2-column join on delta to improve join-order. --- java/ql/lib/semmle/code/java/Generics.qll | 18 +++++++++++++----- 1 file changed, 13 insertions(+), 5 deletions(-) diff --git a/java/ql/lib/semmle/code/java/Generics.qll b/java/ql/lib/semmle/code/java/Generics.qll index e0204b1beace..fbd979a03694 100644 --- a/java/ql/lib/semmle/code/java/Generics.qll +++ b/java/ql/lib/semmle/code/java/Generics.qll @@ -521,7 +521,13 @@ private predicate unificationTargets(RefType t1, Type t2) { t2 = a2.getComponentType() ) or - exists(ParameterizedType pt1, ParameterizedType pt2, int pos | + unificationTargetsParameterized(_, _, t1, t2) +} + +private predicate unificationTargetsParameterized( + ParameterizedType pt1, ParameterizedType pt2, RefType t1, RefType t2 +) { + exists(int pos | unificationTargets(pt1, pt2) and t1 = pt1.getTypeArgument(pos) and t2 = pt2.getTypeArgument(pos) @@ -565,10 +571,12 @@ private predicate hasParameterSubstitution( GenericType g1, ParameterizedType pt1, GenericType g2, ParameterizedType pt2, TypeVariable v, RefType subst ) { - unificationTargets(pt1, pt2) and - exists(int pos | hasSubstitution(pt1.getTypeArgument(pos), pt2.getTypeArgument(pos), v, subst)) and - g1 = pt1.getGenericType() and - g2 = pt2.getGenericType() + exists(RefType t1, RefType t2 | + unificationTargetsParameterized(pt1, pt2, t1, t2) and + hasSubstitution(t1, t2, v, subst) and + g1 = pt1.getGenericType() and + g2 = pt2.getGenericType() + ) } /** From 7883124abddf3ac73c383df10e9942cd8d0dedb8 Mon Sep 17 00:00:00 2001 From: Anders Schack-Mulligen Date: Fri, 18 Jul 2025 11:47:14 +0200 Subject: [PATCH 2/3] Java: getSourceDeclaration() and getASourceSupertype*() commute and this yields much better join-order. --- java/ql/src/Likely Bugs/Collections/ContainsTypeMismatch.ql | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/java/ql/src/Likely Bugs/Collections/ContainsTypeMismatch.ql b/java/ql/src/Likely Bugs/Collections/ContainsTypeMismatch.ql index d1a398d1322c..497aa10cb4de 100644 --- a/java/ql/src/Likely Bugs/Collections/ContainsTypeMismatch.ql +++ b/java/ql/src/Likely Bugs/Collections/ContainsTypeMismatch.ql @@ -103,8 +103,8 @@ class MismatchedContainerAccess extends MethodCall { | this.getCallee() .getDeclaringType() - .getASourceSupertype*() .getSourceDeclaration() + .getASourceSupertype*() .hasQualifiedName(package, type) and this.getCallee().getParameter(i).getType() instanceof TypeObject ) @@ -119,7 +119,7 @@ class MismatchedContainerAccess extends MethodCall { containerAccess(package, type, p, this.getCallee().getSignature(), i) | t = this.getCallee().getDeclaringType() and - t.getASourceSupertype*().getSourceDeclaration() = g and + t.getSourceDeclaration().getASourceSupertype*() = g and g.hasQualifiedName(package, type) and indirectlyInstantiates(t, g, p, result) ) From d9f47bdec9ec0ac568c1a447ccf42fe93ad0ccdc Mon Sep 17 00:00:00 2001 From: Anders Schack-Mulligen Date: Fri, 18 Jul 2025 11:48:50 +0200 Subject: [PATCH 3/3] Java: Improve join-order by properly annotating haveIntersection. --- java/ql/lib/semmle/code/java/Type.qll | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/java/ql/lib/semmle/code/java/Type.qll b/java/ql/lib/semmle/code/java/Type.qll index aa1cc5fdc7f7..dd646e74285c 100644 --- a/java/ql/lib/semmle/code/java/Type.qll +++ b/java/ql/lib/semmle/code/java/Type.qll @@ -1261,14 +1261,21 @@ private Type erase(Type t) { * * For the definition of the notion of *erasure* see JLS v8, section 4.6 (Type Erasure). */ +bindingset[t1, t2] overlay[caller?] -pragma[inline] +pragma[inline_late] predicate haveIntersection(RefType t1, RefType t2) { exists(RefType e1, RefType e2 | e1 = erase(t1) and e2 = erase(t2) | - erasedHaveIntersection(e1, e2) + erasedHaveIntersectionFilter(e1, e2) ) } +bindingset[t1, t2] +pragma[inline_late] +private predicate erasedHaveIntersectionFilter(RefType t1, RefType t2) { + erasedHaveIntersection(t1, t2) +} + /** * Holds if there is no common (reflexive, transitive) subtype of the erasures * of types `t1` and `t2`.