-
Notifications
You must be signed in to change notification settings - Fork 29
Handle intersection type in viewpoint adaptation #1434
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
base: master
Are you sure you want to change the base?
Changes from all commits
e77c3c7
faa762e
61bad4f
e6ed628
5aac11f
54215a0
3a53122
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -367,6 +367,19 @@ protected AnnotatedTypeMirror combineAnnotationWithType( | |
| receiverAnnotation, extractAnnotationMirror(ant)); | ||
| ant.replaceAnnotation(resultAnnotation); | ||
| return ant; | ||
| } else if (declared.getKind() == TypeKind.INTERSECTION) { | ||
| AnnotatedTypeMirror.AnnotatedIntersectionType intersection = | ||
| (AnnotatedTypeMirror.AnnotatedIntersectionType) declared.shallowCopy(true); | ||
| List<AnnotatedTypeMirror> listBounds = intersection.getBounds(); | ||
| List<AnnotatedTypeMirror> listBoundsCopy = new ArrayList<>(listBounds); | ||
| for (int i = 0; i < listBoundsCopy.size(); i++) { | ||
| AnnotatedTypeMirror bound = listBoundsCopy.get(i); | ||
| AnnotatedTypeMirror combinedBound = | ||
| combineAnnotationWithType(receiverAnnotation, bound); | ||
| listBoundsCopy.set(i, combinedBound); | ||
| } | ||
| intersection.setBounds(listBoundsCopy); | ||
| return intersection; | ||
| } else { | ||
| throw new BugInCF( | ||
| "ViewpointAdapter::combineAnnotationWithType: Unknown decl: " | ||
|
|
@@ -451,6 +464,18 @@ private AnnotatedTypeMirror substituteTVars(AnnotatedTypeMirror lhs, AnnotatedTy | |
| rhs = AnnotatedTypeCopierWithReplacement.replace(aat, mappings); | ||
| } else if (rhs.getKind().isPrimitive() || rhs.getKind() == TypeKind.NULL) { | ||
| // nothing to do for primitive types and the null type | ||
| } else if (rhs.getKind() == TypeKind.INTERSECTION) { | ||
| AnnotatedTypeMirror.AnnotatedIntersectionType intersection = | ||
| (AnnotatedTypeMirror.AnnotatedIntersectionType) rhs.shallowCopy(true); | ||
| List<AnnotatedTypeMirror> listBounds = intersection.getBounds(); | ||
| List<AnnotatedTypeMirror> listBoundsCopy = new ArrayList<>(listBounds); | ||
| for (int i = 0; i < listBoundsCopy.size(); i++) { | ||
| AnnotatedTypeMirror bound = listBoundsCopy.get(i); | ||
| AnnotatedTypeMirror substBound = substituteTVars(lhs, bound); | ||
| listBoundsCopy.set(i, substBound); | ||
| } | ||
| intersection.setBounds(listBoundsCopy); | ||
| rhs = intersection; | ||
|
Comment on lines
+468
to
+478
|
||
| } else { | ||
| throw new BugInCF( | ||
| "ViewpointAdapter::substituteTVars: Cannot handle rhs: " | ||
|
|
||
| Original file line number | Diff line number | Diff line change | ||||
|---|---|---|---|---|---|---|
| @@ -0,0 +1,33 @@ | ||||||
| // Test case for EISOP Issue 433: | ||||||
| // https://github.com/eisop/checker-framework/issues/433 | ||||||
|
|
||||||
| import viewpointtest.quals.*; | ||||||
|
|
||||||
| public class IntersectionTypes { | ||||||
|
|
||||||
| interface Foo {} | ||||||
|
|
||||||
| interface Bar {} | ||||||
|
|
||||||
| class Baz implements Foo, Bar {} | ||||||
|
|
||||||
| <T extends Foo & Bar> void call(T p) {} | ||||||
|
|
||||||
| void foo() { | ||||||
| // :: warning: (cast.unsafe.constructor.invocation) | ||||||
| Baz baz = new @A Baz(); | ||||||
| call(baz); | ||||||
| } | ||||||
|
|
||||||
| interface B<X> {} | ||||||
|
|
||||||
| interface C<X> {} | ||||||
|
|
||||||
| abstract class D<X extends B<X> & C<X>> {} | ||||||
|
|
||||||
| class BC implements B<BC>, C<BC> {} | ||||||
|
|
||||||
| class E extends D<BC> {} | ||||||
|
|
||||||
| <T extends B<T> & C<T>> void call(T p) {} | ||||||
|
||||||
| <T extends B<T> & C<T>> void call(T p) {} | |
| <T extends B<T> & C<T>> void callBC(T p) {} |
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.
AnnotatedIntersectionType.shallowCopy(true)copies primary annotations viaaddAnnotations, andAnnotatedIntersectionType.addAnnotationpropagates them to the (shared) bounds list. BecauseshallowCopyalso sharesbounds(type.bounds = this.bounds), this can mutate the originaldeclaredbounds, and the returned intersection's primary annotations can become inconsistent after you replace bounds with viewpoint-adapted ones. To keep this method side-effect free and consistent, construct the copy without copying annotations (e.g.,shallowCopy(false)ordeepCopy(false)), adapt bounds, set them, then recompute primary annotations from the new bounds (e.g.,clearAnnotations()+copyIntersectionBoundAnnotations()).