uber/NullAway

Document sources of deliberate unsoundness

Closed

#1,617 opened on Jun 20, 2026

 (5 comments) (0 reactions) (1 assignee)Java (288 forks)batch import
documentationgood first issue

Repository metrics

Stars
 (3,462 stars)
PR merge metrics
 (Avg merge 3d 23h) (14 merged PRs in 30d)

Description

Description

NullAway currently does not warn when doing nested null-checks with mutable data. I can write:

if(rental.returnPolicy() == null || rental.returnPolicy().mustBeReturnedAfter() == null){
    //                                                                                   ^^^^^
    // is not, but should be: [NullAway] dereferenced expression rental.returnPolicy() is @Nullable
    // returnPolicy is just a method so its return value could change between first and second call
    return 0;
}

To me that seems like a false negative. It does not warn but should.

Minimal repro

import org.jetbrains.annotations.Nullable;

public class Main {
    public static void main(String[] args){
        check(new RegularRental());
    }

    static int check(Rental rental){
        if(rental.returnPolicy() == null || rental.returnPolicy().mustBeReturnedAfter() == null){
            //                                                    ^^^^^^^^^^^^^^^^^^^^
            // is not, but should be: [NullAway] dereferenced expression rental.returnPolicy() is @Nullable
            // returnPolicy is just a method so its return value could change between first and second call
            return 0;
        }
        return 1;
    }
}


interface Rental {
    @Nullable ReturnPolicy returnPolicy();
}

class RegularRental implements Rental {

    private ReturnPolicy returnPolicy = new ReturnPolicy("2");

    @Override public ReturnPolicy returnPolicy(){ return this.returnPolicy; }
}

class ReturnPolicy {
    private @Nullable String mustBeReturnedAfter;

    ReturnPolicy(@Nullable String mustBeReturnedAfter) { this.mustBeReturnedAfter = mustBeReturnedAfter; }

    public @Nullable String mustBeReturnedAfter() { return mustBeReturnedAfter; }
}

Contributor guide