GV

GeezerVison

The World Wide Web, restored to 800 pixels of glory.

Home|About|Gaming cabinet|Archives|How it works|Starter sites

On this site

  • Sign in
  • ActionsCI/CD and automation
  • CodespacesCloud development environments
  • All Features
  • Documentation
  • Training
  • Certifications
  • Build with Copilot
  • Customize Copilot
  • Integrations
  • Trending repos
  • GitHub Sponsors
  • Developer articles
  • Enterprises

This view

  • Original page
  • New address

GeezerVison is showing github.com — Add Null Support by rcosta358 · Pull Request #143 · liquid-java/liquidjava

Conversation

@rcosta358

@rcosta358 rcosta358 commented Feb 7, 2026 •
edited
Loading

Uh oh!

There was an error while loading. Please reload this page.

Copy link
Copy Markdown
Collaborator

This PR adds support for null checking in LiquidJava.

Changes

Refinements Language

  • Added the null literal to the grammar
  • Added the LiteralNull AST node

Typing

  • The literal null can be assigned to any non-primitive type
  • String literals, literals of boxed types and new object instances implicitly carry the refinement _ != null, while the literal null carries the refinement _ == null
  • When a class field is declared without a value, it is implicitly refined with _ == null

Z3 Translation

  • Nulls are converted to uninterpreted constants of the uninterpreted sort java.lang.Object
  • In equality comparisons, null literals are converted to the sort of the other operand to match both sorts

Simplification

  • The simplifier removes redundant null checks when an equality to a non-null literal already implies a non-null value. This way, s == -1 && s != null simplifies to s == -1 instead of -1 != null

Testing

  • Added various tests to ensure the correctness of these changes

Sorry, something went wrong.

Uh oh!

There was an error while loading. Please reload this page.

All reactions
rcosta358 added 2 commits February 7, 2026 22:04
@rcosta358
Add Null & Boxed Types Support
7a8de62
@rcosta358
Add Tests
c2ae323
@rcosta358 rcosta358 self-assigned this Feb 7, 2026
@rcosta358 rcosta358 added the enhancement New feature or request label Feb 7, 2026
@rcosta358
rcosta358 requested a review from CatarinaGamboa February 7, 2026 22:08
rcosta358 added 2 commits February 7, 2026 22:24
@rcosta358
Minor Changes
d73b81c
@rcosta358
Unused Imports
f24dc28
CatarinaGamboa
CatarinaGamboa requested changes Feb 9, 2026
View reviewed changes

@CatarinaGamboa CatarinaGamboa left a comment

Copy link
Copy Markdown
Collaborator

There was a problem hiding this comment.

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

