Skip to content

Commit

Permalink
Implement subtyping for type variables created by capture conversion …
Browse files Browse the repository at this point in the history
…of `? super` wildcards.

- For the code in `isNullnessSubtype`, see
  ["`F` is a type-variable usage that meets _both_ of the following conditions...."](https://jspecify.dev/spec#:~:text=F%20is%20a%20type%2Dvariable%20usage%20that%20meets%20both%20of%20the%20following%20conditions%3A)
- For the code in `isNullInclusiveUnderEveryParameterization`, see
  ["It is a type variable that meets _both_ of the following conditions...."](https://jspecify.dev/spec#:~:text=It%20is%20a%20type%20variable%20that%20meets%20both%20of%20the%20following%20conditions%3A)

This code will never (or
[perhaps only _almost_ never](e80571b))
run under the current version of the checker, but it will become
necessary when we merge the upstream implementation of capture
conversion.
  • Loading branch information
cpovirk committed Mar 8, 2022
1 parent 2fda402 commit f23ec80
Showing 1 changed file with 14 additions and 5 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@
import static javax.lang.model.element.ElementKind.ENUM_CONSTANT;
import static javax.lang.model.type.TypeKind.ARRAY;
import static javax.lang.model.type.TypeKind.DECLARED;
import static javax.lang.model.type.TypeKind.TYPEVAR;
import static javax.lang.model.type.TypeKind.WILDCARD;
import static org.checkerframework.framework.qual.TypeUseLocation.CONSTRUCTOR_RESULT;
import static org.checkerframework.framework.qual.TypeUseLocation.EXCEPTION_PARAMETER;
Expand Down Expand Up @@ -444,6 +445,11 @@ private boolean isNullnessSubtype(AnnotatedTypeMirror subtype, AnnotatedTypeMirr
*/
return true;
}
if (supertype.getKind() == TYPEVAR
&& !supertype.hasAnnotation(minusNull)
&& isNullnessSubtype(subtype, ((AnnotatedTypeVariable) supertype).getLowerBound())) {
return true;
}
return isNullInclusiveUnderEveryParameterization(supertype)
|| isNullExclusiveUnderEveryParameterization(subtype)
|| (nullnessEstablishingPathExists(subtype, supertype)
Expand All @@ -452,6 +458,14 @@ private boolean isNullnessSubtype(AnnotatedTypeMirror subtype, AnnotatedTypeMirr
}

boolean isNullInclusiveUnderEveryParameterization(AnnotatedTypeMirror type) {
// We put the third case from the spec first because it's a mouthful.
// (As discussed in the spec, we probably don't strictly need this case at all....)
if (type.getKind() == TYPEVAR
&& !type.hasAnnotation(minusNull)
&& isNullInclusiveUnderEveryParameterization(
((AnnotatedTypeVariable) type).getLowerBound())) {
return true;
}
/*
* Our draft subtyping rules specify a special case for intersection types. However, those rules
* make sense only because the rules also specify that an intersection type never has an
Expand Down Expand Up @@ -562,11 +576,6 @@ private boolean nullnessEstablishingPathExists(
return true;
}
}
/*
* We don't need to handle the "lower-bound rule" here: The Checker Framework doesn't perform
* wildcard capture conversion. (Hmm, but it might see post-capture-conversion types in some
* cases....) It compares "? super Foo" against "Bar" by more directly comparing Foo and Bar.
*/
return false;
}

Expand Down

0 comments on commit f23ec80

Please sign in to comment.