JSpecify: a `var` initialized with a conditional expression gets no @Nullable type argument from diamond or generic method inference
Maintainers usually reply within 1 day
Nobody has claimed this yet.
Assessment
- Difficulty
- 3/5
- Estimated time
- 1-2 days
- Newbie friendliness
- 75/100
Research direction
Start with the TODO in ConditionalExprTests.varConditionalDoesNotProvideTargetTypeForGenericMethodInference and compare the existing tests for direct var inference and conditional expressions. Add regression cases for the Box diamond expression and generic box call, expecting nullable dereference diagnostics for both. Run the relevant ConditionalExprTests tests; done means both conditional cases report the expected diagnostics.
Written by the indexing model from the issue text.
Description
In JSpecify mode, var cond = flag ? new Box<>(null) : new Box<>("fallback"); gets a non-null type argument, so cond.get().hashCode() is not reported. Without the conditional, var d = new Box<>(null); is inferred as Box<@Nullable Object> (since #1708, v0.14.0) and d.get().hashCode() is reported. A generic method call behaves the same way: var d2 = box(null); is reported on dereference, var cond2 = flag ? box(null) : box("fallback"); is not.
This is the case left over from #1633: the TODO in ConditionalExprTests.varConditionalDoesNotProvideTargetTypeForGenericMethodInference still links #1633, which is otherwise fixed.
Version: NullAway master at 3035507e1 (after 0.14.2), JDK 21.0.9.
Flags: -XepOpt:NullAway:AnnotatedPackages=com.uber -XepOpt:NullAway:JSpecifyMode=true -XDaddTypeAnnotationsToSymbol=true -XepOpt:NullAway:JSpecifyExperimental=true
import org.jspecify.annotations.*;
@NullMarked
public class Test {
static class Box<T extends @Nullable Object> {
private final T value;
Box(T value) { this.value = value; }
T get() { return value; }
}
interface Box2<T extends @Nullable Object> { T get(); }
static <T extends @Nullable Object> Box2<T> box(T t) { throw new RuntimeException(); }
void test(boolean flag) {
var cond = flag ? new Box<>(null) : new Box<>("fallback");
cond.get().hashCode(); // expected: dereferenced expression is @Nullable
var cond2 = flag ? box(null) : box("fallback");
cond2.get().hashCode(); // expected: dereferenced expression is @Nullable
}
}
Observed: no diagnostic on either dereference (a CompilationTestHelper test with this source and no // BUG: lines passes).
Expected: dereferenced expression cond.get() is @Nullable and dereferenced expression cond2.get() is @Nullable, the same diagnostic NullAway reports for the direct forms var d = new Box<>(null); d.get().hashCode(); and var d2 = box(null); d2.get().hashCode(); (checked with the same flags; both are reported).
Grounding: JLS 14.4.1 types a var local as the upward projection of its initializer's type, and JLS 15.25.3 types a reference conditional as the lub of its operand types, so the type argument of cond comes from Box<@Nullable Object> and Box<String>; one operand admits null, so the result should too. The existing TODO in ConditionalExprTests states the same expectation.
Related: #1633 (the direct form, fixed by #1708), #1477 (conditional expressions with a target type, closed).
- Dominant language
- Java
- Stars
- 4.1k
- Forks
- 379
- Avg merge
- 1d 2h
- Merged PRs (30d)
- 106
Getting set up
- No Dockerfile or Docker Compose file
- Has a pull request template
- Read the contributing 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.
More from uber/NullAway
-
Difficulty 2/5 1-3 hours Newbie friendliness 72/100
uber/NullAway#2145 · 1 reaction ·
Maintainers usually reply within 1 day
-
Difficulty 1/5 1-3 hours Newbie friendliness 85/100
uber/NullAway#2058 · 1 comment ·
Maintainers usually reply within 1 day
-
Difficulty 2/5 1-3 hours Newbie friendliness 76/100
uber/NullAway#1899 · 1 comment ·
Maintainers usually reply within 1 day
-
Difficulty 5/5 Over a week Newbie friendliness 15/100
uber/NullAway#2160 · 1 comment ·
Maintainers usually reply within 1 day
-
Difficulty 3/5 1-2 days Newbie friendliness 62/100
Maintainers usually reply within 1 day
Similar issues
-
Difficulty 1/5 Under an hour Newbie friendliness 88/100
johanhaleby/occurrent#1505 ·
Maintainers usually reply within 1 day
-
bug
Difficulty 2/5 1-3 hours Newbie friendliness 72/100
Maintainers usually reply within 1 day
-
Difficulty 2/5 1-3 hours Newbie friendliness 72/100
FasterXML/jackson-databind#6443 ·
Maintainers usually reply within 1 day
-
Difficulty 2/5 1-3 hours Newbie friendliness 80/100
finos/fluxnova-bpm-platform#387 ·
Maintainers usually reply within 4 days
-
Difficulty 1/5 Under an hour Newbie friendliness 88/100