New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Allow tracking non-static field accesses outside the this instance #625
Conversation
@msridhar Given that this revisits a five years old design decision in NullAway, and I am not sure if I am missing any pitfalls, I don't plan to land this until I have had a chance to test this is in our internal codebases, and ideally after you are back from vacation and can provide a review. But I don't see or remember an obvious reason to not support these kind of access paths 😅 |
Pull Request Test Coverage Report for Build #892
💛 - Coveralls |
I think the reason to not support this was mainly paranoia around performance overhead, as tracking more access paths leads to larger dataflow stores. I never rigorously measured the impact; it seemed we could get away with just not tracking these. I guess that has changed, and I agree the current behavior is confusing. So I'm open to this change assuming we don't see much of an overhead regression.
Why does this issue come up more for JDK11 codebases? |
Sorry, those were two thoughts: a) this is likely to come up more for JDK17 vs JDK11/JDK9, b) we definitely see this in JDK11 code outside the Android world. I wasn't trying to imply that this is more common in Java 11 than 8/9. |
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.
Change LGTM. Except a minor question.
@@ -1086,18 +1093,27 @@ private final class ReadableUpdates implements Updates { | |||
|
|||
@Override | |||
public void set(LocalVariableNode node, Nullness value) { | |||
values.put(AccessPath.fromLocal(node), checkNotNull(value)); | |||
values.put(AccessPath.fromLocal(node), value); | |||
} | |||
|
|||
@Override | |||
public void set(VariableDeclarationNode node, Nullness value) { |
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.
why did we remove the checkNotNull
?
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.
We are checking NullAway with NullAway now, and value
is not marked @Nullable
, so it should always be non-null. I think this is from before NullAway was running on itself 😄
FYI, just looked at this change and it looks great 🙂 |
We took the decision, back around the origins of NullAway, to not track arbitrary field-dereferences for nullness propagation. Instead, NullAway expects field accesses to be: a) specifically on fields of the current instance object (i.e.
this
), b) on static fields (e.g. constants/enums), or c) made through getters.This means that, for example, the following code would produce a surprising NullAway error:
Assuming field
o
ofFoo
is@Nullable
and an instance field, the code above will cause NullAway to complain thatfoo.o.toString()
might be dereferencing a "nullable" expressionfoo.o
, despite the check right before it. This is because NullAway doesn't track any access paths of the form (argument/local)+field, whereas it does track (argument/local)+method call. This is unintuitive.While getters are good practice in Java, they aren't universal. This is already a problem for JDK11 codebases and only likely to become more obvious when dealing with JDK17 records.
This PR attempts to relax this requirement.