You are viewing a plain text version of this content. The canonical link for it is here.
Posted to notifications@groovy.apache.org by "ASF GitHub Bot (Jira)" <ji...@apache.org> on 2026/07/29 08:08:00 UTC

[jira] [Commented] (GROOVY-12208) NullChecker: broaden null-guard recognition

    [ https://issues.apache.org/jira/browse/GROOVY-12208?page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanel&focusedCommentId=18099976#comment-18099976 ] 

ASF GitHub Bot commented on GROOVY-12208:
-----------------------------------------

paulk-asert opened a new pull request, #2746:
URL: https://github.com/apache/groovy/pull/2746

   (no comment)




> 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
>            Priority: Major
>
> 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)