-
Notifications
You must be signed in to change notification settings - Fork 299
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
NullAway doesn't recognize Guava Preconditions checks #47
Comments
Thanks for the report! I think we should add default support for |
I believe Supporting |
Ah, I didn't realize we already support |
I will try to use |
Yes, that is true. If we can find a way to support |
|
Hey, this will be a blast from the past, but is there any plans to support |
@jrepe no concrete plans to prioritize this. I would be open to accepting a PR if we could show it doesn't impact overhead too much (and I don't think it should). |
Another flavor of this is scenario is- |
This shows up enough internally and asked about externally often enough that we should probably prioritize it above There are also cases like this, where there is no
|
I wonder if in the Checker Framework CFG, there are stores corresponding to the program point after evaluation of the first expression passed as the first argument to these methods. It seems possible that if we can find that store, we might be able to magically extract the right facts from the "then" store and propagate them to the correct successor store for the |
So, I see I think a better alternative is to use handlers to move the APs around. The easy part of that is using |
In the Checker Framework, the standard transfer function type The I think the right thing to do here may be to re-jigger things so that |
So, we already can get values for Even more,
As printing
Which we can use to set The problem is, this only works for the complex boolean expression case (due to the implicit control flow). In these cases:
We simply get:
As no branching is taking place inside the argument to the call. I suppose worst case we'd have to handle three cases semi-redundantly:
But even that might miss something. p.s. The NullnessStore handles cases like |
Actually, never mind, the above explanation is wrong. The GOOD news is: that The BAD news is: what breaks that approach is the presence of an explanation string in the
The "previous" thing to be evaluated is the string "a ought to be non-null" and not Edit: Not at all ready for review, but #607 shows this approach in more detail. |
I don't understand this. I would expect that the approach would be to query the store(s) for the first actual parameter passed to |
It doesn't query the store at an arbitrary node, it queries it on input to If we had a way to do stop and do a callback inside Another option is, having the node, try to find its corresponding block, and then use a reference to the analysis to call getInput(Block b) |
Ah, I get it. With this API, we can ask about the right Not obvious how to get exactly what we want in a clean way. May need to step through with a debugger and see if the relevant state is around somewhere. |
This also doesn't seem to work, since the whole thing is in the same block, when asking about the block corresponding to
So, getting the store either before or after that whole |
We could think about adding an API to Checker dataflow and opening a PR; I think they would be open to it if we show the change is useful. |
…ation (#608) See #47 for discussion. This PR adds support for `Preconditions.checkArgument(...)` and `Preconditions.checkState(...)` throw a new `PreconditionsHandler` handler. In order to implement said handler, we need a custom CFG translation pipeline in NullAway (`NullAwayCFGBuilder`) which subclasses the Checker Framework's `CFGBuilder` (which we were using directly before this change). This pipeline allows us to add handler callbacks during the AST to CFG translation process. At the moment, we add a single such callback, right after visiting a `MethodInvocationTree`. We also add a more or less generic method to insert a conditional jump and a throw based on a given boolean expression node. Abstracting some details about our AST and CFG structures, we translate: ``` Preconditions.checkArgument($someBoolExpr[, $someString]); ``` Into something resembling: ``` Preconditions.checkArgument($someBoolExpr[, $someString]); if ($someBoolExpr) { throw new IllegalArgumentException(); } ``` Note that this causes `$someBoolExpr` to be evaluated twice. This is necessary based on how NullAway evaluates branch conditionals, since we currently do not track boolean values through our dataflow (e.g. `boolean b = (o == null); if (b) { throw [...] }; o.toString();` produces a dereference according to NullAway, independent on whether that code was added by rewriting or directly on the source. Obviously, this doesn't change the code being compiled or bytecode being produced, the rewrite is only ever used by/visible to NullAway itself. Finally, our implementation of `NullAwayCFGBuilder` and particularly `NullAwayCFGTranslationPhaseOne` in this PR, depend on a Checker Framework APIs that are currently private. We are simultaneously submitting a PR to change the visibility of these APIs (see [CheckerFramework#5156](typetools/checker-framework#5156))
This issue is fixed in NullAway 0.9.8! Let us know if you still see problems. |
I'm using Google Guava Preconditions to raise errors on null parameters. So basically, when I write something like:
item
is null safe, but NullAway still raises an error.The text was updated successfully, but these errors were encountered: