Skip to content
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

refactor to directly return mayBeNullFieldAccess #748

Closed

Conversation

XN137
Copy link
Contributor

@XN137 XN137 commented Mar 12, 2023

the method already calls onOverrideMayBeNullExpr and nullnessFromDataflow so there is no point to break out of the switch to call the former again

see also other usage of mayBeNullFieldAccess a few lines below

also remove comments that just restated the obvious

case IDENTIFIER:
if (exprSymbol == null) {
throw new IllegalStateException(
"unexpected null symbol for identifier " + state.getSourceForNode(expr));
}
if (exprSymbol.getKind().equals(ElementKind.FIELD)) {
// Special case: mayBeNullFieldAccess runs handler.onOverrideMayBeNullExpr before
// dataflow.
Copy link
Contributor Author

Choose a reason for hiding this comment

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

note how this isnt a special case, because the else branch does the same thing

the only difference is the initial value of the exprMayBeNull parameter

Copy link
Collaborator

Choose a reason for hiding this comment

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

It's been a long time since I looked at this code! I think the intended structure is as follows for the common case:

  • The switch statement sets the exprMayBeNull variable, mostly according to the kind of expression and the expression's nullability type qualifier.
  • After the switch, handler.onOverrideMayBeNullExpr is run to allow for overriding from handlers.
  • Finally, if we have concluded that the expression may be null based on the above, we run dataflow analysis to possibly override this conclusion based on some null check in the code.

For local variables, we always infer their nullability via dataflow analysis. Right now, that code is written as an "early return" out of the switch. But maybe it would be clearer if we just did (on lines 2274-2275):

// local variable's type must always be inferred using dataflow
exprMayBeNull = true;
break;

For method calls and field accesses, I think we could do something similar. We could just avoid running the handler and dataflow in mayBeNullMethodCall and mayBeNullFieldAccess, just setting exprMayBeNull appropriately but getting rid of the handler and dataflow calls, leaving those to one place, after the switch statement. This would get rid of all the early returns out of the switch and some duplicated code.

What do you think?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

After the switch, handler.onOverrideMayBeNullExpr is run to allow for overriding from handlers.

Finally, if we have concluded that the expression may be null based on the above, we run dataflow analysis to possibly override this conclusion based on some null check in the code.

i might be missing something but this doesnt seem to be true.
when we break from the switch, dataflow analysis is NOT run...
only some expression types run it inside the switch branches.

taking a step back:
this PR focuses on a very narrow cleanup of redundant calls/obsolete comments
if you see the potential for more cleanups/unifying we should do those in a followup imo

Copy link
Contributor Author

Choose a reason for hiding this comment

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

also note that some switch branches seem to run nullnessFromDataflow before handler.onOverrideMayBeNullExpr while others do it the other way round.

// Special case: mayBeNullMethodCall runs handler.onOverrideMayBeNullExpr before dataflow.
return mayBeNullMethodCall(state, expr, (Symbol.MethodSymbol) exprSymbol);

local testing suggests that order may not matter (tests seem to pass in both cases)

Copy link
Contributor Author

Choose a reason for hiding this comment

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

if i understood you correctly this was your suggestion:
#753

however see the open questions there

@XN137 XN137 force-pushed the refactor-return-mayBeNullFieldAccess branch from 946318c to 2e4b774 Compare March 31, 2023 08:20
@XN137 XN137 force-pushed the refactor-return-mayBeNullFieldAccess branch from 2e4b774 to f1de173 Compare March 31, 2023 17:04
the method already calls `onOverrideMayBeNullExpr` and `nullnessFromDataflow`
so there is no point to break out of the switch to call the former
again

see also other usage of `mayBeNullFieldAccess` a few lines below

also remove comments that just restated the obvious
@XN137 XN137 force-pushed the refactor-return-mayBeNullFieldAccess branch from f1de173 to f8143b3 Compare April 1, 2023 07:26
@XN137
Copy link
Contributor Author

XN137 commented Apr 4, 2023

obsolete after the other PR got merged

@XN137 XN137 closed this Apr 4, 2023
@XN137 XN137 deleted the refactor-return-mayBeNullFieldAccess branch April 4, 2023 17:34
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

2 participants