Skip to content

Commit e4ced88

Browse files
committed
commits for fixing PICO-TypeCheck and part of PICO-Infer
1 parent 6e4e3c6 commit e4ced88

21 files changed

Lines changed: 338 additions & 298 deletions

build.gradle

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -50,6 +50,8 @@ sourceSets {
5050
main {
5151
java {
5252
srcDirs = ["src/main/java"]
53+
exclude "pico/inference/**"
54+
5355
}
5456

5557
resources {
@@ -62,6 +64,8 @@ sourceSets {
6264
java {
6365
// TODO: we shouldn't need source level dependency on CFITest
6466
srcDirs = ["src/test/java", "${cfiPath}/tests/checkers/inference/test"]
67+
exclude "pico/ImmutabilityInferenceInitialTypecheckTest.java","pico/ImmutabilityReImInferenceTest.java",
68+
"pico/ImmutabilityInferenceTest.java"
6569
}
6670
}
6771
}

src/main/java/pico/inference/PICOInferenceChecker.java

Lines changed: 2 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,6 @@
11
package pico.inference;
22

3-
import checkers.inference.BaseInferrableChecker;
4-
import checkers.inference.InferenceAnnotatedTypeFactory;
5-
import checkers.inference.InferenceChecker;
6-
import checkers.inference.InferenceVisitor;
7-
import checkers.inference.InferrableChecker;
8-
import checkers.inference.SlotManager;
3+
import checkers.inference.*;
94
import checkers.inference.model.ConstraintManager;
105
import org.checkerframework.common.basetype.BaseAnnotatedTypeFactory;
116
import org.checkerframework.framework.source.SupportedOptions;
@@ -24,7 +19,7 @@ public void initChecker() {
2419
}
2520

2621
@Override
27-
public BaseAnnotatedTypeFactory createRealTypeFactory() {
22+
public BaseInferenceRealTypeFactory createRealTypeFactory(boolean infer) {
2823
return new PICOInferenceRealTypeFactory(this, true);
2924
}
3025

src/main/java/pico/inference/PICOInferenceRealTypeFactory.java

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@
1616
import javax.lang.model.type.TypeMirror;
1717
import javax.lang.model.util.Elements;
1818

19+
import checkers.inference.BaseInferenceRealTypeFactory;
1920
import com.sun.tools.javac.tree.JCTree;
2021
import org.checkerframework.common.basetype.BaseAnnotatedTypeFactory;
2122
import org.checkerframework.common.basetype.BaseTypeChecker;
@@ -58,7 +59,7 @@
5859
* to InitializationAnnotatedTypeFactory as if there is only one mutability qualifier hierarchy.
5960
* This class has lots of copied code from PICOAnnotatedTypeFactory. The two should be in sync.
6061
*/
61-
public class PICOInferenceRealTypeFactory extends BaseAnnotatedTypeFactory implements ViewpointAdapterGettable {
62+
public class PICOInferenceRealTypeFactory extends BaseInferenceRealTypeFactory implements ViewpointAdapterGettable {
6263

6364
private static final List<String> IMMUTABLE_ALIASES = Arrays.asList(
6465
"com.google.errorprone.annotations.Immutable",
@@ -226,7 +227,7 @@ public AnnotatedTypeMirror getTypeOfExtendsImplements(Tree clause) {
226227

227228
}
228229
AnnotationMirror mainBound = enclosing.getAnnotationInHierarchy(READONLY);
229-
AnnotatedTypeMirror fromTypeTree = this.fromTypeTree(clause);
230+
AnnotatedTypeMirror fromTypeTree = this.getAnnotatedTypeFromTypeTree(clause);
230231
if (!fromTypeTree.isAnnotatedInHierarchy(READONLY)) {
231232
fromTypeTree.addAnnotation(mainBound);
232233
}

src/main/java/pico/inference/PICOInferenceVisitor.java

Lines changed: 22 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -148,6 +148,7 @@ private boolean isAdaptedSubtype(AnnotatedTypeMirror lhs, AnnotatedTypeMirror rh
148148
if (extractVarAnnot(lhs).equals(extractVarAnnot(rhs))) {
149149
return true;
150150
}
151+
// todo: haifeng we should do the viewpointAdapt in baseTypeValidator.java#visitDeclared 299 function:getTypeDeclarationBounds
151152
ExtendedViewpointAdapter vpa = ((ViewpointAdapterGettable)atypeFactory).getViewpointAdapter();
152153
AnnotatedTypeMirror adapted = vpa.rawCombineAnnotationWithType(extractVarAnnot(lhs),
153154
rhs);
@@ -494,7 +495,22 @@ public Void visitMethod(MethodTree node, Void p) {
494495
// TODO Object identity check
495496
return super.visitMethod(node, p);
496497
}
497-
498+
/*
499+
* @RDM
500+
* class A <T> {
501+
*
502+
* void foo(T) {
503+
*
504+
* }
505+
* }
506+
* class B extends @Immutable A<@X String> {
507+
*
508+
* @Override
509+
* void foo(@Y String) { // string is compatible to bound of T. Adapt the signature of Class A to the use of class B.
510+
* }
511+
* }
512+
*
513+
* */
498514
private void flexibleOverrideChecker(MethodTree node) {
499515
// Method overriding checks
500516
// TODO Copied from super, hence has lots of duplicate code with super. We need to
@@ -520,7 +536,7 @@ private void flexibleOverrideChecker(MethodTree node) {
520536
types, atypeFactory, enclosingType, pair.getValue());
521537
// Viewpoint adapt super method executable type to current class bound(is this always class bound?)
522538
// to allow flexible overriding
523-
atypeFactory.getViewpointAdapter().viewpointAdaptMethod(enclosingType, pair.getValue() , overriddenMethod);
539+
atypeFactory.getViewpointAdapter().viewpointAdaptMethod(enclosingType, pair.getValue() , overriddenMethod); // todo: should we cast it?
524540
AnnotatedExecutableType overrider = atypeFactory.getAnnotatedType(node);
525541
if (!checkOverride(node, overrider, enclosingType, overriddenMethod, overriddenType)) {
526542
// Stop at the first mismatch; this makes a difference only if
@@ -707,7 +723,7 @@ private void checkAssignableField(ExpressionTree node, ExpressionTree variable,
707723
}
708724
}
709725

710-
private void checkInitializingObject(ExpressionTree node, ExpressionTree variable, AnnotatedTypeMirror receiverType) {
726+
private void checkInitializingObject(ExpressionTree node, ExpressionTree variable, AnnotatedTypeMirror receiverType) { // todo: haifeng we only need to do this in one statement
711727
// TODO rm infer after mainIsNot returns bool
712728
if (infer) {
713729
// Can be anything from mutable, immutable or receiverdependantmutable
@@ -718,7 +734,7 @@ private void checkInitializingObject(ExpressionTree node, ExpressionTree variabl
718734
}
719735
}
720736
}
721-
737+
// todo: haifeng: the deciding factor seems to be if it is array or not. Not infer.
722738
private void checkMutableReceiverCase(ExpressionTree node, ExpressionTree variable, AnnotatedTypeMirror receiverType) {
723739
// TODO rm infer after mainIs returns bool
724740
if (infer) {
@@ -1004,7 +1020,7 @@ private boolean checkCompatabilityBetweenBoundAndSuperClassesBounds(ClassTree no
10041020
*/
10051021
@Override
10061022
protected void commonAssignmentCheck(
1007-
Tree varTree, ExpressionTree valueExp, String errorKey) {
1023+
Tree varTree, ExpressionTree valueExp, String errorKey, Object... extraArgs) {
10081024
AnnotatedTypeMirror var = atypeFactory.getAnnotatedTypeLhs(varTree);
10091025
assert var != null : "no variable found for tree: " + varTree;
10101026

@@ -1043,7 +1059,7 @@ protected void commonAssignmentCheck(
10431059
@Override
10441060
protected void commonAssignmentCheck(AnnotatedTypeMirror varType,
10451061
AnnotatedTypeMirror valueType, Tree valueTree,
1046-
String errorKey) {
1062+
String errorKey, Object... extraArgs) {
10471063
// TODO: WORKAROUND: anonymous class handling
10481064
if (TypesUtils.isAnonymous(valueType.getUnderlyingType())) {
10491065
AnnotatedTypeMirror newValueType = varType.deepCopy();

src/main/java/pico/inference/PICOVariableAnnotator.java

Lines changed: 87 additions & 90 deletions
Original file line numberDiff line numberDiff line change
@@ -45,80 +45,80 @@ public PICOVariableAnnotator(InferenceAnnotatedTypeFactory typeFactory, Annotate
4545
super(typeFactory, realTypeFactory, realChecker, slotManager, constraintManager);
4646
}
4747

48-
@Override
49-
protected void handleClassDeclaration(AnnotatedDeclaredType classType, ClassTree classTree) {
50-
super.handleClassDeclaration(classType, classTree);
51-
int interfaceIndex = 1;
52-
for(Tree implementsTree : classTree.getImplementsClause()) {
53-
final AnnotatedTypeMirror implementsType = inferenceTypeFactory.getAnnotatedTypeFromTypeTree(implementsTree);
54-
AnnotatedTypeMirror supertype = classType.directSuperTypes().get(interfaceIndex);
55-
assert supertype.getUnderlyingType() == implementsType.getUnderlyingType();
56-
visit(supertype, implementsTree);
57-
interfaceIndex++;
58-
}
59-
}
60-
61-
@Override
62-
protected void handleClassDeclarationBound(AnnotatedDeclaredType classType) {
63-
TypeElement classElement = (TypeElement) classType.getUnderlyingType().asElement();
64-
if (classDeclAnnos.containsKey(classElement)) {
65-
classType.addAnnotation(slotManager.getAnnotation(classDeclAnnos.get(classElement)));
66-
classType.addAnnotation(READONLY);
67-
return;
68-
}
69-
AnnotatedDeclaredType bound = inferenceTypeFactory.fromElement(classElement);
70-
71-
VariableSlot boundSlot;
72-
73-
// Insert @Immutable VarAnnot directly to enum bound
74-
// if (PICOTypeUtil.isEnumOrEnumConstant(bound)) {
75-
// boundSlot = slotManager.createConstantSlot(IMMUTABLE);
76-
// classType.addAnnotation(slotManager.getAnnotation(boundSlot));
77-
// classDeclAnnos.put(classElement, boundSlot);
48+
// @Override
49+
// protected void handleClassDeclaration(AnnotatedDeclaredType classType, ClassTree classTree) {
50+
// super.handleClassDeclaration(classType, classTree);
51+
// int interfaceIndex = 1;
52+
// for(Tree implementsTree : classTree.getImplementsClause()) {
53+
// final AnnotatedTypeMirror implementsType = inferenceTypeFactory.getAnnotatedTypeFromTypeTree(implementsTree);
54+
// AnnotatedTypeMirror supertype = classType.directSupertypes().get(interfaceIndex);
55+
// assert supertype.getUnderlyingType() == implementsType.getUnderlyingType();
56+
// visit(supertype, implementsTree);
57+
// interfaceIndex++;
58+
// }
59+
// }
60+
61+
// @Override
62+
// protected void handleClassDeclarationBound(AnnotatedDeclaredType classType) {
63+
// TypeElement classElement = (TypeElement) classType.getUnderlyingType().asElement();
64+
// if (classDeclAnnos.containsKey(classElement)) {
65+
// classType.addAnnotation(slotManager.getAnnotation(classDeclAnnos.get(classElement)));
66+
// classType.addAnnotation(READONLY);
7867
// return;
7968
// }
80-
81-
Tree classTree = inferenceTypeFactory.declarationFromElement(classElement);
82-
if (classTree != null) {
83-
// Have source tree
84-
if (bound.isAnnotatedInHierarchy(READONLY)) {
85-
// Have bound annotation -> convert to equivalent ConstantSlot
86-
boundSlot = slotManager.createConstantSlot(bound.getAnnotationInHierarchy(READONLY));
87-
} else {
88-
// No existing annotation -> create new VariableSlot
89-
boundSlot = createVariable(treeToLocation(classTree));
90-
}
91-
} else {
92-
// No source tree: bytecode classes
93-
if (bound.isAnnotatedInHierarchy(READONLY)) {
94-
// Have bound annotation in stub file
95-
boundSlot = slotManager.createConstantSlot(bound.getAnnotationInHierarchy(READONLY));
96-
} else {
97-
// No stub file
98-
if (PICOTypeUtil.isImplicitlyImmutableType(classType)) {
99-
// Implicitly immutable
100-
boundSlot = slotManager.createConstantSlot(IMMUTABLE);
101-
} else {
102-
// None of the above applies: use conservative @Mutable
103-
boundSlot = slotManager.createConstantSlot(MUTABLE);
104-
}
105-
}
106-
}
107-
classType.addAnnotation(slotManager.getAnnotation(boundSlot));
108-
classDeclAnnos.put(classElement, boundSlot);
109-
}
69+
// AnnotatedDeclaredType bound = inferenceTypeFactory.fromElement(classElement);
70+
//
71+
// VariableSlot boundSlot;
72+
//
73+
// // Insert @Immutable VarAnnot directly to enum bound
74+
//// if (PICOTypeUtil.isEnumOrEnumConstant(bound)) {
75+
//// boundSlot = slotManager.createConstantSlot(IMMUTABLE);
76+
//// classType.addAnnotation(slotManager.getAnnotation(boundSlot));
77+
//// classDeclAnnos.put(classElement, boundSlot);
78+
//// return;
79+
//// }
80+
//
81+
// Tree classTree = inferenceTypeFactory.declarationFromElement(classElement);
82+
// if (classTree != null) {
83+
// // Have source tree
84+
// if (bound.isAnnotatedInHierarchy(READONLY)) {
85+
// // Have bound annotation -> convert to equivalent ConstantSlot
86+
// boundSlot = slotManager.createConstantSlot(bound.getAnnotationInHierarchy(READONLY));
87+
// } else {
88+
// // No existing annotation -> create new VariableSlot
89+
// boundSlot = createVariable(treeToLocation(classTree));
90+
// }
91+
// } else {
92+
// // No source tree: bytecode classes
93+
// if (bound.isAnnotatedInHierarchy(READONLY)) {
94+
// // Have bound annotation in stub file
95+
// boundSlot = slotManager.createConstantSlot(bound.getAnnotationInHierarchy(READONLY));
96+
// } else {
97+
// // No stub file
98+
// if (PICOTypeUtil.isImplicitlyImmutableType(classType)) {
99+
// // Implicitly immutable
100+
// boundSlot = slotManager.createConstantSlot(IMMUTABLE);
101+
// } else {
102+
// // None of the above applies: use conservative @Mutable
103+
// boundSlot = slotManager.createConstantSlot(MUTABLE);
104+
// }
105+
// }
106+
// }
107+
// classType.addAnnotation(slotManager.getAnnotation(boundSlot));
108+
// classDeclAnnos.put(classElement, boundSlot);
109+
// }
110110

111111
@Override
112112
protected VariableSlot getOrCreateDeclBound(AnnotatedDeclaredType type) {
113113
TypeElement classDecl = (TypeElement) type.getUnderlyingType().asElement();
114114

115-
VariableSlot declSlot = classDeclAnnos.get(classDecl);
115+
AnnotationMirror declSlot = getClassDeclVarAnnot(classDecl);
116116
if (declSlot == null) {
117117
// if a explicit annotation presents on the class DECL, use that directly
118118
if (type.isDeclaration() && type.isAnnotatedInHierarchy(READONLY) && !type.hasAnnotation(READONLY)) {
119119
VariableSlot constantSlot = (VariableSlot) slotManager.getSlot(type.getAnnotationInHierarchy(READONLY));
120120
// TypeElement classDecl = (TypeElement) type.getUnderlyingType().asElement();
121-
classDeclAnnos.put(classDecl, constantSlot);
121+
super.getOrCreateDeclBound(type);
122122
// // avoid duplicate annos
123123
// type.removeAnnotationInHierarchy(READONLY);
124124
return constantSlot;
@@ -134,21 +134,21 @@ protected VariableSlot getOrCreateDeclBound(AnnotatedDeclaredType type) {
134134
return (VariableSlot) slotManager.getSlot(type.getAnnotation(VarAnnot.class));
135135
}
136136
}
137-
return super.getOrCreateDeclBound(type);
137+
return (VariableSlot) super.getOrCreateDeclBound(type);
138138
}
139139

140-
@Override
141-
protected void handleExplicitExtends(Tree extendsTree) {
142-
// PICO cannot use base extends handling: not simply subtype relationship because of RDM
143-
// Constraints already generated in processClassTree
144-
}
140+
// @Override
141+
// protected void handleExplicitExtends(Tree extendsTree) {
142+
// // PICO cannot use base extends handling: not simply subtype relationship because of RDM
143+
// // Constraints already generated in processClassTree
144+
// }
145145

146146
@Override
147147
public void storeElementType(Element element, AnnotatedTypeMirror atm) {
148148
// this method is override the behavior of super.handleClassDeclaration before storing
149149
// find a better way
150150

151-
Slot slot = slotManager.getVariableSlot(atm);
151+
Slot slot = slotManager.getSlot(atm);
152152
// do not use potential slot generated on the class decl annotation
153153
// PICO always have a annotation on the class bound, so Existential should always exist
154154
// TODO make VariableAnnotator::getOrCreateDeclBound protected and override that instead of this method
@@ -167,22 +167,22 @@ public void storeElementType(Element element, AnnotatedTypeMirror atm) {
167167
}
168168

169169
// Don't generate subtype constraint between use type and bound type
170-
@Override
171-
protected void handleInstantiationConstraint(AnnotatedTypeMirror.AnnotatedDeclaredType adt, VariableSlot instantiationSlot, Tree tree) {
172-
return;
173-
}
174-
175-
@Override
176-
protected VariableSlot addPrimaryVariable(AnnotatedTypeMirror atm, Tree tree) {
177-
// if (PICOTypeUtil.isEnumOrEnumConstant(atm)) {
178-
// // Don't add new VarAnnot to type use of enum type
179-
// PICOTypeUtil.applyConstant(atm, IMMUTABLE);
170+
// @Override
171+
// protected void handleInstantiationConstraint(AnnotatedTypeMirror.AnnotatedDeclaredType adt, VariableSlot instantiationSlot, Tree tree) {
172+
// return;
173+
// }
174+
175+
// @Override
176+
// protected VariableSlot addPrimaryVariable(AnnotatedTypeMirror atm, Tree tree) {
177+
//// if (PICOTypeUtil.isEnumOrEnumConstant(atm)) {
178+
//// // Don't add new VarAnnot to type use of enum type
179+
//// PICOTypeUtil.applyConstant(atm, IMMUTABLE);
180+
//// }
181+
// if (atm instanceof AnnotatedTypeMirror.AnnotatedNullType) {
182+
// PICOTypeUtil.applyConstant(atm, BOTTOM);
180183
// }
181-
if (atm instanceof AnnotatedTypeMirror.AnnotatedNullType) {
182-
PICOTypeUtil.applyConstant(atm, BOTTOM);
183-
}
184-
return super.addPrimaryVariable(atm, tree);
185-
}
184+
// return super.addPrimaryVariable(atm, tree);
185+
// }
186186

187187
// Generates inequality constraint between every strict VariableSlot and @Bottom so that @Bottom is not inserted
188188
// back to source code, but can be within the internal state because of dataflow refinement
@@ -285,7 +285,7 @@ public Void visitWildcard(AnnotatedTypeMirror.AnnotatedWildcardType wildcardType
285285

286286
@Override
287287
public void handleBinaryTree(AnnotatedTypeMirror atm, BinaryTree binaryTree) {
288-
if (atm.isAnnotatedInHierarchy(varAnnot)) {
288+
if (atm.isAnnotatedInHierarchy(inferenceTypeFactory.getVarAnnot())) {
289289
// Happens for binary trees whose atm is implicitly immutable and already handled by
290290
// PICOInferencePropagationTreeAnnotator
291291
return;
@@ -294,15 +294,12 @@ public void handleBinaryTree(AnnotatedTypeMirror atm, BinaryTree binaryTree) {
294294
}
295295

296296
public AnnotationMirror getClassDeclAnno(Element ele) {
297-
if (classDeclAnnos.get(ele) != null) {
298-
return slotManager.getAnnotation(classDeclAnnos.get(ele));
299-
}
300-
return null;
297+
return getClassDeclVarAnnot((TypeElement) ele); // todo: solved
301298
}
302299

303300

304301
@Override
305-
protected void addDeclarationConstraints(VariableSlot declSlot, VariableSlot instanceSlot) {
302+
protected void addDeclarationConstraints(Slot declSlot, Slot instanceSlot) {
306303
// RDM-related constraints cannot use subtype.
307304
// Necessary constraints added in visitor instead.
308305
}

0 commit comments

Comments
 (0)