Skip to content
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

Fix polymorphism check and introduce the concept of PolymorphicInstanceSlot #381

Merged
merged 5 commits into from
Mar 1, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
23 changes: 19 additions & 4 deletions src/checkers/inference/DefaultSlotManager.java
Original file line number Diff line number Diff line change
Expand Up @@ -369,8 +369,11 @@ public int getNumberOfSlots() {
return nextId - 1;
}

@Override
public SourceVariableSlot createSourceVariableSlot(AnnotationLocation location, TypeMirror type) {
private SourceVariableSlot createSourceVariableSlot(
AnnotationLocation location,
TypeMirror type,
boolean insertable
) {
AnnotationMirror defaultAnnotation = null;
if (!InferenceOptions.makeDefaultsExplicit) {
// retrieve the default annotation when needed
Expand All @@ -381,7 +384,7 @@ public SourceVariableSlot createSourceVariableSlot(AnnotationLocation location,
if (location.getKind() == AnnotationLocation.Kind.MISSING) {
if (InferenceMain.isHackMode()) {
//Don't cache slot for MISSING LOCATION. Just create a new one and return.
sourceVarSlot = new SourceVariableSlot(nextId(), location, type, defaultAnnotation, true);
sourceVarSlot = new SourceVariableSlot(nextId(), location, type, defaultAnnotation, insertable);
addToSlots(sourceVarSlot);
} else {
throw new BugInCF("Creating SourceVariableSlot on MISSING_LOCATION!");
Expand All @@ -391,13 +394,25 @@ public SourceVariableSlot createSourceVariableSlot(AnnotationLocation location,
int id = locationCache.get(location);
sourceVarSlot = (SourceVariableSlot) getSlot(id);
} else {
sourceVarSlot = new SourceVariableSlot(nextId(), location, type, defaultAnnotation, true);
sourceVarSlot = new SourceVariableSlot(nextId(), location, type, defaultAnnotation, insertable);
addToSlots(sourceVarSlot);
locationCache.put(location, sourceVarSlot.getId());
}
return sourceVarSlot;
}

@Override
public SourceVariableSlot createSourceVariableSlot(AnnotationLocation location, TypeMirror type) {
return createSourceVariableSlot(location, type, true);
}

@Override
public VariableSlot createPolymorphicInstanceSlot(AnnotationLocation location, TypeMirror type) {
// TODO: For now, a polymorphic instance slot is just equivalent to a non-insertable
// source variable slot. We may consider changing this implementation later.
return createSourceVariableSlot(location, type, false);
}

/**
* Find the default annotation for this location by checking the real type factory.
* @param location location to create a new {@link SourceVariableSlot}
Expand Down
7 changes: 6 additions & 1 deletion src/checkers/inference/InferenceAnnotatedTypeFactory.java
Original file line number Diff line number Diff line change
Expand Up @@ -150,7 +150,12 @@ public InferenceAnnotatedTypeFactory(
existentialInserter = new ExistentialVariableInserter(slotManager, constraintManager,
realTop, varAnnot, variableAnnotator);

inferencePoly = new InferenceQualifierPolymorphism(slotManager, variableAnnotator, this, varAnnot);
inferencePoly = new InferenceQualifierPolymorphism(
slotManager,
variableAnnotator,
this,
realTypeFactory,
varAnnot);

constantToVariableAnnotator = new ConstantToVariableAnnotator(realTop, varAnnot);
// Every subclass must call postInit!
Expand Down
11 changes: 8 additions & 3 deletions src/checkers/inference/InferenceQualifierPolymorphism.java
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
package checkers.inference;

import checkers.inference.model.VariableSlot;
import org.checkerframework.common.basetype.BaseAnnotatedTypeFactory;
import org.checkerframework.framework.type.AnnotatedTypeMirror;
import org.checkerframework.framework.type.AnnotatedTypeMirror.AnnotatedExecutableType;
import org.checkerframework.framework.type.visitor.AnnotatedTypeScanner;
Expand All @@ -26,14 +28,17 @@ public class InferenceQualifierPolymorphism {
private final AnnotationMirror varAnnot;
private final SlotManager slotManager;
private final InferenceAnnotatedTypeFactory atypeFactory;
private final BaseAnnotatedTypeFactory realTypeFactory;

public InferenceQualifierPolymorphism(final SlotManager slotManager,
final VariableAnnotator variableAnnotator,
final InferenceAnnotatedTypeFactory atypeFactory,
final BaseAnnotatedTypeFactory realTypeFactory,
final AnnotationMirror varAnnot) {
this.slotManager = slotManager;
this.variableAnnotator = variableAnnotator;
this.atypeFactory = atypeFactory;
this.realTypeFactory = realTypeFactory;
this.varAnnot = varAnnot;
}

Expand All @@ -57,13 +62,13 @@ private class PolyReplacer extends AnnotatedTypeScanner<Void, Void> {
/**
* The variable slot created for this method call
*/
private SourceVariableSlot polyVar = null;
private VariableSlot polyVar = null;

private PolyReplacer(Tree methodCall) {
this.methodCall = methodCall;
}

private SourceVariableSlot getOrCreatePolyVar() {
private VariableSlot getOrCreatePolyVar() {
if (polyVar == null) {
polyVar = variableAnnotator.getOrCreatePolyVar(methodCall);
}
Expand All @@ -80,7 +85,7 @@ public Void scan(AnnotatedTypeMirror type, Void v) {
if (InferenceMain.isHackMode(slot == null)) {
} else if (slot instanceof ConstantSlot) {
AnnotationMirror constant = ((ConstantSlot) slot).getValue();
if (atypeFactory.getQualifierHierarchy().isPolymorphicQualifier(constant)) {
if (realTypeFactory.getQualifierHierarchy().isPolymorphicQualifier(constant)) {
type.replaceAnnotation(slotManager.getAnnotation(getOrCreatePolyVar()));
}
}
Expand Down
13 changes: 13 additions & 0 deletions src/checkers/inference/SlotManager.java
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,19 @@ public interface SlotManager {
*/
SourceVariableSlot createSourceVariableSlot(AnnotationLocation location, TypeMirror type);

/**
* Create new VariableSlot and return the reference to it if no VariableSlot
* on this location exists. Otherwise return the reference to existing VariableSlot
* on this location. Each location uniquely identifies a polymorphic instance.
* For now, there's no dedicated slot for polymorphic instance, but we may add one
* in the future.
*
* @param location
* used to locate this variable in code
* @return VariableSlot that corresponds to this location
*/
VariableSlot createPolymorphicInstanceSlot(AnnotationLocation location, TypeMirror type);

/**
* Create new RefinementVariableSlot (as well as the refinement constraint if
* possible) and return the reference to it if no RefinementVariableSlot on this
Expand Down
8 changes: 4 additions & 4 deletions src/checkers/inference/VariableAnnotator.java
Original file line number Diff line number Diff line change
Expand Up @@ -134,7 +134,7 @@ public class VariableAnnotator extends AnnotatedTypeScanner<Void,Tree> {
* methodCall -> variable created to represent Poly qualifiers
* See InferenceQualifierPolymorphism.
*/
private final Map<Tree, SourceVariableSlot> treeToPolyVar;
private final Map<Tree, VariableSlot> treeToPolyVar;

// An instance of @VarAnnot
private final AnnotationMirror varAnnot;
Expand Down Expand Up @@ -206,10 +206,10 @@ protected AnnotationLocation treeToLocation(Tree tree) {
* one and return it, if we haven't created one for the given tree. see InferenceQualifierPolymorphism
* @return The Variable representing PolymorphicQualifier for the given tree
*/
public SourceVariableSlot getOrCreatePolyVar(Tree tree) {
SourceVariableSlot polyVar = treeToPolyVar.get(tree);
public VariableSlot getOrCreatePolyVar(Tree tree) {
VariableSlot polyVar = treeToPolyVar.get(tree);
if (polyVar == null) {
polyVar = slotManager.createSourceVariableSlot(treeToLocation(tree), TreeUtils.typeOf(tree));
polyVar = slotManager.createPolymorphicInstanceSlot(treeToLocation(tree), TreeUtils.typeOf(tree));
treeToPolyVar.put(tree, polyVar);
}

Expand Down