<T extends Expression> SpecializedNode specialize(final Assignment<T> assignment) { final Node node = ((Node)assignment); final T lhs = assignment.getAssignmentDest(); final Expression rhs = assignment.getAssignmentSource(); if (!canHaveCallSiteType(lhs)) { return new SpecializedNode(node, null); } final Type to; if (node.isSelfModifying()) { to = node.getWidestOperationType(); } else { to = rhs.getType(); } if (!isSupportedCallSiteType(to)) { //meaningless to specialize to boolean or object return new SpecializedNode(node, null); } final Node newNode = assignment.setAssignmentDest(setTypeOverride(lhs, to)); final Node typePropagatedNode; if(newNode instanceof Expression) { typePropagatedNode = propagateType((Expression)newNode, to); } else if(newNode instanceof VarNode) { // VarNode, being a statement, doesn't have its own symbol; it uses the symbol of its name instead. final VarNode varNode = (VarNode)newNode; typePropagatedNode = varNode.setName((IdentNode)propagateType(varNode.getName(), to)); } else { throw new AssertionError(); } return new SpecializedNode(typePropagatedNode, to); }