Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
63 commits
Select commit Hold shift + click to select a range
a2aa1fc
checkpoint
smillst Sep 4, 2025
97213b5
Passes issue specific test, but fails all-tests.
smillst Sep 8, 2025
5fcff3e
Fix.
smillst Sep 9, 2025
8f07d03
Fix.
smillst Sep 9, 2025
89826db
Fix.
smillst Sep 10, 2025
31dc362
Merge remote-tracking branch 'origin/master' into dataflow-lambda
smillst Sep 10, 2025
1c3d8bc
Fix.
smillst Sep 10, 2025
cf85491
Merge remote-tracking branch 'origin/master' into dataflow-lambda
smillst Sep 10, 2025
75b5d30
Add test cases.
smillst Sep 10, 2025
dfee582
Correct error message.
smillst Sep 11, 2025
0bf2cc3
Merge remote-tracking branch 'origin/master' into dataflow-lambda
smillst Sep 16, 2025
58ff982
Merge remote-tracking branch 'origin/master' into dataflow-lambda
smillst Sep 26, 2025
1fea0f1
Fix.
smillst Sep 26, 2025
3a2ff25
Add javadoc.
smillst Sep 26, 2025
cb00f2c
Fix error.
smillst Sep 26, 2025
a593775
Fix error.
smillst Sep 26, 2025
7ca1759
Add opt.
smillst Sep 29, 2025
be26bfb
Merge remote-tracking branch 'origin/master' into dataflow-lambda-2
smillst Oct 2, 2025
3c0b6f7
Put lambdas in own block.
smillst Oct 3, 2025
b72c068
Merge branch 'lambda-in-own-block' into dataflow-lambda-2
smillst Oct 3, 2025
b7083d3
fix. this should work.
smillst Oct 3, 2025
002af82
fix interning error.
smillst Oct 3, 2025
e2f119f
Make checker/dist/checker.jar an output file.
smillst Oct 6, 2025
c444537
Merge branch 'gradle-tweak' into dataflow-lambda-2
smillst Oct 6, 2025
4f446ad
Fix.
smillst Oct 6, 2025
b9cd9db
Fix.
smillst Oct 6, 2025
6629722
Fix.
smillst Oct 7, 2025
395df46
Tweaks.
smillst Oct 8, 2025
01c8dea
Add comment.
smillst Oct 8, 2025
59988f5
Merge ../checker-framework-branch-master into dataflow-lambda-2
mernst Oct 9, 2025
00cc6c2
Code review tweaks.
smillst Oct 9, 2025
cf74460
More tweaks.
smillst Oct 9, 2025
1c886a3
Coderabbit suggestions.
smillst Oct 9, 2025
2ec4d83
More tweaks.
smillst Oct 9, 2025
408d3d6
Merge branch 'master' into dataflow-lambda-2
smillst Oct 9, 2025
c6ccb0c
Merge branch 'dataflow-lambda-2' of github.com:smillst/checker-framew…
mernst Oct 10, 2025
b904957
Revert change.
smillst Oct 10, 2025
1bf5991
Merge remote-tracking branch 'origin/master' into dataflow-lambda-2
smillst Oct 10, 2025
906daf7
Fix.
smillst Oct 10, 2025
40ac356
Remove unused parameter.
smillst Oct 10, 2025
11ac7c2
Update framework/src/main/java/org/checkerframework/framework/type/Ge…
smillst Oct 10, 2025
7b05e51
Merge ../checker-framework-branch-master into dataflow-lambda-2
mernst Oct 14, 2025
9b851da
Documentation and naming
mernst Oct 14, 2025
980bbdf
Worklists
mernst Oct 14, 2025
708d6f1
Improve style for worklists
mernst Oct 14, 2025
f0850cc
Merge ../checker-framework-fork-mernst-branch-worklists into dataflow…
mernst Oct 14, 2025
c90194e
Rename class flow methods
mernst Oct 14, 2025
68d43a3
Undo whitespace change
mernst Oct 14, 2025
c37145c
Merge ../checker-framework-fork-mernst-branch-flow-analysis-class-nam…
mernst Oct 14, 2025
dc01243
Naming
mernst Oct 14, 2025
b8fb483
Simplifications
mernst Oct 14, 2025
c3da5a8
Merge remote-tracking branch 'origin/master' into dataflow-lambda-2
smillst Oct 15, 2025
4b3fb68
Code review.
smillst Oct 15, 2025
87fb050
Code review.
smillst Oct 15, 2025
e78e0bf
Code rabbit.
smillst Oct 16, 2025
0bab99f
Fix typechecking errors.
smillst Oct 16, 2025
320309e
Merge ../checker-framework-branch-master into dataflow-lambda-2
mernst Oct 21, 2025
6de3e4a
Rename a variable, tweak documentation
mernst Oct 23, 2025
b912c2c
Code review.
smillst Oct 24, 2025
ddd2000
Coderabbit.
smillst Oct 24, 2025
67849aa
Merge remote-tracking branch 'origin/master' into dataflow-lambda-2
smillst Oct 24, 2025
d614675
Fix.
smillst Oct 24, 2025
f152263
Merge branch 'master' into dataflow-lambda-2
smillst Oct 24, 2025
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@

