-
Notifications
You must be signed in to change notification settings - Fork 11
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
fix typetools/checker-framework issue#3249 #132
Conversation
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.
Thanks for working on this fix!
Can you add test cases for typetools#1727 and typetools#3249 to show that the issue is actually fixed?
output += "boolean literal is true\n"; | ||
isWhileTrue = true; | ||
} else { | ||
if (nodeList.size() > firstConditionPos + 1) { |
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.
Does javac treat while (!false)
as a special case?
Is it really worth handling such unusual code?
|
||
boolean isWhileTrue = false; | ||
int firstConditionPos = nodeList.size(); | ||
String output = "First condition position" + String.valueOf(firstConditionPos) + "\n"; |
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.
You can remove the debug output and the commented-out assert below.
@@ -4878,8 +4878,34 @@ public Node visitWhileLoop(WhileLoopTree tree, Void p) { | |||
|
|||
// Condition | |||
addLabelForNextNode(conditionStart); | |||
|
|||
boolean isWhileTrue = false; | |||
int firstConditionPos = nodeList.size(); |
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.
Instead of going through the converted nodes, wouldn't it be easier to just look at the condition tree and see whether it's the literal true
?
|
||
while (true) { | ||
B op = getB(); | ||
// :: warning: (known.nonnull) |
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.
Instead you could make the return type of getB
@Nullable B
. Otherwise the example isn't very convincing...
|
||
// Is condition constant true? | ||
boolean isWhileTrue = false; | ||
|
||
if (tree.getCondition() != null) { |
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.
I don't think the condition tree could ever be null, could it?
So maybe change this to
if (tree.getCondition() == null) {
raise error;
}
Then you can move the declaration of isWhileTrue
to line 4906 and simply have boolean isWhileTrue = condType.isTrue()
and avoid the unnecessary initialization with false.
extendWithExtendedNode(cjump); | ||
|
||
if (!isWhileTrue) { | ||
ConditionalJump cjump = new ConditionalJump(loopEntry, loopExit); |
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.
Add a comment here to explain why we do this.
extendWithExtendedNode(new UnconditionalJump(conditionStart)); | ||
|
||
// If the condition is constant true, the successor of loop end is loop entry, instead | ||
// of condition start |
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.
End the sentence with .
} | ||
|
||
// Loop body | ||
addLabelForNextNode(loopEntry); | ||
if (tree.getStatement() != null) { | ||
scan(tree.getStatement(), p); | ||
} | ||
extendWithExtendedNode(new UnconditionalJump(conditionStart)); | ||
|
||
// If the condition is constant true, the successor of loop end is loop entry, instead |
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.
What is the effect of this change? Is it really necessary to skip the condition for a while true?
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.
In fact, Javac bytecode generator merges the control flow at the end of the loop body with the condition start, so this change is just an optimization.
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.
A few more small comments to address.
Once they are and tests pass, please make a PR against typetools and we'll continue there.
local = 1; | ||
break; | ||
} | ||
// :: error: (assignment.type.incompatible) |
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.
Interesting that this isn't a constant... do you understand why? If you do, add a comment to explain.
if (tree.getCondition() != null) { | ||
unbox(scan(tree.getCondition(), p)); | ||
|
||
// Is condition constant true? |
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 should go to the declaration of isWhileTrue
a bit further down.
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.
Actually, there is already documentation down there, so just remove this.
unbox(scan(tree.getCondition(), p)); | ||
|
||
// Is condition constant true? | ||
assert tree.getCondition() != null : "while loop condition must not be null"; |
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.
I've made this change throughout in typetools#3364
I didn't add descriptions, so to avoid a merge problem maybe remove the one here as well.
|
||
// Is condition constant true? | ||
assert tree.getCondition() != null : "while loop condition must not be null"; | ||
// Check whether the loop condition is constant true, the criteria is consistent with |
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.
How about Determine whether loop condition is a constant true, according to the compiler logic.
?
|
||
unbox(scan(tree.getCondition(), p)); | ||
|
||
// If the loop condition is not constant true, the control flow is split into two |
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.
Move this comment into the then block.
@@ -4908,7 +4919,15 @@ public Node visitWhileLoop(WhileLoopTree tree, Void p) { | |||
if (tree.getStatement() != null) { | |||
scan(tree.getStatement(), p); | |||
} | |||
extendWithExtendedNode(new UnconditionalJump(conditionStart)); | |||
|
|||
// If the condition is constant true, for the purpose of improving the dataflow analysis |
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.
I find the performance argument rather weak - it's a constant true expression.
I would add a brief comment to the then and else block, just stating something like:
then: The condition is constant true so we can directly jump back to the loop entry.
else: Otherwise, jump back to evaluate the condition.
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 looks very nice now! Please close the PR here and move it to typetools.
New PR is here typetools#3389 |
This PR fixes typetools#3249