Add a test case

This commit is contained in:
Clément Fournier committed 2022-11-29 19:50:59 +01:00
1 parent b90e46a449
commit eeed82ae4e
9 files changed
+245 -202

No files matched your search

@@ -62,6 +62,7 @@ class AstSymbolicAnnot implements SymbolicValue.SymAnnot {
@Override
public boolean appliesToTypeUse() {
// todo look into whether hardcoding Override is good for perf, as it's very frequent
return node.getTypeMirror().getSymbol().annotationAppliesTo(ElementType.TYPE_USE);
}
@@ -117,19 +117,23 @@ public final class TypeOps {
}
}
public static boolean areSameTypes(List<JTypeMirror> ts, List<JTypeMirror> ss, boolean inInference) {
return areSameTypes(ts, ss, EMPTY, inInference, false);
public static boolean areSameTypes(List<JTypeMirror> ts, List<JTypeMirror> ss) {
return areSameTypes(ts, ss, EMPTY, false, false);
}
public static boolean areSameTypes(List<JTypeMirror> ts, List<JTypeMirror> ss, boolean inInference, boolean considerAnnotations) {
public static boolean areSameTypesInInference(List<JTypeMirror> ts, List<JTypeMirror> ss) {
return areSameTypes(ts, ss, EMPTY, true, false);
}
private static boolean areSameTypes(List<JTypeMirror> ts, List<JTypeMirror> ss, boolean inInference, boolean considerAnnotations) {
return areSameTypes(ts, ss, EMPTY, inInference, considerAnnotations);
}
public static boolean areSameTypes(List<JTypeMirror> ts, List<JTypeMirror> ss, Substitution subst) {
private static boolean areSameTypes(List<JTypeMirror> ts, List<JTypeMirror> ss, Substitution subst) {
return areSameTypes(ts, ss, subst, false, false);
}
public static boolean areSameTypes(List<JTypeMirror> ts, List<JTypeMirror> ss, Substitution subst, boolean inInference, boolean considerAnnotations) {
private static boolean areSameTypes(List<JTypeMirror> ts, List<JTypeMirror> ss, Substitution subst, boolean inInference, boolean considerAnnotations) {
if (ts.size() != ss.size()) {
return false;
}
@@ -115,12 +115,15 @@ abstract class TypeVarImpl implements JTypeVar {
@Override
public JTypeVar withAnnotations(PSet<SymAnnot> newTypeAnnots) {
if (newTypeAnnots.isEmpty() && this.typeAnnots.isEmpty()) {
return this;
}
return new RegularTypeVar(this, newTypeAnnots);
}
@Override
public JTypeVar addAnnotation(@NonNull SymAnnot newAnnot) {
return new RegularTypeVar(this, typeAnnots.plus(newAnnot));
return withAnnotations(typeAnnots.plus(newAnnot));
}
@Override
@@ -5,7 +5,7 @@
package net.sourceforge.pmd.lang.java.types.internal.infer;
import static net.sourceforge.pmd.lang.java.types.TypeConversion.capture;
import static net.sourceforge.pmd.lang.java.types.TypeOps.areSameTypes;
import static net.sourceforge.pmd.lang.java.types.TypeOps.areSameTypesInInference;
import static net.sourceforge.pmd.lang.java.types.TypeOps.asClassType;
import static net.sourceforge.pmd.lang.java.types.TypeOps.findFunctionalInterfaceMethod;
import static net.sourceforge.pmd.lang.java.types.TypeOps.mentionsAny;
@@ -539,7 +539,7 @@ final class ExprCheckHelper {
// and the function type has parameter types G1, ..., Gn, then
// i) for all i (1 ≤ i ≤ n), Fi = Gi
if (lambda.isExplicitlyTyped()
&& !areSameTypes(groundFun.getFormalParameters(), lambda.getExplicitParameterTypes(), true)) {
&& !areSameTypesInInference(groundFun.getFormalParameters(), lambda.getExplicitParameterTypes())) {
throw ResolutionFailedException.mismatchedLambdaParameters(infer.LOG, groundFun, lambda.getExplicitParameterTypes(), lambda);
}
@@ -96,6 +96,10 @@ public class JavaParsingHelper extends BaseParsingHelper<JavaParsingHelper, ASTC
return new JavaParsingHelper(this.getParams(), this.semanticLogger, this.ts, logger);
}
public JavaParsingHelper logTypeInferenceVerbose() {
return logTypeInference(true, System.out);
}
@Override
protected @NonNull JavaParsingHelper clone(@NonNull Params params) {
return new JavaParsingHelper(params, semanticLogger, ts, typeInfLogger);
@@ -15,6 +15,7 @@ import net.sourceforge.pmd.lang.ast.test.BaseTreeDumpTest;
import net.sourceforge.pmd.lang.ast.test.RelevantAttributePrinter;
import net.sourceforge.pmd.lang.java.JavaParsingHelper;
import net.sourceforge.pmd.lang.java.ast.ASTAssignableExpr.ASTNamedReferenceExpr;
import net.sourceforge.pmd.lang.java.ast.ASTMethodDeclaration;
import net.sourceforge.pmd.lang.java.ast.ASTVariableDeclaratorId;
import net.sourceforge.pmd.lang.java.ast.InvocationNode;
import net.sourceforge.pmd.lang.java.ast.TypeNode;
@@ -71,6 +72,9 @@ class TypesTreeDumpTest extends BaseTreeDumpTest {
if (node instanceof ASTVariableDeclaratorId) {
result.add(new AttributeInfo("Name", ((ASTVariableDeclaratorId) node).getName()));
}
if (node instanceof ASTMethodDeclaration) {
result.add(new AttributeInfo("Name", ((ASTMethodDeclaration) node).getName()));
}
}
@Override
@@ -726,4 +726,43 @@ class NodeStream<T> {
}
}
parserTest("f:inference of call within lambda fails") {
val (acu, spy) = parser.logTypeInferenceVerbose().parseWithTypeInferenceSpy("""
interface Iterator<Q> {}
interface Function<U,V> {
V apply(U u);
}
interface Iterable<Q> {
Iterator<Q> iterator();
}
class NodeStream {
public static <T, R> Iterable<R> mapIterator(Iterable<? extends T> iter, Function<? super Iterator<? extends T>, ? extends Iterator<R>> mapper) {
return () -> mapper.apply(iter.iterator());
}
}
""")
val (t_Iterator, t_Function, t_Iterable) = acu.declaredTypeSignatures()
val (lambda) = acu.descendants(ASTLambdaExpression::class.java).crossFindBoundaries().toList()
val (_, _, _, _, tvar, rvar) = acu.typeVariables()
spy.shouldBeOk {
lambda shouldHaveType t_Iterable[rvar]
lambda.expressionBody!!.shouldBeA<ASTMethodCall> {
it.methodType.shouldMatchMethod(
named = "apply",
withFormals = listOf(t_Iterator[`?` extends tvar])
)
it shouldHaveType t_Iterator[rvar]
}
}
}
})
@@ -3,8 +3,8 @@
*/
package net.sourceforge.pmd.internal.util;
import java.lang.annotation.ElementType;
import java.lang.annotation.Target;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
@@ -30,10 +30,13 @@ public final class IteratorUtilCopy {
private static final int MATCH_ALL = 1;
private static final int MATCH_NONE = 2;
private IteratorUtil() {
private IteratorUtilCopy() {
}
@Target(ElementType.TYPE_USE)
@interface Nullable {}
public static <T> Iterator<T> takeWhile(Iterator<T> iter, Predicate<? super T> predicate) {
return new AbstractIterator<T>() {
@Override
@@ -246,8 +249,6 @@ public final class IteratorUtilCopy {
public static void advance(Iterator<?> iterator, int n) {
AssertionUtil.requireNonNegative("n", n);
while (n > 0 && iterator.hasNext()) {
iterator.next();
n--;
@@ -256,7 +257,6 @@ public final class IteratorUtilCopy {
public static <T> Iterator<T> take(Iterator<? extends T> iterator, final int n) {
AssertionUtil.requireNonNegative("n", n);
if (n == 0) {
return Collections.emptyIterator();
}
@@ -278,7 +278,6 @@ public final class IteratorUtilCopy {
public static <T> Iterator<T> drop(Iterator<? extends T> source, final int n) {
AssertionUtil.requireNonNegative("n", n);
if (n == 0) {
return (Iterator<T>) source;
}
File diff suppressed because it is too large. Load diff