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

Errors running builder 'Java Builder' on project 'org.eclipse.tycho.core.shared'. #520

Closed
laeubi opened this issue Nov 8, 2022 · 14 comments · Fixed by #1236
Closed

Errors running builder 'Java Builder' on project 'org.eclipse.tycho.core.shared'. #520

laeubi opened this issue Nov 8, 2022 · 14 comments · Fixed by #1236

Comments

@laeubi
Copy link
Contributor

laeubi commented Nov 8, 2022

While refactoring i go the following error message:

java.lang.NullPointerException: Cannot invoke "org.eclipse.jdt.internal.compiler.lookup.TypeBinding.kind()" because "receiverType" is null
	at org.eclipse.jdt.internal.compiler.lookup.Scope.getMethod(Scope.java:3042)
	at org.eclipse.jdt.internal.compiler.ast.MessageSend.findMethodBinding(MessageSend.java:1020)
	at org.eclipse.jdt.internal.compiler.ast.MessageSend.resolveType(MessageSend.java:835)
	at org.eclipse.jdt.internal.compiler.ast.Expression.resolveTypeExpecting(Expression.java:1147)
	at org.eclipse.jdt.internal.compiler.ast.SwitchExpression.resolveTypeInternal(SwitchExpression.java:522)
	at org.eclipse.jdt.internal.compiler.ast.SwitchExpression.resolveType(SwitchExpression.java:459)
	at org.eclipse.jdt.internal.compiler.ast.ASTNode.resolvePolyExpressionArguments(ASTNode.java:763)
	at org.eclipse.jdt.internal.compiler.ast.MessageSend.findMethodBinding(MessageSend.java:1027)
	at org.eclipse.jdt.internal.compiler.ast.MessageSend.resolveType(MessageSend.java:835)
	at org.eclipse.jdt.internal.compiler.ast.Expression.resolve(Expression.java:1113)
	at org.eclipse.jdt.internal.compiler.ast.AbstractMethodDeclaration.resolveStatements(AbstractMethodDeclaration.java:662)
	at org.eclipse.jdt.internal.compiler.ast.MethodDeclaration.resolveStatements(MethodDeclaration.java:388)
	at org.eclipse.jdt.internal.compiler.ast.AbstractMethodDeclaration.resolve(AbstractMethodDeclaration.java:571)
	at org.eclipse.jdt.internal.compiler.ast.TypeDeclaration.resolve(TypeDeclaration.java:1503)
	at org.eclipse.jdt.internal.compiler.ast.TypeDeclaration.resolve(TypeDeclaration.java:1628)
	at org.eclipse.jdt.internal.compiler.ast.CompilationUnitDeclaration.resolve(CompilationUnitDeclaration.java:667)
	at org.eclipse.jdt.internal.compiler.Compiler.process(Compiler.java:905)
	at org.eclipse.jdt.internal.compiler.ProcessTaskManager.run(ProcessTaskManager.java:145)
	at java.base/java.lang.Thread.run(Thread.java:833)
@laeubi
Copy link
Contributor Author

laeubi commented Nov 8, 2022

If this happens once, Eclipse is effectively unusable and each action show the same error dialog again!

@iloveeclipse
Copy link
Member

The stack doesn't math master code. If you can reproduce, please attach stack trace from master build.

@laeubi
Copy link
Contributor Author

laeubi commented Nov 8, 2022

The stack is from Version: 2022-09 (4.25.0), when I restart and clean all projects the erros was gone.

@stephan-herrmann
Copy link
Contributor

Here's how I read the stack trace:

  • Scope.getMethod() is invoked with a null receiverType.
  • Within findMethodBinding() this.actualReceiverType is passed, so that field must be null
  • This in turn is called from resolve() within this code section:
		if (this.actualReceiverType == null) {
			return null;
		}
		// base type cannot receive any message
		if (this.actualReceiverType.isBaseType()) {
			scope.problemReporter().errorNoMethodFor(this, this.actualReceiverType, this.argumentTypes);
			return null;
		}
	}

	TypeBinding methodType = findMethodBinding(scope);

