Paul King created GROOVY-12208:
----------------------------------

             Summary: NullChecker: broaden null-guard recognition
                 Key: GROOVY-12208
                 URL: https://issues.apache.org/jira/browse/GROOVY-12208
             Project: Groovy
          Issue Type: Improvement
          Components: groovy-typecheckers
            Reporter: Paul King


The incubating {{groovy.typecheckers.NullChecker}} currently recognizes a 
limited in-body guard vocabulary: single {{x != null}} / {{x == null}} binary 
comparisons (including identity forms) as {{if}} conditions, and early-exit 
patterns ({{if (x == null) return/throw}}), plus safe navigation. (Separately, 
the groovy-contracts bridge already infers non-nullness from {{@Requires}} 
conditions including conjunctions, via {{StaticTypesMarker.INFERRED_NON_NULL}} 
— this issue is about guard recognition inside method bodies, where 
conjunctions and other idiomatic forms are not yet recognized.)

Idiomatic Groovy uses several other null-guard forms, each currently producing 
false positives that discourage adoption:

* Groovy-truth guards: {{if (x) { x.foo() } }} — for reference types, 
truthiness implies non-null within the guarded block (Groovy truth being false 
for empty strings/collections does not affect nullness soundness).
* Boolean conjunctions in conditions: {{if (x != null && x.foo())}}, and 
short-circuit dereferences {{x != null && x.foo()}} in expression position; 
Groovy-truth conjuncts {{x && x.foo()}}.
* {{instanceof}} checks: {{if (x instanceof Foo)}} implies {{x}} is non-null 
(aligns with the flow typing the static type checker already performs for 
{{instanceof}}).
* {{Objects.nonNull(x)}} / {{Objects.isNull(x)}} in the positions the binary 
forms are recognized today.
* {{assert x}} and {{assert x != null}} statements.
* Guard conditions in {{while}} loops and ternary conditions, mirroring the 
{{if}} handling.

Each addition removes a class of false positives without changing the checker's 
architecture. Test coverage should include the negated forms and else-branch 
behaviour for each new guard shape, following the existing patterns in 
{{NullCheckerTest}} (cf. {{testNullableWithNotNullGuard}} et al.).




--
This message was sent by Atlassian Jira
(v8.20.10#820010)

Reply via email to