Fix initialization annotation of outer receiver with explicit annotation - #1253
Fix initialization annotation of outer receiver with explicit annotation#1253byd110 wants to merge 41 commits into
Conversation
…he outer receiver when possible during tree annotation.
…he previous run on my local system
….java Co-authored-by: Aosen Xiong <aosen.xiong@uwaterloo.ca>
# Conflicts: # checker/tests/nullness-enclosingexpr/NullnessEnclosingExprTest.java
wmdietl
left a comment
There was a problem hiding this comment.
Great, thanks for tracking this down and fixing this bug!
Please add an entry in the changelog, at least that the issue is fixed.
| exeType.getReturnType().replaceAnnotation(a); | ||
|
|
||
| // If the receiver type exists (meaning there is an enclosing type) and is | ||
| // annotated, then annotate the enclosing type with the same annotation. |
There was a problem hiding this comment.
The "enclosing type" reference is unclear. It looks like it is being added to the enclosing type of the return type of the method.
|
|
||
| // If the receiver type exists (meaning there is an enclosing type) and is | ||
| // annotated, then annotate the enclosing type with the same annotation. | ||
| // TODO: look into why there is this inconsistency between receiver type and |
There was a problem hiding this comment.
Is this a separate issue? Is this PR not fixing all of #412?
There was a problem hiding this comment.
I would classify this as a saparate issue. getEnclosingType returns the enclsoing type with the correct annotation, whereas the enclosing type in the receiver is not annotated.
This PR fully fixes the problem. The inconsistency only affacts the way to get the correct annotation.
I haven't looked into the root cause of this consistency. There is also no failing test cases to show this inconsistency would cause any problem.
| exeType.getReceiverType().getAnnotationInHierarchy(a); | ||
| AnnotatedDeclaredType ret = (AnnotatedDeclaredType) exeType.getReturnType(); | ||
| if (ret.getEnclosingType() != null) { | ||
| ret.getEnclosingType().addAnnotation(enclAnno); |
There was a problem hiding this comment.
The return type of a constructor can never be explicitly written in source code, right?
So there never can already be a manually written annotation on the enclosing type.
So using addAnnotation instead of the replaceAnnotation that is used above is always correct?
Can you write a short comment that hints at that?
| if (exeType.getReceiverType() != null) { | ||
| if (exeType.getReceiverType().hasAnnotationInHierarchy(a)) { |
There was a problem hiding this comment.
| if (exeType.getReceiverType() != null) { | |
| if (exeType.getReceiverType().hasAnnotationInHierarchy(a)) { | |
| if (exeType.getReceiverType() != null && exeType.getReceiverType().hasAnnotationInHierarchy(a)) { |
To reduce nesting levels.
| super(testFiles, NullnessChecker.class, "nullness", "-AcheckEnclosingExpr"); | ||
| } | ||
|
|
||
| /** |
There was a problem hiding this comment.
To write down what we discussed in person: This change wouldn't be strictly necessary.
However, our javadoc enforcement script sees that there is a change to a file NullnessEnclosingExprTest.java and doesn't take the full paths into account - there is another file with that base name in this PR.
This seems unlikely to occur frequently, so we're punting on the issue.
| } | ||
|
|
||
| Issue412a() { | ||
| new InnerWithUnknownInitializationEnclosingExpression(); |
There was a problem hiding this comment.
Can you add another class with a constructor that has no @UnknownInitialization Issue412a Issue412a.this receiver and call it here, to ensure we do get an error for that illegal invocation. (Or rename InnerWithUnknownInitializationEnclosingExpression and have two constructors in it.)
| } | ||
|
|
||
| class Inner { | ||
| /* The framework can correctly identify the outer class reciever type to be @H1Top. |
There was a problem hiding this comment.
| /* The framework can correctly identify the outer class reciever type to be @H1Top. | |
| /* The framework can correctly identify the outer class receiver type to be @H1Top. |
| @@ -0,0 +1,21 @@ | |||
| import org.checkerframework.framework.testchecker.h1h2checker.quals.*; | |||
|
|
|||
| // @skip-test | |||
There was a problem hiding this comment.
Should this be unskipped? If it should be skipped, is there a new issue you can reference?
There was a problem hiding this comment.
Yes, it should be unskipped. The error reported rules out the problem with general framework.
…ed with correct "-AcheckEnclosingExpr" flag
# Conflicts: # docs/CHANGELOG.md
# Conflicts: # docs/CHANGELOG.md
# Conflicts: # docs/CHANGELOG.md
# Conflicts: # docs/CHANGELOG.md
…anation, refine the comment in Issue412a test case
Problem description
fix #412. The explicit enclosing receiver annotation is captured by the receiver type of the constructor but not annotated in
InitializationParentAnnotatedTypeFactory.CommitmentTreeAnnotator#visitMethod.This yeild a false positive during the check if we specify the enclosing receiver to be
@UnknownInitialized, but in the method body check the type is the default@Initialized.Fix
If the method visiting has an annotated receiver type, then retrive the annotation and annotate the enclosing receiver with it.
Two test cases are added to check this edge case.
checker/tests/initialization/Issue412a.javachecks the fix is correct.framework/tests/h1h2checker/Issue412b.javamake sure the general framework can also catch this problem.