For the nullness check, I think we need more cases, like what if we declare the var and it doesn't have a value?
There are full tools just for the nullness checking (e.g., NullAway https://github.com/uber/NullAway)

PS: this would be so much easier if it were 2 prs, one for null and one for boxed types -- the boxed types would be an easy squash and merge

Sorry, something went wrong.

Uh oh!

There was an error while loading. Please reload this page.

rcosta358 reacted with thumbs up emoji
All reactions
  • 👍 1 reaction
Comment thread ...va-verifier/src/main/java/liquidjava/processor/refinement_checker/RefinementTypeChecker.java Resolved

Uh oh!

There was an error while loading. Please reload this page.

@rcosta358

This comment was marked as resolved.

Sign in to view
rcosta358

This comment was marked as resolved.

Sign in to view

Sorry, something went wrong.

Uh oh!

There was an error while loading. Please reload this page.

rcosta358 added 5 commits February 10, 2026 21:35
@rcosta358
Minor Improvements
cb50d1e
@rcosta358
Merge branch 'main' into null-support
65e938d
@rcosta358
Mark Uninitialized Fields as Null
aef5189
@rcosta358
Merge branch 'main' into null-support
e959ce6
@rcosta358
Fix Merge
4c4661c
@rcosta358
rcosta358 requested a review from CatarinaGamboa February 12, 2026 14:54
@rcosta358
Remove Boxed Types
8998f23
@rcosta358 rcosta358 changed the title Add Null & Boxed Types Support Add Null Support Feb 13, 2026
@rcosta358
Merge branch 'main' into null-support
d8e500d
CatarinaGamboa
CatarinaGamboa requested changes Feb 13, 2026
View reviewed changes

@CatarinaGamboa CatarinaGamboa left a comment

Copy link
Copy Markdown
Collaborator

There was a problem hiding this comment.

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is nice to have, but I have some questions (we already discussed some offline):

  • obj != null and state. It would be great if we didnt have to pollute the refinements with always having to write this != null. Maybe we can assume that all object states imply != null?
  • null of fields are trickier, check the comment below

Sorry, something went wrong.

Uh oh!

There was an error while loading. Please reload this page.

rcosta358 reacted with thumbs up emoji
All reactions
  • 👍 1 reaction
CatarinaGamboa
CatarinaGamboa reviewed Feb 13, 2026
View reviewed changes

@CatarinaGamboa CatarinaGamboa left a comment

Copy link
Copy Markdown
Collaborator

There was a problem hiding this comment.

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this comment

Sorry, something went wrong.

Uh oh!

There was an error while loading. Please reload this page.

All reactions
Comment thread liquidjava-example/src/main/java/testSuite/CorrectNullChecks.java Outdated
Integer x; // implicit null

void test() {
mustBeNull(x);

@CatarinaGamboa CatarinaGamboa Feb 13, 2026

Copy link
Copy Markdown
Collaborator

There was a problem hiding this comment.

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

But we don't know if this is null right? how do we know? what if there was a constructor, what if another method is called first and sets this fiels? what are the assumptions here?

Sorry, something went wrong.

Uh oh!

There was an error while loading. Please reload this page.

All reactions

@rcosta358 rcosta358 Feb 13, 2026

Copy link
Copy Markdown
Collaborator Author

There was a problem hiding this comment.

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah you're right. I'll try to handle those cases.

Sorry, something went wrong.

Uh oh!

There was an error while loading. Please reload this page.

All reactions

@rcosta358 rcosta358 Feb 15, 2026 •
edited
Loading

Uh oh!

There was an error while loading. Please reload this page.

Copy link
Copy Markdown
Collaborator Author

There was a problem hiding this comment.

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Well, I think that is a different problem, not actually related to nulls.
Consider this example, which fails the verification:

public class TestField {
    boolean x; // even if we initialize x with true the same error occurs btw

    @Refinement("_ == true")
    boolean test() {
        setValue();
        return x; // Refinement Error: #ret_0 == this#x is not a subtype of #ret_0 == true
    }

    void setValue() {
        x = true;
    }
}

However, in this case, the verification passes:

public class TestField {
    boolean x;

    @Refinement("_ == true")
    boolean test() {
        x = true;
        return x; // ok
    }
}

This means that the specific problem you mentioned is about how field updates across method calls are handled. The typechecker does not propagate the effect of setValue(), meaning field mutations are not reflected in the context after a method or constructor is called.

Therefore, I think that problem is unrelated to this PR and we should open its own issue.
What do you think @CatarinaGamboa?

Sorry, something went wrong.

Uh oh!

There was an error while loading. Please reload this page.

All reactions

@CatarinaGamboa CatarinaGamboa Feb 15, 2026

Copy link
Copy Markdown
Collaborator

There was a problem hiding this comment.

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Okay several points:
1 - We cannot handle the field tracking atm, only with Latte - aliasing tracking extension, that we are working on in parallel. So you don't need to try and tackle this issue here, definitely, I agree.
2 - I think my main issue in the example was with mustBeNull, like we can't know for sure, we maybe should not track the nullness of them when entering methods, we would need an if to verify its value like

   void test() {
        if ( x == null){
             mustBeNull(x);
        } else {
             mustBeNotNull(x);
        }

This I think we should support, but we cannot be certain of the value at the start of the method.
Does this make sense?
We would have the code slilghtly polluted by ifs bit at least we check the values.

Sorry, something went wrong.

Uh oh!

There was an error while loading. Please reload this page.

All reactions

@rcosta358 rcosta358 Feb 15, 2026 •
edited
Loading

Uh oh!

There was an error while loading. Please reload this page.

Copy link
Copy Markdown
Collaborator Author

There was a problem hiding this comment.

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

1 - Yeah you're right, I didn't even think of Latte.
2 - I agree. I'll change that test.

Sorry, something went wrong.

Uh oh!

There was an error while loading. Please reload this page.

All reactions

@CatarinaGamboa CatarinaGamboa Feb 15, 2026

Copy link
Copy Markdown
Collaborator

There was a problem hiding this comment.

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

for 2 - I think we should point out an issue with the call to mustBeNull(x) without the if

Sorry, something went wrong.

Uh oh!

There was an error while loading. Please reload this page.

rcosta358 reacted with thumbs up emoji
All reactions
  • 👍 1 reaction
@rcosta358
rcosta358 marked this pull request as draft February 13, 2026 15:57
@rcosta358
rcosta358 marked this pull request as draft February 13, 2026 15:57
rcosta358 added 2 commits February 15, 2026 16:41
@rcosta358
Change CorrectNullChecks Test
31bd897
@rcosta358
Remove Fields Implicit Null Refinement
c739e5f
@rcosta358
rcosta358 force-pushed the main branch from 215f1d4 to d91f256 Compare July 27, 2026 13:30
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Reviewers

@CatarinaGamboa CatarinaGamboa CatarinaGamboa requested changes

Requested changes must be addressed to merge this pull request.

Uh oh!

There was an error while loading. Please reload this page.

Assignees

@rcosta358 rcosta358

Labels

enhancement New feature or request

Projects

None yet

Milestone

No milestone

Development

Successfully merging this pull request may close these issues.

Uh oh!

There was an error while loading. Please reload this page.

2 participants

@rcosta358 @CatarinaGamboa
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
You are visitor 01402503 — GeezerVison does not store the pages you look up.
Best viewed with Netscape Navigator 4.7 or Internet Explorer 6 at 800×600. No cookies required.