Skip to content

Commit

Permalink
Implement substitution rules.
Browse files Browse the repository at this point in the history
Note that our substitution rules also have implications for usages of
type variables even *before* substitution. For example, CF considers
`@NullnessUnspecified T` to always "have unspecified nullness," and thus
it considers it safe to dereference in "lenient mode." In contrast, we
consider "unspecified nullness" to be only the *lower* bound, so we will
want to forbid dereferences (as it may be instantiated with a nullable
type argument).

Full handling of these implications will require additional changes,
likely including changes to CF itself.
  • Loading branch information
cpovirk committed Oct 9, 2020
1 parent 4b29bf2 commit 3db7615
Showing 1 changed file with 25 additions and 0 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -29,10 +29,13 @@
import org.checkerframework.framework.flow.CFTransfer;
import org.checkerframework.framework.flow.CFValue;
import org.checkerframework.framework.type.AnnotatedTypeFormatter;
import org.checkerframework.framework.type.AnnotatedTypeMirror;
import org.checkerframework.framework.type.AnnotatedTypeMirror.AnnotatedTypeVariable;
import org.checkerframework.framework.type.DefaultAnnotatedTypeFormatter;
import org.checkerframework.framework.type.ElementQualifierHierarchy;
import org.checkerframework.framework.type.GenericAnnotatedTypeFactory;
import org.checkerframework.framework.type.QualifierHierarchy;
import org.checkerframework.framework.type.TypeVariableSubstitutor;
import org.checkerframework.framework.util.AnnotationFormatter;
import org.checkerframework.framework.util.DefaultAnnotationFormatter;
import org.checkerframework.javacutil.AnnotationBuilder;
Expand Down Expand Up @@ -149,6 +152,28 @@ public AnnotationMirror greatestLowerBound(
}
}

@Override
protected TypeVariableSubstitutor createTypeVariableSubstitutor() {
return new NullSpecTypeVariableSubstitutor();
}

private final class NullSpecTypeVariableSubstitutor extends TypeVariableSubstitutor {
@Override
protected AnnotatedTypeMirror substituteTypeVariable(AnnotatedTypeMirror argument,
AnnotatedTypeVariable use) {
// TODO(cpovirk): Delegate to leastUpperBound?
AnnotatedTypeMirror substitute = argument.deepCopy(/*copyAnnotations=*/ true);
if (argument.hasAnnotation(unionNull) || use.hasAnnotation(unionNull)) {
substitute.replaceAnnotation(unionNull);
} else if (argument.hasAnnotation(codeNotNullnessAware) || use
.hasAnnotation(codeNotNullnessAware)) {
substitute.replaceAnnotation(codeNotNullnessAware);
}

return substitute;
}
}

@Override
protected AnnotationFormatter createAnnotationFormatter() {
return new DefaultAnnotationFormatter() {
Expand Down

0 comments on commit 3db7615

Please sign in to comment.