@NotNull
  @Override
  public DfType meet(@NotNull DfType other) {
    if (other instanceof DfConstantType || other instanceof DfEphemeralReferenceType) {
      return other.meet(this);
    }
    if (isSuperType(other)) return other;
    if (other.isSuperType(this)) return this;
    if (!(other instanceof DfReferenceType type)) return BOTTOM;
    TypeConstraint constraint = getConstraint().meet(type.getConstraint());
    if (constraint == TypeConstraints.BOTTOM) {
      return isSuperType(DfTypes.NULL) && other.isSuperType(DfTypes.NULL) ? DfTypes.NULL : BOTTOM;
    }
    DfaNullability nullability = getNullability().intersect(type.getNullability());
    if (nullability == null) return BOTTOM;
    Mutability mutability = getMutability().meet(type.getMutability());
    if (mutability == null) return BOTTOM;
    boolean locality = isLocal() || type.isLocal();
    SpecialField sf;
    DfType sfType;
    if (getSpecialField() == null) {
      sf = type.getSpecialField();
      sfType = type.getSpecialFieldType();
    }
    else if (type.getSpecialField() == null) {
      sf = getSpecialField();
      sfType = getSpecialFieldType();
    } else {
      sf = getSpecialField();
      if (sf != type.getSpecialField()) return BOTTOM;
      sfType = getSpecialFieldType().meet(type.getSpecialFieldType());
    }
    if (sf != null && sfType == BOTTOM) return BOTTOM;
    Set<Object> notValues = myNotValues;
    if (type instanceof DfGenericObjectType) {
      Set<Object> otherNotValues = ((DfGenericObjectType)other).myNotValues;
      if (otherNotValues.containsAll(myNotValues)) {
        notValues = otherNotValues;
      }
      else if (!myNotValues.containsAll(otherNotValues)) {
        notValues = new HashSet<>(myNotValues);
        notValues.addAll(otherNotValues);
        if (nullability == DfaNullability.NOT_NULL) {
          DfEphemeralReferenceType ephemeralValue = checkEphemeral(constraint, notValues);
          if (ephemeralValue != null) {
            return ephemeralValue;
          }
        }
      }
    }
    if (nullability == DfaNullability.NOT_NULL && constraint.isSingleton()) {
      return new DfReferenceConstantType(constraint, constraint, false);
    }
    return new DfGenericObjectType(notValues, constraint, nullability, mutability, sf, sfType, locality);
  }
@NotNull
  @Override
  public DfType meet(@NotNull DfType other)