-
Notifications
You must be signed in to change notification settings - Fork 353
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
First Phase of RLC inference #5870
Conversation
checker/src/main/java/org/checkerframework/checker/mustcall/MustCallTransfer.java
Outdated
Show resolved
Hide resolved
checker/src/main/java/org/checkerframework/checker/mustcall/MustCallVisitor.java
Outdated
Show resolved
Hide resolved
checker/src/main/java/org/checkerframework/checker/resourceleak/MustCallInferenceLogic.java
Outdated
Show resolved
Hide resolved
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.
CI is failing. Could you at least make the misc
job succeed?
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 review only provides high-level feedback on the interactions with the rest of the Checker Framework (i.e., I didn't review MustCallInferenceLogic
).
checker/src/main/java/org/checkerframework/checker/calledmethods/CalledMethodsTransfer.java
Outdated
Show resolved
Hide resolved
checker/src/main/java/org/checkerframework/checker/mustcall/MustCallAnnotatedTypeFactory.java
Outdated
Show resolved
Hide resolved
checker/src/main/java/org/checkerframework/checker/resourceleak/ResourceLeakVisitor.java
Outdated
Show resolved
Hide resolved
framework/src/main/java/org/checkerframework/common/accumulation/AccumulationTransfer.java
Outdated
Show resolved
Hide resolved
...rg/checkerframework/common/wholeprograminference/WholeProgramInferenceJavaParserStorage.java
Show resolved
Hide resolved
checker/src/main/java/org/checkerframework/checker/resourceleak/MustCallInferenceLogic.java
Outdated
Show resolved
Hide resolved
checker/src/main/java/org/checkerframework/checker/resourceleak/MustCallInferenceLogic.java
Outdated
Show resolved
Hide resolved
checker/src/main/java/org/checkerframework/checker/resourceleak/MustCallInferenceLogic.java
Outdated
Show resolved
Hide resolved
checker/src/main/java/org/checkerframework/checker/resourceleak/MustCallInferenceLogic.java
Outdated
Show resolved
Hide resolved
...rg/checkerframework/common/wholeprograminference/WholeProgramInferenceJavaParserStorage.java
Outdated
Show resolved
Hide resolved
...rg/checkerframework/common/wholeprograminference/WholeProgramInferenceJavaParserStorage.java
Outdated
Show resolved
Hide resolved
checker/src/main/java/org/checkerframework/checker/resourceleak/ResourceLeakVisitor.java
Outdated
Show resolved
Hide resolved
...rg/checkerframework/common/wholeprograminference/WholeProgramInferenceJavaParserStorage.java
Outdated
Show resolved
Hide resolved
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 did a full review of all code not in MustCallInferenceLogic
, but I only reviewed the documentation of methods/fields in that class.
checker/src/main/java/org/checkerframework/checker/calledmethods/CalledMethodsTransfer.java
Outdated
Show resolved
Hide resolved
checker/src/main/java/org/checkerframework/checker/calledmethods/CalledMethodsTransfer.java
Outdated
Show resolved
Hide resolved
checker/tests/ainfer-resourceleak/non-annotated/EnsuresCalledMethodsTest.java
Outdated
Show resolved
Hide resolved
checker/tests/ainfer-resourceleak/non-annotated/EnsuresCalledMethodsTest.java
Outdated
Show resolved
Hide resolved
analysis | ||
.checker | ||
.getUpstreamCheckerNames() | ||
.contains("org.checkerframework.checker.resourceleak.ResourceLeakChecker"); |
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.
Putting this in CFAbstractTransfer
seems like too much coupling, to me. If you're going to use this implementation strategy (which I'd prefer we replace; see my comment on the first use of the isResourceLeakCheckerEnabled
above), this logic should be in some Resource Leak Checker class (maybe as a static method that takes a BaseTypeChecker
?)
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 flag is used in MustCallTransfer and CalledMethodsTransfer, so I think it should be defined within these two checkers rather than in some Resource Leak Checker class, am I right?
checker/src/main/java/org/checkerframework/checker/resourceleak/MustCallInferenceLogic.java
Outdated
Show resolved
Hide resolved
checker/src/main/java/org/checkerframework/checker/resourceleak/MustCallInferenceLogic.java
Outdated
Show resolved
Hide resolved
checker/src/main/java/org/checkerframework/checker/resourceleak/MustCallInferenceLogic.java
Outdated
Show resolved
Hide resolved
checker/src/main/java/org/checkerframework/checker/resourceleak/MustCallInferenceLogic.java
Outdated
Show resolved
Hide resolved
checker/src/main/java/org/checkerframework/checker/resourceleak/MustCallInferenceLogic.java
Outdated
Show resolved
Hide resolved
checker/src/main/java/org/checkerframework/checker/mustcall/MustCallAnnotatedTypeFactory.java
Outdated
Show resolved
Hide resolved
checker/src/main/java/org/checkerframework/checker/resourceleak/MustCallInferenceLogic.java
Outdated
Show resolved
Hide resolved
checker/src/main/java/org/checkerframework/checker/resourceleak/MustCallInferenceLogic.java
Outdated
Show resolved
Hide resolved
checker/src/main/java/org/checkerframework/checker/resourceleak/MustCallInferenceLogic.java
Outdated
Show resolved
Hide resolved
checker/src/main/java/org/checkerframework/checker/resourceleak/MustCallInferenceLogic.java
Outdated
Show resolved
Hide resolved
checker/src/main/java/org/checkerframework/checker/resourceleak/MustCallInferenceLogic.java
Outdated
Show resolved
Hide resolved
checker/src/main/java/org/checkerframework/checker/resourceleak/MustCallInferenceLogic.java
Outdated
Show resolved
Hide resolved
checker/src/main/java/org/checkerframework/checker/resourceleak/MustCallInferenceLogic.java
Outdated
Show resolved
Hide resolved
...rc/main/java/org/checkerframework/checker/resourceleak/ResourceLeakAnnotatedTypeFactory.java
Outdated
Show resolved
Hide resolved
@@ -113,6 +113,9 @@ public abstract class CFAbstractTransfer< | |||
/** Indicates that the whole-program inference is on. */ | |||
private final boolean infer; | |||
|
|||
/** Indicates that the resource leak checker is enabled. */ | |||
private final boolean enableWPIForRLC; |
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 still don't think CFAbstractTransfer
is the appropriate place for this flag. I agree that it's the LUB of MustCallTransfer
and CalledMethodsTransfer
, but this class should only contain code that's germane to all CF checkers.
Maybe create an interface with this functionality instead that those two classes can implement?
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 is looking great! I have one (hopefully last!) comment.
checker/src/main/java/org/checkerframework/checker/resourceleak/MustCallInference.java
Outdated
Show resolved
Hide resolved
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.
LGTM!
checker/tests/ainfer-resourceleak/non-annotated/ECMInference.java
Outdated
Show resolved
Hide resolved
checker/src/main/java/org/checkerframework/checker/resourceleak/ResourceLeakChecker.java
Outdated
Show resolved
Hide resolved
if (getWholeProgramInference() != null | ||
&& elt.getKind() == ElementKind.PARAMETER | ||
&& getDeclAnnotation(elt, MustCallAlias.class) != null) { | ||
type.replaceAnnotation(BOTTOM); | ||
} |
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.
It doesn't appear that the comment that you promised here was actually added to the code.
...ker/src/main/java/org/checkerframework/checker/resourceleak/MustCallConsistencyAnalyzer.java
Show resolved
Hide resolved
checker/src/main/java/org/checkerframework/checker/resourceleak/MustCallInference.java
Show resolved
Hide resolved
|
||
/** | ||
* Adds the node to the disposedFields set if it is a field and its must-call obligation is | ||
* satisfied by the given method call. If so, it will be given an @Owning annotation later. |
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.
If so, it will be given an
@Owning
annotation later.
I don't think this is guaranteed to be true, based on the conversation related to disposedFields
and its Javadoc, above. Please make sure this is consistent, and that the Javadoc does not make false claims.
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 think if we want to be consistent with the algorithm, when we see somewhere in the code, must-call obligation of a field is satisfied, then the field has to be owning. Since disposedFields does not monotonically increase, I think we need to add it to the owningField set too.
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 think we need to add it to the owningField set too
If you're saying that there is a bug in the implementation (which I think you are), then we should write a test case for this situation.
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 was unable to reproduce a test case because the test infrastructure for WPI can only run for one iteration. I suspect that this issue arises when the @ECM annotation on the finalizer method is inferred during the second iteration.
{
Foo f;
void overwriteFoo() {
f.a();
f = new Foo();
}
finalizer() {
closeFoo(f);
}
}
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 was unable to reproduce a test case because the test infrastructure for WPI can only run for one iteration
This should not prevent you from writing a test case: if you want to test what happens on the second iteration, the input should have the annotations produced by the first iteration. This process works inductively, so it is possible to test WPI behavior on any iteration using the one-iteration test infrastructure.
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 wasn't able to reproduce this issue because in the test infrastructure, the final result (after inference) should be type checked. If a class has an owning field, it also needs to have a finalizer method m
that disposes of the field and an @InheritableMustCall('m')
annotation on the class declaration. This contradicts the scenario I described
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 wasn't able to reproduce this issue because in the test infrastructure, the final result (after inference) should be type checked
It's possible to avoid this limitation in one of the following ways:
- use an
@SuppressWarnings
annotation to ignore the other warning that you don't care about testing - use the same mechanism in the
build.gradle
file that is used by theExpectedErrors.java
test case for theAinferTestChecker
: effectively, disable the removal of the expected warnings.
Of these two, I think in this situation, you should strongly prefer the former.
If you're not able to get this working, rather than a text-only response, can you include the full test case in your next comment on this thread so that I can try to get it working myself?
} | ||
|
||
/** | ||
* Computes @Owning annotations for the arguments or receiver of a call. |
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 it ever make sense for a receiver to be @Owning
? I don't think so (and I don't think we considered this case in our formalism at all): receivers are an object of the class that's currently being considered, so I'm not sure what an "owning receiver" means - maybe that the method with that receiver should be a must-call method of the class?
Regardless, I'm concerned that we have code for it at all, since it doesn't make sense to me.
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.
@kelloggm this is referring to the actual parameter passed in the receiver position at a call site, not this
inside a method. Does that help?
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 the clarification. Yes, this helps. I think we need to distinguish "receiver" (i.e., the self object this
of when discussing an instance method of a class) from the "receiver of a method invocation" (i.e., the actual argument passed in the receiver position at a call site). Maybe "receiver argument" would work? I think my confusion here could have been avoided if there was a comment noting this distinction at the first point that the receiver of the method invocation is mentioned here (although to be fair I probably should have figured this out myself from the code...)
checker/src/main/java/org/checkerframework/checker/resourceleak/MustCallInference.java
Show resolved
Hide resolved
* @param invocation the method or constructor invocation | ||
*/ | ||
private void computeOwningFromInvocation(Set<Obligation> obligations, Node invocation) { | ||
if (methodElt == 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.
A brief comment to explain this (seemingly-unrelated) check here would be helpful. methodElt
is a field of the class and might be unrelated to invocation
, right? So why does it need to be checked here?
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.
It's not actually dereferenced in the body of this method...
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.
It is used in addOwningToParam
. I can't recall if the null value here has caused any NPE in real benchmarks. Even if it does, I agree that here is not the best place to check this. I will remove it from here.
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 am happy with the current state of this PR and I believe it is ready to merge.
@mernst, please review my changes in 29cfb1f to a method that you wrote. I think it contained a bug, which I fixed: the intention seemed to be to print the actual elements of the collection, not to print a field of the current instance repeatedly. I also made the method static
to avoid that problem in the future.
Oops! Martin, thanks for fixing my bug. |
Co-authored-by: Michael Ernst <mernst@cs.washington.edu> Co-authored-by: Manu Sridharan <msridhar@gmail.com> Co-authored-by: Martin Kellogg <martin.kellogg@njit.edu>
This PR infers:
@Owning
annotation for owning fields and parameters.