import com.google.common.collect.BiMap;
import com.google.common.collect.HashBiMap;
import com.sun.source.tree.ClassTree;
import com.sun.source.tree.LambdaExpressionTree;
import com.sun.source.tree.MethodInvocationTree;
import com.sun.source.tree.MethodTree;
import com.sun.source.tree.NewClassTree;
Expand All @@ -11,6 +13,7 @@
import java.util.Arrays;
import java.util.Collections;
import java.util.List;
import java.util.Queue;
import java.util.Set;
import javax.lang.model.element.AnnotationMirror;
import javax.lang.model.element.Element;
Expand Down Expand Up @@ -47,6 +50,7 @@
import org.checkerframework.dataflow.cfg.node.LocalVariableNode;
import org.checkerframework.dataflow.cfg.node.MethodInvocationNode;
import org.checkerframework.dataflow.cfg.node.Node;
import org.checkerframework.framework.flow.CFAbstractAnalysis.FieldInitialValue;
import org.checkerframework.framework.flow.CFStore;
import org.checkerframework.framework.source.SourceChecker;
import org.checkerframework.framework.type.AnnotatedTypeMirror;
Expand All @@ -56,6 +60,7 @@
import org.checkerframework.javacutil.ElementUtils;
import org.checkerframework.javacutil.TreeUtils;
import org.checkerframework.javacutil.TypeSystemError;
import org.plumelib.util.IPair;

