Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

RestrictedApiChecker: java.util.NoSuchElementException at com.sun.tools.javac.code.Scope$ScopeImpl$1.next(Scope.java:592) #2099

Closed
lgemeinhardt opened this issue Jan 13, 2021 · 3 comments · Fixed by #2116

Comments

@lgemeinhardt
Copy link

Description of the problem / feature request:

After upgrading errorprone from 2.4.0 to 2.5.0 following is reported using ant build (with JDK8):

[javac] src\test\java\com\foo\FooTest.java:32: error: An unhandled exception was thrown by the Error Prone static analysis plugin.
[javac] 		final Loo helper = this.foo.new Loo() { // works if inner class is static and this.foo could be removed
[javac] 		                            ^
[javac]      Please report this at https://github.com/google/error-prone/issues/new and include the following:
[javac]   
[javac]      error-prone version: 2.5.0
[javac]      BugPattern: RestrictedApiChecker
[javac]      Stack Trace:
[javac]      java.util.NoSuchElementException
[javac]   	at com.sun.tools.javac.code.Scope$ScopeImpl$1.next(Scope.java:592)
[javac]   	at com.sun.tools.javac.code.Scope$ScopeImpl$1.next(Scope.java:572)
[javac]   	at com.google.common.collect.Iterators.getOnlyElement(Iterators.java:301)
[javac]   	at com.google.common.collect.Iterables.getOnlyElement(Iterables.java:254)
[javac]   	at com.google.errorprone.bugpatterns.RestrictedApiChecker.superclassConstructorSymbol(RestrictedApiChecker.java:131)
[javac]   	at com.google.errorprone.bugpatterns.RestrictedApiChecker.matchNewClass(RestrictedApiChecker.java:145)
[javac]   	at com.google.errorprone.scanner.ErrorProneScanner.processMatchers(ErrorProneScanner.java:450)
[javac]   	at com.google.errorprone.scanner.ErrorProneScanner.visitNewClass(ErrorProneScanner.java:774)
[javac]   	at com.google.errorprone.scanner.ErrorProneScanner.visitNewClass(ErrorProneScanner.java:151)
[javac]   	at com.sun.tools.javac.tree.JCTree$JCNewClass.accept(JCTree.java:1705)
[javac]   	at com.sun.source.util.TreePathScanner.scan(TreePathScanner.java:82)
[javac]   	at com.google.errorprone.scanner.Scanner.scan(Scanner.java:74)
[javac]   	at com.google.errorprone.scanner.Scanner.scan(Scanner.java:48)
[javac]   	at com.sun.source.util.TreeScanner.scanAndReduce(TreeScanner.java:90)
[javac]   	at com.sun.source.util.TreeScanner.visitVariable(TreeScanner.java:223)
[javac]   	at com.google.errorprone.scanner.ErrorProneScanner.visitVariable(ErrorProneScanner.java:886)
[javac]   	at com.google.errorprone.scanner.ErrorProneScanner.visitVariable(ErrorProneScanner.java:151)
[javac]   	at com.sun.tools.javac.tree.JCTree$JCVariableDecl.accept(JCTree.java:968)
[javac]   	at com.sun.source.util.TreePathScanner.scan(TreePathScanner.java:82)
[javac]   	at com.google.errorprone.scanner.Scanner.scan(Scanner.java:74)
[javac]   	at com.google.errorprone.scanner.Scanner.scan(Scanner.java:48)
[javac]   	at com.sun.source.util.TreeScanner.scan(TreeScanner.java:105)
[javac]   	at com.sun.source.util.TreeScanner.visitBlock(TreeScanner.java:248)
[javac]   	at com.google.errorprone.scanner.ErrorProneScanner.visitBlock(ErrorProneScanner.java:521)
[javac]   	at com.google.errorprone.scanner.ErrorProneScanner.visitBlock(ErrorProneScanner.java:151)
[javac]   	at com.sun.tools.javac.tree.JCTree$JCBlock.accept(JCTree.java:1026)
[javac]   	at com.sun.source.util.TreePathScanner.scan(TreePathScanner.java:82)
[javac]   	at com.google.errorprone.scanner.Scanner.scan(Scanner.java:74)
[javac]   	at com.google.errorprone.scanner.Scanner.scan(Scanner.java:48)
[javac]   	at com.sun.source.util.TreeScanner.scanAndReduce(TreeScanner.java:90)
[javac]   	at com.sun.source.util.TreeScanner.visitMethod(TreeScanner.java:206)
[javac]   	at com.google.errorprone.scanner.ErrorProneScanner.visitMethod(ErrorProneScanner.java:741)
[javac]   	at com.google.errorprone.scanner.ErrorProneScanner.visitMethod(ErrorProneScanner.java:151)
[javac]   	at com.sun.tools.javac.tree.JCTree$JCMethodDecl.accept(JCTree.java:898)
[javac]   	at com.sun.source.util.TreePathScanner.scan(TreePathScanner.java:82)
[javac]   	at com.google.errorprone.scanner.Scanner.scan(Scanner.java:74)
[javac]   	at com.google.errorprone.scanner.Scanner.scan(Scanner.java:48)
[javac]   	at com.sun.source.util.TreeScanner.scanAndReduce(TreeScanner.java:90)
[javac]   	at com.sun.source.util.TreeScanner.scan(TreeScanner.java:105)
[javac]   	at com.sun.source.util.TreeScanner.scanAndReduce(TreeScanner.java:113)
[javac]   	at com.sun.source.util.TreeScanner.visitClass(TreeScanner.java:187)
[javac]   	at com.google.errorprone.scanner.ErrorProneScanner.visitClass(ErrorProneScanner.java:549)
[javac]   	at com.google.errorprone.scanner.ErrorProneScanner.visitClass(ErrorProneScanner.java:151)
[javac]   	at com.sun.tools.javac.tree.JCTree$JCClassDecl.accept(JCTree.java:808)
[javac]   	at com.sun.source.util.TreePathScanner.scan(TreePathScanner.java:82)
[javac]   	at com.google.errorprone.scanner.Scanner.scan(Scanner.java:74)
[javac]   	at com.google.errorprone.scanner.Scanner.scan(Scanner.java:48)
[javac]   	at com.sun.source.util.TreeScanner.scan(TreeScanner.java:105)
[javac]   	at com.sun.source.util.TreeScanner.scanAndReduce(TreeScanner.java:113)
[javac]   	at com.sun.source.util.TreeScanner.visitCompilationUnit(TreeScanner.java:144)
[javac]   	at com.google.errorprone.scanner.ErrorProneScanner.visitCompilationUnit(ErrorProneScanner.java:561)
[javac]   	at com.google.errorprone.scanner.ErrorProneScanner.visitCompilationUnit(ErrorProneScanner.java:151)
[javac]   	at com.sun.tools.javac.tree.JCTree$JCCompilationUnit.accept(JCTree.java:591)
[javac]   	at com.sun.source.util.TreePathScanner.scan(TreePathScanner.java:56)
[javac]   	at com.google.errorprone.scanner.Scanner.scan(Scanner.java:58)
[javac]   	at com.google.errorprone.scanner.ErrorProneScannerTransformer.apply(ErrorProneScannerTransformer.java:43)
[javac]   	at com.google.errorprone.ErrorProneAnalyzer.finished(ErrorProneAnalyzer.java:152)
[javac]   	at com.sun.tools.javac.api.MultiTaskListener.finished(MultiTaskListener.java:120)
[javac]   	at com.sun.tools.javac.main.JavaCompiler.flow(JavaCompiler.java:1404)
[javac]   	at com.sun.tools.javac.main.JavaCompiler.flow(JavaCompiler.java:1353)
[javac]   	at com.sun.tools.javac.main.JavaCompiler.compile(JavaCompiler.java:946)
[javac]   	at com.sun.tools.javac.main.Main.compile(Main.java:302)
[javac]   	at com.sun.tools.javac.main.Main.compile(Main.java:162)
[javac]   	at com.sun.tools.javac.Main.compile(Main.java:57)
[javac]   	at com.sun.tools.javac.Main.main(Main.java:43)
[javac] 1 error

Bugs: what's the simplest, easiest way to reproduce this bug? Please provide a minimal example if possible.

package com.foo;

import static org.assertj.core.api.Assertions.assertThat;

import java.util.HashSet;
import java.util.Set;

import org.junit.Test;

import com.google.common.collect.ImmutableSet;
import com.foo.FooTest.Foo.Loo;

public class FooTest {

	static class Foo {

		private boolean outer;

		class Loo { // class is non-static to show the issue

			protected Set<Integer> getGoo() {
				return Foo.this.outer ? ImmutableSet.of() : new HashSet<>(); // outer reference to avoid static
			}
		}

	}

	private final Foo foo = new Foo();

	@Test
	public void testFoo() {
		final Loo helper = this.foo.new Loo() { // works if inner class is static and this.foo could be removed

			@Override
			protected Set<Integer> getGoo() {
				return ImmutableSet.of();
			}
		};
		assertThat(this.foo).isNotNull();
		assertThat(helper).isNotNull();
	}

}

This sample code is simplified and the non-static inner class raises the issue!

What version of Error Prone are you using?

2.5.0

@cushon
Copy link
Collaborator

cushon commented Jan 14, 2021

Thanks for the report and the repro! I can observe the same crash with this smaller example:

package t;

class T {

  static class Foo {
    class Loo {}
  }

  public void testFoo(Foo foo) {
    foo.new Loo() {};
  }
}
$ javac -J-Xbootclasspath/p:javac-9+181-r4173-1.jar \
  -XDcompilePolicy=simple \
  -processorpath error_prone_core-2.5.0-with-dependencies.jar:dataflow-2.5.7.jar:javacutil-2.5.7.jar:jFormatString-3.0.0.jar \
  '-Xplugin:ErrorProne -Xep:HidingField:OFF' \
  T.java
...
T.java:10: error: An unhandled exception was thrown by the Error Prone static analysis plugin.
    foo.new Loo() {};
        ^
     Please report this at https://github.com/google/error-prone/issues/new and include the following:

     error-prone version: 2.5.0
     BugPattern: RestrictedApiChecker
     Stack Trace:
     java.util.NoSuchElementException
  	at com.sun.tools.javac.code.Scope$ScopeImpl$1.next(Scope.java:592)
  	at com.sun.tools.javac.code.Scope$ScopeImpl$1.next(Scope.java:572)
  	at com.google.common.collect.Iterators.getOnlyElement(Iterators.java:301)  

@cushon
Copy link
Collaborator

cushon commented Jan 14, 2021

It looks like the AST for foo.new Loo() {}; is different in JDK 8 and 9, in 8 it might be getting desugared earlier than it should be. That is breaking this assumption:

@cushon
Copy link
Collaborator

cushon commented Jan 15, 2021

I found the change between 8 and 9 that's causing this:

copybara-service bot pushed a commit that referenced this issue Jan 15, 2021
to avoid preventing workarounds for crashes like
#2099

PiperOrigin-RevId: 351906045
copybara-service bot pushed a commit that referenced this issue Jan 15, 2021
to avoid preventing workarounds for crashes like
#2099

PiperOrigin-RevId: 351906045
copybara-service bot pushed a commit that referenced this issue Jan 15, 2021
to avoid preventing workarounds for crashes like
#2099

PiperOrigin-RevId: 351906045
copybara-service bot pushed a commit that referenced this issue Jan 15, 2021
to avoid preventing workarounds for crashes like
#2099

PiperOrigin-RevId: 351906045
copybara-service bot pushed a commit that referenced this issue Jan 15, 2021
`NewClassTree.getEnclosingInstance` doesn't work in JDK 8, because it gets
desugared in an early pass before Error Prone runs. This change adds a
workaround that detects `NewClassTree` by looking at the synthetic parameter
added by the desugaring pass instead of using `getEnclosingInstance`.

Fixes #2099

PiperOrigin-RevId: 351909719
copybara-service bot pushed a commit that referenced this issue Jan 15, 2021
to avoid preventing workarounds for crashes like
#2099

PiperOrigin-RevId: 351919242
copybara-service bot pushed a commit that referenced this issue Jan 15, 2021
`NewClassTree.getEnclosingInstance` doesn't work in JDK 8, because it gets
desugared in an early pass before Error Prone runs. This change adds a
workaround that detects `NewClassTree` by looking at the synthetic parameter
added by the desugaring pass instead of using `getEnclosingInstance`.

Fixes #2099

PiperOrigin-RevId: 351909719
copybara-service bot pushed a commit that referenced this issue Jan 15, 2021
`NewClassTree.getEnclosingInstance` doesn't work in JDK 8, because it gets
desugared in an early pass before Error Prone runs. This change adds a
workaround that detects `NewClassTree` by looking at the synthetic parameter
added by the desugaring pass instead of using `getEnclosingInstance`.

Fixes #2099

PiperOrigin-RevId: 351909719
stevie400 pushed a commit to HubSpot/error-prone that referenced this issue Jan 15, 2021
to avoid preventing workarounds for crashes like
google#2099

PiperOrigin-RevId: 351919242
stevie400 pushed a commit to HubSpot/error-prone that referenced this issue Jan 15, 2021
`NewClassTree.getEnclosingInstance` doesn't work in JDK 8, because it gets
desugared in an early pass before Error Prone runs. This change adds a
workaround that detects `NewClassTree` by looking at the synthetic parameter
added by the desugaring pass instead of using `getEnclosingInstance`.

Fixes google#2099

PiperOrigin-RevId: 351921606
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging a pull request may close this issue.

2 participants