Community
Participate
Working Groups
Created attachment 251154 [details] 2 test projects We're seeing a strange ping-pong effect when trying to compile master of org.eclipse.releng.tools and org.eclipse.jgit. On every second incremental compilation, we see this error in org.eclipse.releng.tools.git.GitCopyrightAdapter: "The type java.lang.AutoCloseable cannot be resolved. It is indirectly referenced from required .class files" The attached self-contained projects reproduce the problem (needs a 1.5 and a 1.7 Installed JRE). Just open GitCopyrightAdapter, add a space, and save. Hint: It's easier to debug without a reconciler thread: Use Open With > Text Editor. In this code path, we get the IProblem#IsClassPathCorrect as expected: at org.eclipse.jdt.internal.compiler.lookup.UnresolvedReferenceBinding.resolve(UnresolvedReferenceBinding.java:104) at org.eclipse.jdt.internal.compiler.lookup.BinaryTypeBinding.resolveType(BinaryTypeBinding.java:187) at org.eclipse.jdt.internal.compiler.lookup.BinaryTypeBinding.superInterfaces(BinaryTypeBinding.java:1805) at org.eclipse.jdt.internal.compiler.lookup.Scope.findMethodInSuperInterfaces(Scope.java:1834) at org.eclipse.jdt.internal.compiler.lookup.Scope.findDefaultAbstractMethod(Scope.java:1113) at org.eclipse.jdt.internal.compiler.lookup.Scope.findMethod0(Scope.java:1630) at org.eclipse.jdt.internal.compiler.lookup.Scope.findMethod(Scope.java:1525) at org.eclipse.jdt.internal.compiler.lookup.Scope.getMethod(Scope.java:2800) at org.eclipse.jdt.internal.compiler.ast.MessageSend.findMethodBinding(MessageSend.java:890) at org.eclipse.jdt.internal.compiler.ast.MessageSend.resolveType(MessageSend.java:704) at org.eclipse.jdt.internal.compiler.ast.Expression.resolve(Expression.java:1020) at org.eclipse.jdt.internal.compiler.ast.AbstractMethodDeclaration.resolveStatements(AbstractMethodDeclaration.java:638) at org.eclipse.jdt.internal.compiler.ast.MethodDeclaration.resolveStatements(MethodDeclaration.java:307) at org.eclipse.jdt.internal.compiler.ast.AbstractMethodDeclaration.resolve(AbstractMethodDeclaration.java:548) at org.eclipse.jdt.internal.compiler.ast.TypeDeclaration.resolve(TypeDeclaration.java:1188) at org.eclipse.jdt.internal.compiler.ast.TypeDeclaration.resolve(TypeDeclaration.java:1301) at org.eclipse.jdt.internal.compiler.ast.CompilationUnitDeclaration.resolve(CompilationUnitDeclaration.java:590) at org.eclipse.jdt.internal.compiler.Compiler.process(Compiler.java:803) at org.eclipse.jdt.internal.compiler.ProcessTaskManager.run(ProcessTaskManager.java:141) at java.lang.Thread.run(Thread.java:745) In the next incremental compile pass, the builder decides to build the Messages class as well. That already looks wrong to me. But as a side effect, this computes the supertypes of type String. In MethodScope(Scope).findExactMethod(ReferenceBinding, char[], TypeBinding[], InvocationSite) line: 1215, the code reads: if (isPossibleSubtypeOfRawType(argumentTypes[i])) return null; In the case where the Messages class has not been compiled before, the isPossibleSubtypeOfRawType(..) call returns true for argumentType=String (because the supertypes of String have not been resolved yet). As a consequence, Scope#findExactMethod(..) return null, and the findMethod0(..) shown above eventually resolves the type Repository and reports the missing supertype AutoCloseable. In the other case, where the compilation of class Messages already resolved the supertypes of String, the isPossibleSubtypeOfRawType(..) call returns false, and the findExactMethod(..) call returns the "resolve" method binding without ever checking the supertypes of type Repository. => Error is not reported in this case. Two questions to investigate: 1. Why does incremental compilation compile class Messages again? Is it because the previous compilation aborted due to an incomplete build path, so the next build will be a full build? 2. Why does findMethod0(..) resolve the receiver type and report errors, but findExactMethod(..) sometimes returns without ever having resolved the receiver type? If the error is worth reporting at all, then it should be reported all the time.
(In reply to Markus Keller from comment #0) > Two questions to investigate: Thanks for the detailed report, Markus! > 1. Why does incremental compilation compile class Messages again? Is it > because the previous compilation aborted due to an incomplete build path, so > the next build will be a full build? Yep, This line in IncrementalImageBuilder (line: 84) adds all source files in the affected project when a build error was previously reported: if (this.javaBuilder.hasBuildpathErrors()) { .... > 2. Why does findMethod0(..) resolve the receiver type and report errors, but > findExactMethod(..) sometimes returns without ever having resolved the > receiver type? If the error is worth reporting at all, then it should be > reported all the time. This looks like a problem and needs closer look.
Created attachment 251165 [details] 2 test projects v2 I was a bit too eager stripping out unnecessary files, and I accidentally removed the .settings that set the compiler compliance. Here's a version that is even easier to debug, since it avoids the MessageSend in Messages.java, and it includes the launch config I used to verify that javac doesn't have this problem.
New Gerrit change created: https://git.eclipse.org/r/42893
This could be easier to fix than I initially thought. Bug 360164 laid all the ground work to fix such problems. I think this is just an oversight where the "this.environment.mayTolerateMissingType = true;" range was chosen a bit too narrow. BinaryTypeBinding#superclass() probably has the same problem -- it also calls "resolveType(..)" outside of the "mayTolerate" block.
Thanks Markus, for taking this up!
Looked too easy... Gerrit reports two failures for tests that have been added for bug 164622: MultiProjectTests.test102_missing_required_binaries MultiProjectTests.test103_missing_required_binaries I think I investigated into the wrong direction. For javac 1.7, the interface AutoCloseable seems to be a very special beast that is also supported in cross-compilation mode [1], although it really shouldn't be. When I change class org.eclipse.jgit.lib.Repository in the example projects to implement java.nio.file.CopyOption or java.nio.file.WatchKey, and then compile the 1.5 project org.eclipse.releng.tools with: javac -source 1.5 -target 1.5 -bootclasspath C:\java\jdk5\jre\lib\rt.jar -sourcepath src -d classes -classpath ..\org.eclipse.jgit\bin src\org\eclipse\releng\tools\git\* .. then I get a compile error form javac as well: javac 1.7.0_76 src\org\eclipse\releng\tools\git\GitCopyrightAdapter.java:8: error: cannot access CopyOption repo.resolve("Head"); ^ class file for java.nio.file.CopyOption not found 1 error => I now think the compile error is actually correct, and we have to make sure that findExactMethod(..) doesn't take the shortcut that avoids resolving the supertypes of the receiver.
Some other bugs that always crop up when I look at this code: Bug 164622, bug 275471, bug 206930, bug 269883, bug 360164. It looks like we don't have crystal clear rules as to when supertypes of a binary type need to be resolved and when problems in there can be tolerated. This bug goes away when I revert bug 275471, i.e. when I comment out this line in Scope#isPossibleSubtypeOfRawType(TypeBinding), which effectively removes the "Possible" in the method's name: if (!currentType.isHierarchyConnected()) return true; // do not fault in super types right now, so assume one is a raw type Then, the "repo.resolve("Head");" call consistently compiles without error. Which makes sense, since the supertypes of type Repository can't influence the validity of the method call at hand. I'm inclined to just revert the fix for bug 275471. That looks like a hack and the bug's comments don't justify why this should be correct. I think the fix for bug 360164 actually fixes the problem from bug 275471. I'll prepare another Gerrit review for that.
(In reply to Markus Keller from comment #6) > I think I investigated into the wrong direction. For javac 1.7, the > interface AutoCloseable seems to be a very special beast Right. You probably saw that the fix in bug 360164 specifically protects the code newly introduced via bug 349326, which eagerly searches for AutoCloseable or Closeable in the ancestry. Later BitUninternedType joined the party. > that is also > supported in cross-compilation mode [1], although it really shouldn't be. If you refer to the mix of 1.5 and 1.7 projects: your observation is true only for AutoCloseable, the other two should be detected also at 1.5.
OK, I've written a test that fails against master and passes when I remove the hack for bug 275471: https://git.eclipse.org/r/#/c/42893/2 I'll release this if Gerrit reports green tests. With this change, ECJ behaves the same as javac for the very specific example from comment 0 (with AutoCloseable as supertype of Repository). For other supertypes, javac reports an error, but ECJ won't (to keep cases like bug 360164 working).
For patch set 2, Gerrit reports that MethodVerifyTest#test124() fails for 1.5 and 1.6, but NOT for 1.7 and 1.8. This looked fishy again, and indeed I can construct an example where the compiler is definitely wrong even without my change. Just add another file "A.java" to the test, so that the hierarchy of "String" already gets "connected" when A.java is compiled: public void test124b() { this.runConformTest( new String[] { "A.java", "class A {\n" + " public Object o = \"\";\n" + "}\n", "X.java", ... In 1.5 and 1.6 compliance mode, this makes the test fail because it produces compile errors. (In 1.7 and 1.8 the test passes compilation and fails in the execution phase because it tries to run the wrong CU -- but that doesn't invalidate my argument about the wrong compilation.) I'm a bit lost here. I still think that the "isHierarchyConnected()" call is wrong, but OTOH, I don't know how to fix this new problem.
There's no way around removing the wrong isHierarchyConnected() call. But I think a good way to keep the hacks in Scope#computeCompatibleMethod(..) for bug 207935 happy is to make sure Scope#getMethod(TypeBinding, char[], TypeBinding[], InvocationSite) doesn't return a ProblemMethodBinding from findExactMethod(..), but instead tries harder via #findMethod(..). See patch set 3.
Gerrit change https://git.eclipse.org/r/42893 was merged to [master]. Commit: http://git.eclipse.org/c/jdt/eclipse.jdt.core.git/commit/?id=ae91e57f9e527d38f1a28381db960edf808acef4
.
Verified for 4.5 M6 using I20150316-2000 build