| Summary: | Compiler does not report type mismatch error when null is returned via ternary operator | ||
|---|---|---|---|
| Product: | [Eclipse Project] JDT | Reporter: | Hansjoerg Haberlander <Hansjoerg.Haberlander> |
| Component: | Core | Assignee: | Stephan Herrmann <stephan.herrmann> |
| Status: | VERIFIED INVALID | QA Contact: | |
| Severity: | major | ||
| Priority: | P3 | CC: | daniel_megert, fbricon, jarthana, stephan.herrmann |
| Version: | 3.1 | ||
| Target Milestone: | 4.8 M6 | ||
| Hardware: | All | ||
| OS: | All | ||
| Whiteboard: | |||
Broken since 1.5 was introduced. I get a warning "Potential null pointer access: This expression of type Integer may be null but requires auto-unboxing", so this might be by design. (In reply to Timo Kinnunen from comment #2) > I get a warning "Potential null pointer access: This expression of type > Integer may be null but requires auto-unboxing", so this might be by design. No, you don't out of the box. That's true, I have almost every warning turned on. I didn't mean to imply that that warning would be emitted by default. Note that ternary expressions have different typing rules than the otherwise equivalent if-then-else structure. JLS 15.25 does allow various adaptations to make the 2nd and 3rd operands compatible, including boxing. So the compiler currently seems to infer the common type of "null" and "0" to be "Integer". In fact the resulting code should be fully functional :) The warning "Potential null pointer access.." results from unboxing this Integer to yield the required int. But this happens *after* Integer has already been determined as the accepted type. At a closer look, however, I read the JLS to only allow int & Integer -> Integer (bullet 2) Integer & null -> Integer (bullet 3) but not int & null So, yes, we should report an error. Same issue reported through vscode-java (which uses jdt.ls, hence jdt, under the hood) https://github.com/redhat-developer/vscode-java/issues/436 Some archeology: When compiling the examples from comment 0 with javac, all versions complain about 'typeMismatch' and no version in [1.5,9] complains about 'noTypeMismatch'. Not sure if this was the intended behavior all the time, but this well corresponds to what ecj is answering. Checking the third guy in the game, JLS: Up-to JLS7 we indeed see the bullet list cited in comment 5, which led me to conclude we should report an error. Now for the big surprise, in JLS8 section 15.25 has been re-written to contain an explicit table of what's supported and what is not. In table 15.25-A [1] we do find a cell for 2nd operand null and 3rd operand int. Similarly in table 15.25-E for the inverse pair of int and null. => Ergo, JLS8 made legal what compilers have been accepting all along. => Ergo, nothing to fix. [1] https://docs.oracle.com/javase/specs/jls/se9/html/jls-15.html#jls-15.25-400-A Regardless of what the spec says, that ternary expression is still potentially harmful, and I think it deserves at least a warning, how else can we prevent users from doing stupid stuff? Can something be done above the compiler layer? (In reply to Fred Bricon from comment #8) > Regardless of what the spec says, that ternary expression is still > potentially harmful, and I think it deserves at least a warning, how else > can we prevent users from doing stupid stuff? > Can something be done above the compiler layer? We already do, see comment 2. (You have to enable that warning, though). The "potential null pointer access" is shown as per Hansjoerg' snippet
public int problemDetected() {
return someBoolean ? null : 0;
}
but not if you don't return immediately:
public int noProblemDetected() {
int i = someBoolean ? null : 0;//no warning/error
return i;
}
(In reply to Fred Bricon from comment #10) > The "potential null pointer access" is shown as per Hansjoerg' snippet > > public int problemDetected() { > return someBoolean ? null : 0; > } > > but not if you don't return immediately: > > public int noProblemDetected() { > int i = someBoolean ? null : 0;//no warning/error > return i; > } Thanks, that looks like a bug to me. I filed bug 531073. Verified for 4.8 M6 |
Type mismatch error is not annotated in code when using the ternary operator: public int noTypeMismatch() { return someBoolean ? null : 0; // no type mismatch error } Using regular if shows the annotation: public int typeMismatch() { if (someBoolean) { return null; // type mismatch error } else { return 0; } }