public void endVisit(JBinaryOperation x, Context ctx) {
if (x.getOp().isAssignment() && x.getLhs() instanceof JArrayRef) {
// first, calculate the transitive closure of all possible runtime types
// the lhs could be
JArrayRef lhsArrayRef = (JArrayRef) x.getLhs();
JType elementType = lhsArrayRef.getType();
if (elementType instanceof JNullType) {
// will generate a null pointer exception instead
return;
}
// primitives are statically correct
if (!(elementType instanceof JReferenceType)) {
return;
}
// element type being final means the assignment is statically correct
if (elementType.isFinal()) {
return;
}
/*
* For every instantiated array type that could -in theory- be the
* runtime type of the lhs, we must record a cast from the rhs to the
* prospective element type of the lhs.
*/
JType rhsType = x.getRhs().getType();
assert (rhsType instanceof JReferenceType);
JArrayType lhsArrayType = lhsArrayRef.getArrayType();
for (JArrayType arrayType : instantiatedArrayTypes) {
if (typeOracle.canTheoreticallyCast(arrayType, lhsArrayType)) {
JType itElementType = arrayType.getElementType();
if (itElementType instanceof JReferenceType) {
recordCast(itElementType, x.getRhs());