See the null-check just above?

There is a man behind the curtain: the last closing { was opened from

	if (this.constant != Constant.NotAConstant) {

This could indicate that resolve() was invoked on this MessageSend more than once, where the first invocation failed to set a proper actualReceiverType but did (as always) set constant = NotAConstant.

Generally, the JDT AST is not prepared for double resolving, so it would be interesting to understand what caused that repeated invocation of resolve() here.

@stephan-herrmann
Copy link
Contributor

Inspecting the very head of resolve() I'm reminded that two-part resolving is actually required in some type inference situations (where the first invocation answers a placeholder PolyTypeBinding.

@laeubi
Copy link
Contributor Author

laeubi commented Nov 9, 2022

@stephan-herrmann thanks for the analysis and insight, I can only remember that I moved a class from one project (that is the org.eclipse.tycho.core.shared) into another one and as this new one was really new this resulted in many build errors then because I need to add a the new dependency to the classpath first.

I think the error occurred right after the move finished, and then the error dialog popped up again, I restarted eclipse but problem persist and then was able to fix it by clean the projects, so it seems something was even persistently cached here.

@laeubi
Copy link
Contributor Author

laeubi commented Jan 12, 2023

It might because when Eclipse is running a build and inparallel a maven-build run on a commandline so could it be cause if a classfile is modified while JDT is compiling code?

Errors occurred during the build.
Errors running builder 'Java Builder' on project 'tycho-core'.
Cannot invoke "org.eclipse.jdt.internal.compiler.lookup.TypeBinding.kind()" because "receiverType" is null

@laeubi
Copy link
Contributor Author

laeubi commented Jul 14, 2023

This happens again (see eclipse-platform/eclipse.platform.ui#509 (comment)), this time I did nothing more than changing some things in Eclipse, an autobuild was running and in the meanwhile I triggered a mvn clean install on the command-line.

@stephan-herrmann
Copy link
Contributor

autobuild was running and in the meanwhile I triggered a mvn clean install on the command-line.

In my book this already classifies as asking for trouble.

Still for investigation in JDT we need steps for reproducing, really.

@stephan-herrmann
Copy link
Contributor

stephan-herrmann commented Jul 14, 2023

For good measure I had another look at possible code paths, with these conclusions:

  • Scope.getMethod() is called with receiverType == null
  • This is passed from MessageSend.findMethodBinding() using the field actualReceiverType
  • Flow comes from MessageSend.resolveType() just after the block if (this.constant != Constant.NotAConstant) {...
    • option 1: that code block was actually executed, but then this.actualReceiverType == null would have triggered early return null; WRONG
    • option 2: resolveType() is invoked multiple times, so this must be what happened
  • resolving the same message send more than once usually happens when
    • the message send is in a context that requires either overload resolution or type inference, AND
    • the first invocation did not provide a target type
    • the resolving produced some method binding, which then may have been wrapped in PolyParameterizedGenericMethodBinding
  • For the above I'm quite sure it's necessary that the first invocation of resolveType() did set a non-null #binding.
  • To find such method binding, actualReceiverType must have been a valid type.
  • These are the assignment to actualReceiverType:
    • first occurrence in MessageSend.resolveType(): if this sets null, than no #binding will be assigned, that's not what happened
    • the second occurrence in MessageSend.resolveType() pipes the declaringClass of a valid binding through getErasureCompatibleType() which will never return null, that's not what happened
    • outside completion & eval there's only one option left MessageSend.setActualReceiverType() which refuses to set null

At this level I "proved" that the stack trace in the original ticket description is "impossible".

I admit that one part was incomplete: what are the exact conditions for repeated invocation of MessageSend.resolveType()? Is it possible to decide that re-resolving is needed after the first invocation outright failed due to a missing actualReceiverType?

@stephan-herrmann
Copy link
Contributor

Wow, it's our lucky day:

public class X {
	void test(int i) {
		foo(switch (i) {
			case 0 -> m.call();
			default -> null;
		});
	}
	<T> void foo(T t) { }
}

Ergo: SwitchExpression is the "new" guy in the gang, that doesn't yet play by the rules.
Compiling the above produces:

java.lang.NullPointerException: Cannot invoke "org.eclipse.jdt.internal.compiler.lookup.TypeBinding.kind()" because "receiverType" is null
	at org.eclipse.jdt.internal.compiler.lookup.Scope.getMethod(Scope.java:3076)
	at org.eclipse.jdt.internal.compiler.ast.MessageSend.findMethodBinding(MessageSend.java:1020)
	at org.eclipse.jdt.internal.compiler.ast.MessageSend.resolveType(MessageSend.java:835)
	at org.eclipse.jdt.internal.compiler.ast.Expression.resolveTypeExpecting(Expression.java:1185)
	at org.eclipse.jdt.internal.compiler.ast.SwitchExpression.resolveTypeInternal(SwitchExpression.java:457)
	at org.eclipse.jdt.internal.compiler.ast.SwitchExpression.resolveType(SwitchExpression.java:395)
	at org.eclipse.jdt.internal.compiler.ast.ASTNode.resolvePolyExpressionArguments(ASTNode.java:777)
	at org.eclipse.jdt.internal.compiler.ast.MessageSend.findMethodBinding(MessageSend.java:1027)
	at org.eclipse.jdt.internal.compiler.ast.MessageSend.resolveType(MessageSend.java:835)
	at org.eclipse.jdt.internal.compiler.ast.Expression.resolve(Expression.java:1151)
	at org.eclipse.jdt.internal.compiler.ast.AbstractMethodDeclaration.resolveStatements(AbstractMethodDeclaration.java:662)
	at org.eclipse.jdt.internal.compiler.ast.MethodDeclaration.resolveStatements(MethodDeclaration.java:388)
	at org.eclipse.jdt.internal.compiler.ast.AbstractMethodDeclaration.resolve(AbstractMethodDeclaration.java:571)
	at org.eclipse.jdt.internal.compiler.ast.TypeDeclaration.resolve(TypeDeclaration.java:1508)
	at org.eclipse.jdt.internal.compiler.ast.TypeDeclaration.resolve(TypeDeclaration.java:1633)
	at org.eclipse.jdt.internal.compiler.ast.CompilationUnitDeclaration.resolve(CompilationUnitDeclaration.java:668)
	at org.eclipse.jdt.internal.compiler.Compiler.process(Compiler.java:905)

stephan-herrmann added a commit to stephan-herrmann/eclipse.jdt.core that referenced this issue Jul 14, 2023
@stephan-herrmann
Copy link
Contributor

Still for investigation in JDT we need steps for reproducing, really.

Obviously I spoiled my own appeal, but: (a) this was a very, very lucky shot, constructing the repro from a combination of reading that stack trace and reading lots of code - this only ever works once in a blue moon, and (b) providing the erroneous code right when it happened would have let us fix the bug last in 2022-12 already.

@stephan-herrmann
Copy link
Contributor

This happens again (see eclipse-platform/eclipse.platform.ui#509 (comment))

BTW, without a stacktrace from that occurrence we can't tell if that really was the same issue.

@laeubi
Copy link
Contributor Author

laeubi commented Jul 17, 2023

@stephan-herrmann thanks for finding this out, sadly in a larger project (like Tycho codebase) it is quite hard for a user without deeper knowledge to find out the root cause, especially when the problem seems to not always happen and the code compiles fine!

So I hope in such a case that at least the Stacktrace can give some idea and luckily it was the case here! Especially for NPE I think there is always at least the option to give a better error message.

robstryker pushed a commit to robstryker/eclipse.jdt.core that referenced this issue Jul 18, 2024
srikanth-sankaran added a commit to srikanth-sankaran/eclipse.jdt.core that referenced this issue Oct 31, 2024
srikanth-sankaran added a commit that referenced this issue Nov 1, 2024
 (#3208)

* Also back out its follow on bug fix #520 as it loses relevance
robstryker pushed a commit to robstryker/eclipse.jdt.core that referenced this issue Feb 6, 2025
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
3 participants