/**
* The type factory for the RLCCalledMethodsChecker. The main difference between this and the Called
Expand Down Expand Up @@ -143,7 +148,39 @@ public AnnotationMirror createCalledMethods(String... val) {
}

@Override
public void postAnalyze(ControlFlowGraph cfg) {
protected ControlFlowGraph analyze(
Queue<IPair<ClassTree, @Nullable AccumulationStore>> classQueue,
Queue<IPair<LambdaExpressionTree, @Nullable AccumulationStore>> lambdaQueue,
UnderlyingAST ast,
List<FieldInitialValue<AccumulationValue>> fieldValues,
@Nullable ControlFlowGraph cfg,
boolean isInitializationCode,
boolean updateInitializationStore,
boolean isStatic,
@Nullable AccumulationStore capturedStore) {
// This is a workaround for a bug that I tried and failed to fix.
// See checker/tests/resourceleak/RLLambda.java.
// This code really belongs in postAnalyze, but this code only works correctly when called after
// a method is analyzed the first time and before any containing lambdas are analyzed.
// This workaround means there could be false positives when the type of a method invocation
// depends on dataflow in a lambda.

if (cfg != null) {
// The cfg is not null, so the analysis has been run before. Don't rerun it.
return cfg;
}
cfg =
super.analyze(
classQueue,
lambdaQueue,
ast,
fieldValues,
cfg,
isInitializationCode,
updateInitializationStore,
isStatic,
capturedStore);
assert root != null : "@AssumeAssertion(nullness): at this point root is always nonnull";
rlc.setRoot(root);
MustCallConsistencyAnalyzer mustCallConsistencyAnalyzer = new MustCallConsistencyAnalyzer(rlc);
mustCallConsistencyAnalyzer.analyze(cfg);
Expand All @@ -156,8 +193,8 @@ public void postAnalyze(ControlFlowGraph cfg) {
}
}

super.postAnalyze(cfg);
tempVarToTree.clear();
return cfg;
}

@Override
Expand Down
22 changes: 22 additions & 0 deletions checker/tests/nullness/Issue6629.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
package open.falsepos;

import java.util.stream.Collectors;
import java.util.stream.Stream;

public class Issue6629 {

void method(Stream<String> stream) {
stream
.map(
x -> {
Object o = new Object();
return new Other(o);
})
.collect(Collectors.toList());
}

static class Other {

public Other(Object o) {}
}
}
89 changes: 89 additions & 0 deletions checker/tests/nullness/flow/LambdaFlow.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,89 @@
package open;

import java.util.function.Function;
import org.checkerframework.checker.nullness.qual.NonNull;
import org.checkerframework.checker.nullness.qual.Nullable;

public class LambdaFlow {

void flowIntoLambda(@Nullable String param) {
if (param != null) {
Function<String, @NonNull String> b = s -> param;
}
}

void flowOutOfLambda(@Nullable String param) {
Function<String, @NonNull String> d =
s -> {
if (param != null) {
return param;
} else {
return "";
}
};
}

void flowOutOfLambda2(@Nullable String param) {
@NonNull String f =
foo(
s -> {
if (param != null) {
return param;
} else {
return "";
}
});
}

void flowIntoThenOutOfLambda(@Nullable String param) {
if (param != null) {
@NonNull String h = foo(s -> param);
}
}

// Same examples above but with a field instead of a parameter.

@Nullable String field;

void flowIntoLambdaField() {
if (field != null) {
Function<String, @NonNull String> a =
// :: error: (return)
s -> field;
}
}

void flowOutOfLambda() {
Function<String, @NonNull String> c =
s -> {
if (field != null) {
return field;
} else {
return "";
}
};
}

void flowOutOfLambda2() {
@NonNull String e =
foo(
s -> {
if (field != null) {
return field;
} else {
return "";
}
});
}

void flowIntoThenOutOfLambda() {
if (field != null) {
// :: error: (type.arguments.not.inferred) :: error: (assignment)
@NonNull String g = foo(s -> field);
}
}

<T> T foo(Function<String, T> func) {
return func.apply("");
}
}
59 changes: 59 additions & 0 deletions checker/tests/resourceleak/RLLambda.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.util.function.Function;
import java.util.function.Predicate;
import java.util.stream.Stream;
import org.checkerframework.checker.builder.qual.CalledMethods;
import org.checkerframework.checker.mustcall.qual.InheritableMustCall;
import org.checkerframework.checker.mustcall.qual.MustCall;

public class RLLambda {
@InheritableMustCall("a")
class Foo {
void a() {}

Foo b() {
return this;
}

void c(@CalledMethods("a") Foo this) {}
}

Foo makeFoo() {
return new Foo();
}

void innerfunc3() {

Foo f = makeFoo();
f.a();
Function<@MustCall Foo, @CalledMethods("a") @MustCall Foo> innerfunc =
st -> {
// :: error: (required.method.not.called)
Foo fn1 = new Foo();
Foo fn2 = makeFoo();
fn2.a();
// The need for this cast is undesirable, but is a consequence of our approach
// to generic types. In this case, this cast is clearly safe (a() has already
// been called, so the obligation is satisfied on the returned value, as
// intended).
// :: warning: cast.unsafe
return ((@MustCall Foo) fn2);
};

innerfunc.apply(f);
}

private void prepJdkFromFile(Path root) {
try (Stream<Path> walk = Files.walk(root)) {
Predicate<Path> pathPredicate = p -> false;
} catch (IOException e) {
throw new MyException("prepJdkFromFile", e);
}
}

public static class MyException extends RuntimeException {
public MyException(String s, Exception e) {}
}
}
Loading