public @NotNull DfType getBinOpRange(DfaBinOpValue binOp) {
    DfIntegralType leftType = ObjectUtils.tryCast(getDfType(binOp.getLeft()), DfIntegralType.class);
    DfIntegralType rightType = ObjectUtils.tryCast(getDfType(binOp.getRight()), DfIntegralType.class);
    if (leftType == null || rightType == null) return binOp.getDfType();
    LongRangeSet left = leftType.getRange();
    LongRangeSet right = rightType.getRange();
    LongRangeBinOp op = binOp.getOperation();
    DfIntegralType result = ObjectUtils.tryCast(leftType.eval(rightType, op), DfIntegralType.class);
    if (result == null) {
      result = binOp.getDfType();
    }
    if (op == LongRangeBinOp.MINUS) {
      RelationType rel = getRelation(binOp.getLeft(), binOp.getRight());
      if (rel == RelationType.NE) {
        return result.meetRange(LongRangeSet.all().without(0));
      }
      if (!left.subtractionMayOverflow(right, result.getLongRangeType())) {
        if (rel == RelationType.GT) {
          return result.meetRange(LongRangeSet.range(1, Long.MAX_VALUE));
        }
        if (rel == RelationType.LT) {
          return result.meetRange(LongRangeSet.range(Long.MIN_VALUE, -1));
        }
      }
    }
    if (op == LongRangeBinOp.PLUS && areEqual(binOp.getLeft(), binOp.getRight())) {
      return leftType.eval(binOp.getDfType().meetRange(LongRangeSet.point(2)), LongRangeBinOp.MUL);
    }
    return result;
  }
public @NotNull DfType getBinOpRange(DfaBinOpValue binOp)