*/
private void tighten(JVariable x) {
if (!(x.getType() instanceof JReferenceType)) {
return;
}
JReferenceType refType = (JReferenceType) x.getType();
if (refType == typeNull) {
return;
}
// tighten based on non-instantiability
if (!program.typeOracle.isInstantiatedType(refType)) {
x.setType(typeNull);
myDidChange = true;
return;
}
// tighten based on assignment
List/* <JReferenceType> */typeList = new ArrayList/* <JReferenceType> */();
/*
* For non-parameters, always assume at least one null assignment; if
* there really aren't any other assignments, then this variable will get
* the null type. If there are, it won't hurt anything because null type
* will always lose.
*
* For parameters, don't perform any tightening if we can't find any
* actual assignments. The method should eventually get pruned.
*/
if (!(x instanceof JParameter)) {
typeList.add(typeNull);
}
Set/* <JExpression> */myAssignments = (Set) assignments.get(x);
if (myAssignments != null) {
for (Iterator iter = myAssignments.iterator(); iter.hasNext();) {
JExpression expr = (JExpression) iter.next();
JType type = expr.getType();
if (!(type instanceof JReferenceType)) {
return; // something fishy is going on, just abort
}
typeList.add(type);
}
}
if (x instanceof JParameter) {
Set/* <JParameter> */myParams = (Set) paramUpRefs.get(x);
if (myParams != null) {
for (Iterator iter = myParams.iterator(); iter.hasNext();) {
JParameter param = (JParameter) iter.next();
typeList.add(param.getType());
}
}
}
if (typeList.isEmpty()) {
return;
}
JReferenceType resultType = program.generalizeTypes(typeList);
resultType = program.strongerType(refType, resultType);
if (refType != resultType) {
x.setType(resultType);
myDidChange = true;
}