[Bug]: Type inference/applicability error for `Objects.requireNonNullElse(T,T)` with `T=Double` when first argument is `(condition ? null : primitive_double)`
Nobody has claimed this yet.
- Dominant language
- Java
- Stars
- 2k
- Forks
- 393
- Avg merge
- 11h 24m
- Merged PRs (30d)
- 36
Description
### Describe the bug
__Spoon Version(s):__
- `fr.inria.gforge.spoon:spoon-core:11.2.1-beta-13`
- Also reproduced with `fr.inria.gforge.spoon:spoon-core:11.2.1-beta-16`
__Java Version for Parsing:__
- Code being parsed is Java 17.
- Spoon `complianceLevel` is set to `17`.
- The Spoon launcher MRE was run using OpenJDK 21.
__Problem Description:__ Spoon fails to build a model when parsing a call to `java.util.Objects.requireNonNullElse(T, T)` under specific conditions related to its arguments when `T` is `Double`. The failure occurs when the Spoon environment is configured with `setComplianceLevel(17)` and `setNoClasspath(false)` (an explicit source classpath for the MRE's own compiled class is provided).
The error is:
```javascript
spoon.compiler.ModelBuildingException: The method requireNonNullElse(T, T) in the type Objects is not applicable for the arguments (Double, Double) at path/to/MinimalTest.java:XX
at spoon.support.compiler.jdt.JDTBasedSpoonCompiler.report(JDTBasedSpoonCompiler.java:664)
... (full stack trace) ...
```
This error specifically happens for the following pattern for the first argument: `(condition ? null : primitive_double_expression)` where `primitive_double_expression` results from a `.doubleValue()` call on a `Double` wrapper.
### Source code you are trying to analyze/transform
```Java
import java.util.Objects;
public class MinimalTest {
// This method reproduces the parsing failure
public void processFails(Double wrapperInput, Double defaultInput) {
// When wrapperInput is null, first arg to requireNonNullElse is 'null'.
// When wrapperInput is not null, first arg is 'wrapperInput.doubleValue()' (a primitive double).
Double result = Objects.requireNonNullElse(
(wrapperInput == null) ? null : wrapperInput.doubleValue(),
defaultInput
);
}
// For comparison, these variations parse successfully:
// Variation 1: Using the wrapper directly (no .doubleValue())
public void processWorks_WrapperDirectly(Double wrapperInput, Double defaultInput) {
Double result = Objects.requireNonNullElse(
(wrapperInput == null) ? null : wrapperInput, // No .doubleValue()
defaultInput
);
}
// Variation 2: Casting null to (Double)
public void processWorks_CastedNull(Double wrapperInput, Double defaultInput) {
Double result = Objects.requireNonNullElse(
(wrapperInput == null) ? (Double) null : wrapperInput.doubleValue(), // Explicit (Double)null
defaultInput
);
}
// Variation 3: Using a primitive double literal instead of null
public void processWorks_PrimitiveLiteralForNull(Double wrapperInput, Double defaultInput) {
Double result = Objects.requireNonNullElse(
(wrapperInput == null) ? 0.0 : wrapperInput.doubleValue(), // Using 0.0 instead of null
defaultInput
);
}
}
```
### Source code for your Spoon processing
```Java
// Main method to run the Spoon parsing test
public static void main(String[] args) {
// This part is for running the Spoon parser, not for running the logic itself
spoon.Launcher launcher = new spoon.Launcher();
launcher.addInputResource("app/src/test/java/club/cred/codelens/parser/services/MinimalTest.java"); // Adjust path
spoon.compiler.Environment env = launcher.getEnvironment();
env.setComplianceLevel(17); // Crucial
env.setNoClasspath(false); // Simulate compileMode=true
env.setIgnoreSyntaxErrors(true);
try {
System.out.println("Building Spoon model for MRE...");
launcher.buildModel();
System.out.println("Spoon model built successfully for MRE!");
} catch (Exception e) {
System.err.println("Spoon parsing failed for MRE:");
e.printStackTrace(); // This should show the "requireNonNullElse" error if reproduced
}
}
```
### Actual output
```Java
Building Spoon model for MRE...
Spoon parsing failed for MRE:
spoon.compiler.ModelBuildingException: The method requireNonNullElse(T, T) in the type Objects is not applicable for the arguments (Double, Double) at /Users/ganesh/workspace/codelens-java-parser/app/src/test/java/club/cred/codelens/parser/services/MinimalTest.java:11
at spoon.support.compiler.jdt.JDTBasedSpoonCompiler.report(JDTBasedSpoonCompiler.java:664)
at spoon.support.compiler.jdt.JDTBasedSpoonCompiler.reportProblems(JDTBasedSpoonCompiler.java:646)
at spoon.support.compiler.jdt.JDTBasedSpoonCompiler.build(JDTBasedSpoonCompiler.java:120)
at spoon.support.compiler.jdt.JDTBasedSpoonCompiler.build(JDTBasedSpoonCompiler.java:101)
at spoon.Launcher.buildModel(Launcher.java:781)
at club.cred.codelens.parser.services.MinimalTest.main(MinimalTest.java:55)
```
### Expected output
```Java
Building Spoon model for MRE...
Spoon model built successfully for MRE!
```
### Spoon Version
11.2.1-beta-13, 11.2.1-beta-16
### JVM Version
openjdk 17.0.10
### What operating system are you using?
Mac OSx
Contributor guide
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
Research direction
Start by running the MinimalTest.java reproducer through spoon.Launcher.buildModel with compliance level 17 and no-classpath disabled. Inspect the JDTBasedSpoonCompiler reporting path and compare the failing requireNonNullElse call with the three successful variations; done means the original source builds a Spoon model without the applicability error.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- java
- Domain
- compilers
- Issue type
- Bug
- Difficulty
- 4/5
- Estimated time
- 3-5 days
- Activity status
- Stale
- Clarity
- Clearly specified
- Newbie friendliness
- 45/100