Repository: uber/NullAway (Java)

Issue:
NullPointerException: no environment stored for lambda (from synchronized)
Repro:

```
class Foo {
    void foo() {
        Runnable runnable = () -> {
            Object lock = new Object();
            synchronized (lock) {}
        };
    }
}
```

Yields:
```
Foo.java:8: error: An unhandled exception was thrown by the Error Prone static analysis plugin.
                    synchronized (lock) {
                    ^
     Please report this at https://github.com/google/error-prone/issues/new and include the following:

     error-prone version: 2.37.0
     BugPattern: NullAway
     Stack Trace:
     com.google.common.util.concurrent.UncheckedExecutionException: java.lang.NullPointerException: no environment stored for lambda
  	at com.google.common.cache.LocalCache$Segment.get(LocalCache.java:2086)
  	at com.google.common.cache.LocalCache.get(LocalCache.java:4012)
  	at com.google.common.cache.LocalCache.getOrLoad(LocalCache.java:4035)
  	at com.google.common.cache.LocalCache$LocalLoadingCache.get(LocalCache.java:5011)
  	at com.google.common.cache.LocalCache$LocalLoadingCache.getUnchecked(LocalCache.java:5018)
  	at com.uber.nullaway.dataflow.DataFlow.dataflow(DataFlow.java:157)
  	at com.uber.nullaway.dataflow.DataFlow.resultFor(DataFlow.java:283)
  	at com.uber.nullaway.dataflow.DataFlow.resultForExpr(DataFlow.java:261)
  	at com.uber.nullaway.dataflow.DataFlow.expressionDataflow(DataFlow.java:207)
  	at com.uber.nullaway.dataflow.AccessPathNullnessAnalysis.getNullness(AccessPathNullnessAnalysis.java:131)
  	at com.uber.nullaway.NullAway.nullnessFromDataflow(NullAway.java:2645)
  	at com.uber.nullaway.NullAway.mayBeNullExpr(NullAway.java:2623)
  	at com.uber.nullaway.NullAway.matchSynchronized(NullAway.java:1788)
  	at com.google.errorprone.scanner.ErrorProneScanner.processMatchers(ErrorProneScanner.java:509)
  	at com.google.errorprone.scanner.ErrorProneScanner.visitSynchronized(ErrorProneScanner.java:955)
  	at com.google.errorprone.scanner.ErrorProneScanner.visitSynchronized(ErrorProneScanner.java:170)
  	at jdk.compiler/com.sun.tools.javac.tree.JCTree$JCSynchronized.accept(JCTree.java:1479)
  	at jdk.compiler/com.sun.source.util.TreePathScanner.scan(TreePathScanner.java:92)
  	at com.google.errorprone.scanner.Scanner.scan(Scanner.java:74)
  	at com.google.errorprone.scanner.Scanner.scan(Scanner.java:48)
  	at jdk.compiler/com.sun.source.util.TreeScanner.scanAndReduce(TreeScanner.java:95)
  	at jdk.compiler/com.sun.source.util.TreeScanner.scan(TreeScanner.java:110)
  	at jdk.compiler/com.sun.source.util.TreeScanner.visitBlock(TreeScanner.java:271)
  	at com.google.errorprone.scanner.ErrorProneScanner.visitBlock(ErrorProneScanner.java:591)
  	at com.google.errorprone.scanner.ErrorProneScanner.visitBlock(ErrorProneScanner.java:170)
  	at jdk.compiler/com.sun.tools.javac.tree.JCTree$JCBlock.accept(JCTree.java:1145)
  	at jdk.compiler/com.sun.source.util.TreePathScanner.scan(TreePathScanner.java:92)
  	at com.google.errorprone.scanner.Scanner.scan(Scanner.java:74)
  	at com.google.errorprone.scanner.Scanner.scan(Scanner.java:48)
  	at jdk.compiler/com.sun.source.util.TreeScanner.scanAndReduce(TreeScanner.java:95)
  	at jdk.compiler/com.sun.source.util.TreeScanner.visitLambdaExpression(TreeScanner.java:648)
  	at com.google.errorprone.scanner.ErrorProneScanner.visitLambdaExpression(ErrorProneScanner.java:780)
  	at com.google.errorprone.scanner.ErrorProneScanner.visitLambdaExpression(ErrorProneScanner.java:170)
  	at jdk.compiler/com.sun.tools.javac.tree.JCTree$JCLambda.accept(JCTree.java:2038)
  	at jdk.compiler/com.sun.source.util.TreePathScanner.scan(TreePathScanner.java:92)
  	at com.google.errorprone.scanner.Scanner.scan(Scanner.java:74)
  	at com.google.errorprone.scanner.Scanner.scan(Scanner.java:48)
  	at jdk.compiler/com.sun.source.util.TreeScanner.scanAndReduce(TreeScanner.java:95)
  	at jdk.compiler/com.sun.source.util.TreeScanner.visitVariable(TreeScanner.java:242)
  	at com.google.errorprone.scanner.ErrorProneScanner.visitVariable(ErrorProneScanner.java:1017)
  	at com.google.errorprone.scanner.ErrorProneScanner.visitVariable(ErrorProneScanner.java:170)
  	at jdk.compiler/com.sun.tools.javac.tree.JCTree$JCVariableDecl.accept(JCTree.java:1081)
  	at jdk.compiler/com.sun.source.util.TreePathScanner.scan(TreePathScanner.java:92)
  	at com.google.errorprone.scanner.Scanner.scan(Scanner.java:74)
  	at com.google.errorprone.scanner.Scanner.scan(Scanner.java:48)
  	at jdk.compiler/com.sun.source.util.TreeScanner.scan(TreeScanner.java:110)
  	at jdk.compiler/com.sun.source.util.TreeScanner.visitBlock(TreeScanner.java:271)
  	at com.google.errorprone.scanner.ErrorProneScanner.visitBlock(ErrorProneScanner.java:591)
  	at com.google.errorprone.scanner.ErrorProneScanner.visitBlock(ErrorProneScanner.java:170)
  	at jdk.compiler/com.sun.tools.javac.tree.JCTree$JCBlock.accept(JCTree.java:1145)
  	at jdk.compiler/com.sun.source.util.TreePathScanner.scan(TreePathScanner.java:92)
  	at com.google.errorprone.scanner.Scanner.scan(Scanner.java:74)
  	at com.google.errorprone.scanner.Scanner.scan(Scanner.java:48)
  	at jdk.compiler/com.sun.source.util.TreeScanner.scanAndReduce(TreeScanner.java:95)
  	at jdk.compiler/com.sun.source.util.TreeScanner.visitMethod(TreeScanner.java:223)
  	at com.google.errorprone.scanner.ErrorProneScanner.visitMethod(ErrorProneScanner.java:818)
  	at com.google.errorprone.scanner.ErrorProneScanner.visitMethod(ErrorProneScanner.java:170)
  	at jdk.compiler/com.sun.tools.javac.tree.JCTree$JCMethodDecl.accept(JCTree.java:989)
  	at jdk.compiler/com.sun.source.util.TreePathScanner.scan(TreePathScanner.java:92)
  	at com.google.errorprone.scanner.Scanner.scan(Scanner.java:74)
  	at com.google.errorprone.scanner.Scanner.scan(Scanner.java:48)
  	at jdk.compiler/com.sun.source.util.TreeScanner.scanAndReduce(TreeScanner.java:95)
  	at jdk.compiler/com.sun.source.util.TreeScanner.scan(TreeScanner.java:110)
  	at jdk.compiler/com.sun.source.util.TreeScanner.scanAndReduce(TreeScanner.java:118)
  	at jdk.compiler/com.sun.source.util.TreeScanner.visitClass(TreeScanner.java:202)
  	at com.google.errorprone.scanner.ErrorProneScanner.visitClass(ErrorProneScanner.java:619)
  	at com.google.errorprone.scanner.ErrorProneScanner.visitClass(ErrorProneScanner.java:170)
  	at jdk.compiler/com.sun.tools.javac.tree.JCTree$JCClassDecl.accept(JCTree.java:896)
  	at jdk.compiler/com.sun.source.util.TreePathScanner.scan(TreePathScanner.java:92)
  	at com.google.errorprone.scanner.Scanner.scan(Scanner.java:74)
  	at com.google.errorprone.scanner.Scanner.scan(Scanner.java:48)
  	at jdk.compiler/com.sun.source.util.TreeScanner.scan(TreeScanner.java:110)
  	at jdk.compiler/com.sun.source.util.TreeScanner.scanAndReduce(TreeScanner.java:118)
  	at jdk.compiler/com.sun.source.util.TreeScanner.visitCompilationUnit(TreeScanner.java:151)
  	at com.google.errorprone.scanner.ErrorProneScanner.visitCompilationUnit(ErrorProneScanner.java:631)
  	at com.google.errorprone.scanner.ErrorProneScanner.visitCompilationUnit(ErrorProneScanner.java:170)
  	at jdk.compiler/com.sun.tools.javac.tree.JCTree$JCCompilationUnit.accept(JCTree.java:625)
  	at jdk.compiler/com.sun.source.util.TreePathScanner.scan(TreePathScanner.java:66)
  	at com.google.errorprone.scanner.Scanner.scan(Scanner.java:58)
  	at com.google.errorprone.scanner.ErrorProneScannerTransformer.apply(ErrorProneScannerTransformer.java:43)
  	at com.google.errorprone.ErrorProneAnalyzer.finished(ErrorProneAnalyzer.java:231)
  	at jdk.compiler/com.sun.tools.javac.api.MultiTaskListener.finished(MultiTaskListener.java:133)
  	at jdk.compiler/com.sun.tools.javac.main.JavaCompiler.flow(JavaCompiler.java:1432)
  	at jdk.compiler/com.sun.tools.javac.main.JavaCompiler.flow(JavaCompiler.java:1379)
  	at jdk.compiler/com.sun.tools.javac.main.JavaCompiler.compile(JavaCompiler.java:964)
  	at jdk.compiler/com.sun.tools.javac.main.Main.compile(Main.java:319)
  	at jdk.compiler/com.sun.tools.javac.main.Main.compile(Main.java:178)
  	at jdk.compiler/com.sun.tools.javac.Main.compile(Main.java:66)
  	at jdk.compiler/com.sun.tools.javac.Main.main(Main.java:52)
  Caused by: java.lang.NullPointerException: no environment stored for lambda
  	at java.base/java.util.Objects.requireNonNull(Objects.java:246)
  	at com.uber.nullaway.dataflow.CoreNullnessStoreInitializer.lambdaInitialStore(CoreNullnessStoreInitializer.java:97)
  	at com.uber.nullaway.dataflow.CoreNullnessStoreInitializer.getInitialStore(CoreNullnessStoreInitializer.java:46)
  	at com.uber.nullaway.dataflow.AccessPathNullnessPropagation.initialStore(AccessPathNullnessPropagation.java:209)
  	at com.uber.nullaway.dataflow.AccessPathNullnessPropagation.initialStore(AccessPathNullnessPropagation.java:141)
  	at org.checkerframework.nullaway.dataflow.analysis.ForwardAnalysisImpl.initInitialInputs(ForwardAnalysisImpl.java:347)
  	at org.checkerframework.nullaway.dataflow.analysis.AbstractAnalysis.init(AbstractAnalysis.java:413)
  	at org.checkerframework.nullaway.dataflow.analysis.ForwardAnalysisImpl.performAnalysis(ForwardAnalysisImpl.java:102)
  	at com.uber.nullaway.dataflow.DataFlow$1.load(DataFlow.java:93)
  	at com.uber.nullaway.dataflow.DataFlow$1.load(DataFlow.java:85)
  	at com.google.common.cache.LocalCache$LoadingValueReference.loadFuture(LocalCache.java:3571)
  	at com.google.common.cache.LocalCache$Segment.loadSync(LocalCache.java:2313)
  	at com.google.common.cache.LocalCache$Segment.lockedGetOrLoad(LocalCache.java:2190)
  	at com.google.common.cache.LocalCache$Segment.get(LocalCache.java:2080)
  	... 88 more
```


Discussion: Note: Adding `@NullMarked` to the class fixes the issue.



Fix (patch):
diff --git a/nullaway/src/main/java/com/uber/nullaway/NullAway.java b/nullaway/src/main/java/com/uber/nullaway/NullAway.java
index f7a994fd60..51a1ea259f 100644
--- a/nullaway/src/main/java/com/uber/nullaway/NullAway.java
+++ b/nullaway/src/main/java/com/uber/nullaway/NullAway.java
@@ -1798,6 +1798,9 @@ public Description matchEnhancedForLoop(EnhancedForLoopTree tree, VisitorState s
 
   @Override
   public Description matchSynchronized(SynchronizedTree tree, VisitorState state) {
+    if (!withinAnnotatedCode(state)) {
+      return Description.NO_MATCH;
+    }
     ExpressionTree lockExpr = tree.getExpression();
     // For a synchronized block `synchronized (e) { ... }`, javac returns `(e)` as the expression.
     // We strip the outermost parentheses for a nicer-looking error message.