Skip to content

Conversation

@d367wang
Copy link

@d367wang d367wang commented Apr 1, 2021

The bottom store has the following properties:

  1. The LUB of a bottom store and a second store is the second store.
  2. A bottom store is immutable once it's created. i.e. It doesn't support insertion, replacement and other forms of updating.
  3. When getting value from a bottom store, it always returns the bottom value (consisted of bottom annotation and the underlying type).
  4. With property 2, we maintain one single instance of bottom store for each type system involved at runtime.

Copy link

@zcai1 zcai1 left a comment

Choose a reason for hiding this comment

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

Most of the changes LGTM! 👍

AnnotationMirror guardBy = ((LockAnnotatedTypeFactory) analysis.getTypeFactory()).GUARDEDBY;
AnnotationMirror lockHeld = ((LockAnnotatedTypeFactory) analysis.getTypeFactory()).LOCKHELD;

return analysis.createAbstractValue(new HashSet<>(Arrays.asList(lockHeld, guardBy)), type);
Copy link

Choose a reason for hiding this comment

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

new HashSet<>(Arrays.asList(lockHeld, guardBy)
Can we replace it with ImmutableSet.of(...)? Or should we store these bottom annotations instead of creating a new set each time this method is invoked?

Copy link
Author

Choose a reason for hiding this comment

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

Actually there is a final field bottomAnnos in the these store classes that represents the set of bottom annotations. That field is initialized in the constructor with AnnotatedTypeFactory.getBottomAnnotations().

But LockStore is special. We can't use the real bottom annotations, so here the getBottomValue is overriden.

super(analysis, sequentialSemantics, isBottom);
isPolyNullNonNull = false;
isPolyNullNull = false;
this.isPolyNullNull = false;
Copy link

Choose a reason for hiding this comment

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

Why adding this. on line 49 while line 48 doesn't have this.?


// Is it necessary to consider `x = true ? y : z`
if (parentTree.getKind() == Tree.Kind.CONDITIONAL_EXPRESSION) {
return ((ConditionalExpressionTree) parentTree).getCondition() == tree;
Copy link

Choose a reason for hiding this comment

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

What if the condition is wrapped by parentheses? For example, (x == true) ? y : z.

return ((ConditionalExpressionTree) parentTree).getCondition() == tree;
}

return parentTree.getKind() == Tree.Kind.IF
Copy link

Choose a reason for hiding this comment

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

This logic may work as expected, but I think it's safer to compare with parentTree.getCondition() so we know it indeed is a condition.

// :: error: (assignment.type.incompatible)
int @MinLen(10) [] res = arr;
int @MinLen(4) [] res2 = arr;
// :: error: (assignment.type.incompatible)
Copy link

Choose a reason for hiding this comment

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

These changes make sense, but they also alter the meaning of this test. Should we write a new test case for the merging of @BottomVal and @MinLen(4)?

String ans = "x";
while (true) {
if (true) {
// :: error: (return.type.incompatible)
Copy link

Choose a reason for hiding this comment

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

Same issue here: we are removing all occurences of // :: error: (return.type.incompatible) in this file, and we need some new test cases to cover issue typetools#548.


class DeadBranch {

Object foo(@Nullable Object myObj, boolean x) {
Copy link

Choose a reason for hiding this comment

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

Why do we need boolean x?

Copy link
Author

Choose a reason for hiding this comment

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

Thanks for pointing out! I need to add another case using x as the condition.

} else {
arr = arg2;
}
// :: error: (assignment.type.incompatible)
Copy link

@zcai1 zcai1 Sep 29, 2021

Choose a reason for hiding this comment

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

Same issue here: I think we need to test LUB of @BottomVal and @MinLen(4), and LUB of @MinLen(10) and @MinLen(4).

@d367wang
Copy link
Author

d367wang commented Sep 29, 2021

Thank you for the comments @zcai1

public abstract S createBottomStore(boolean sequentialSemantics);

/**
* Get the singleton of the bottom store corresponding to the type.
Copy link
Author

@d367wang d367wang Sep 29, 2021

Choose a reason for hiding this comment

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

... corresponding to the type system

@Override
public S leastUpperBound(S other) {
if (this.isBottom) return other;
if (other != null && other.isBottom) return (S) this;
Copy link
Author

Choose a reason for hiding this comment

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

Do we need to test the nullness of other here? The dataflow code is nullness-type-safe guaranteed by NullnessChecker, isn't it?


@Override
public KeyForStore createBottomStore(boolean sequentialSemantics) {
return new KeyForStore(this, sequentialSemantics);
Copy link

Choose a reason for hiding this comment

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

Maybe just return createEmptyStore(sequentialSemantics)?

Copy link
Author

@d367wang d367wang Sep 29, 2021

Choose a reason for hiding this comment

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

return new KeyForStore(this, sequentialSemantics, true);

"contracts.conditional.postcondition.not.satisfied" // TODO: `if` needs the
// BOTH_TO_THEN treatment that ?: gets.
)
@SuppressWarnings("contracts.conditional.postcondition.not.satisfied")
Copy link
Author

@d367wang d367wang Sep 29, 2021

Choose a reason for hiding this comment

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

add comment for reason for suppressWarning

add another case return true in if and return false in else

* @return ture if the given tree is a condition
*/
@SuppressWarnings("interning:not.interned")
boolean isCondition(ExpressionTree tree) {
Copy link
Author

Choose a reason for hiding this comment

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

private

* @param type the input {@link TypeMirror}
* @return the bottom value
*/
protected V getBottomValue(TypeMirror type) {
Copy link

Choose a reason for hiding this comment

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

maybe createBottomValue?

zcai1 pushed a commit to zcai1/checker-framework that referenced this pull request Feb 8, 2022
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.

2 participants