From 3dc714083a237fc5916d83f934b29563de761f3f Mon Sep 17 00:00:00 2001 From: Suzanne Millstein Date: Tue, 2 Jul 2024 11:10:38 -0700 Subject: [PATCH 1/3] Correct type argument inference for method references with var args. --- framework/tests/all-systems/Issue6664.java | 30 +++++++++++++++++++ framework/tests/all-systems/Issue6664B.java | 28 +++++++++++++++++ .../checkerframework/javacutil/TreeUtils.java | 13 ++++++++ 3 files changed, 71 insertions(+) create mode 100644 framework/tests/all-systems/Issue6664.java create mode 100644 framework/tests/all-systems/Issue6664B.java diff --git a/framework/tests/all-systems/Issue6664.java b/framework/tests/all-systems/Issue6664.java new file mode 100644 index 00000000000..2ab59e6846a --- /dev/null +++ b/framework/tests/all-systems/Issue6664.java @@ -0,0 +1,30 @@ +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; +import java.util.function.Function; +import java.util.stream.Collector; +import java.util.stream.Collectors; + +public abstract class Issue6664 { + + public static Collector, ?, Issue6664>> breakIt() { + return Collectors.reducing( + Eithers.right(new ArrayList<>()), + either -> either.map(Arrays::asList), + (either, eithers) -> either); + } + + public Issue6664 map(Function function) { + throw new RuntimeException(); + } + + public static final class Eithers { + public static Issue6664 left(A left) { + throw new RuntimeException(); + } + + public static Issue6664 right(B right) { + throw new RuntimeException(); + } + } +} diff --git a/framework/tests/all-systems/Issue6664B.java b/framework/tests/all-systems/Issue6664B.java new file mode 100644 index 00000000000..c00faa56cde --- /dev/null +++ b/framework/tests/all-systems/Issue6664B.java @@ -0,0 +1,28 @@ +import java.util.Arrays; +import java.util.List; +import java.util.function.Function; + +public abstract class Issue6664B { + + void method2() { + // Doesn't use variable arity for method applicability. + Function> f1 = Arrays::asList; + + // Equivalent to Arrays.asList(obj). + Function> f2 = Arrays::asList; + // Equivalent to Arrays.asList(o1,o2,o3). + Foo f3 = Arrays::asList; + // Equivalent to Arrays.asList(). + Foo2 f4 = Arrays::asList; + } + + interface Foo { + + List apply(Object o1, Object o2, Object o3); + } + + interface Foo2 { + + List apply(); + } +} diff --git a/javacutil/src/main/java/org/checkerframework/javacutil/TreeUtils.java b/javacutil/src/main/java/org/checkerframework/javacutil/TreeUtils.java index d72bbfe65cb..81f4c1d09e5 100644 --- a/javacutil/src/main/java/org/checkerframework/javacutil/TreeUtils.java +++ b/javacutil/src/main/java/org/checkerframework/javacutil/TreeUtils.java @@ -2570,6 +2570,17 @@ public static boolean isVariableTreeDeclaredUsingVar(VariableTree variableTree) return type != null && type.pos == Position.NOPOS; } + /** + * Returns true if the given method references has a vararg element. + * + * @param methref the method reference + * @return if the given method references has a vararg element + */ + public static boolean hasVarArgElement(MemberReferenceTree methref) { + JCMemberReference jcMethoRef = (JCMemberReference) methref; + return jcMethoRef.varargsElement != null; + } + /** * Returns true if the given method/constructor invocation is a varargs invocation. * @@ -2582,6 +2593,8 @@ public static boolean isVarargsCall(Tree tree) { return isVarargsCall((MethodInvocationTree) tree); case NEW_CLASS: return isVarargsCall((NewClassTree) tree); + case MEMBER_REFERENCE: + return hasVarArgElement((MemberReferenceTree) tree); default: return false; } From 56b2cc516e9bd15c5ecd51ea266c67b06d96e35a Mon Sep 17 00:00:00 2001 From: Suzanne Millstein Date: Tue, 2 Jul 2024 12:13:04 -0700 Subject: [PATCH 2/3] Suppress warning. --- framework/tests/all-systems/Issue6664B.java | 1 + 1 file changed, 1 insertion(+) diff --git a/framework/tests/all-systems/Issue6664B.java b/framework/tests/all-systems/Issue6664B.java index c00faa56cde..27d5eaf5cc8 100644 --- a/framework/tests/all-systems/Issue6664B.java +++ b/framework/tests/all-systems/Issue6664B.java @@ -4,6 +4,7 @@ public abstract class Issue6664B { + @SuppressWarnings("purity.methodref") void method2() { // Doesn't use variable arity for method applicability. Function> f1 = Arrays::asList; From e24aa56ae1aef999a2eef30ec79daf36adc142b9 Mon Sep 17 00:00:00 2001 From: Michael Ernst Date: Tue, 2 Jul 2024 13:34:43 -0700 Subject: [PATCH 3/3] Rename, improve docs --- .../java/org/checkerframework/javacutil/TreeUtils.java | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/javacutil/src/main/java/org/checkerframework/javacutil/TreeUtils.java b/javacutil/src/main/java/org/checkerframework/javacutil/TreeUtils.java index 81f4c1d09e5..bf246a66b64 100644 --- a/javacutil/src/main/java/org/checkerframework/javacutil/TreeUtils.java +++ b/javacutil/src/main/java/org/checkerframework/javacutil/TreeUtils.java @@ -2571,12 +2571,12 @@ public static boolean isVariableTreeDeclaredUsingVar(VariableTree variableTree) } /** - * Returns true if the given method references has a vararg element. + * Returns true if the given method reference has a varargs formal parameter. * - * @param methref the method reference - * @return if the given method references has a vararg element + * @param methref a method reference + * @return if the given method reference has a varargs formal parameter */ - public static boolean hasVarArgElement(MemberReferenceTree methref) { + public static boolean hasVarargsParameter(MemberReferenceTree methref) { JCMemberReference jcMethoRef = (JCMemberReference) methref; return jcMethoRef.varargsElement != null; } @@ -2594,7 +2594,7 @@ public static boolean isVarargsCall(Tree tree) { case NEW_CLASS: return isVarargsCall((NewClassTree) tree); case MEMBER_REFERENCE: - return hasVarArgElement((MemberReferenceTree) tree); + return hasVarargsParameter((MemberReferenceTree) tree); default: return false; }