@Override
    default String getAssignabilityExplanation(@NotNull TypeConstraint otherType,
                                               boolean expectedAssignable,
                                               @Nls String elementTitle) {
      Exact exact = otherType.instanceOfTypes().collect(MoreCollectors.onlyOne()).orElse(null);
      if (exact == null) return null;
      boolean actual = exact.isAssignableFrom(this);
      if (actual != expectedAssignable) return null;
      if (expectedAssignable) {
        if (equals(exact)) {
          return JavaAnalysisBundle.message("type.constraint.assignability.explanation.exact", elementTitle, toShortString());
        }
        return JavaAnalysisBundle.message("type.constraint.assignability.explanation.exact.subtype", elementTitle, toShortString(), exact.toShortString());
      }
      else {
        return JavaAnalysisBundle.message("type.constraint.assignability.explanation.exact.not.subtype", elementTitle, toShortString(), exact.toShortString());
      }
    }
@Override
    default String getAssignabilityExplanation(@NotNull TypeConstraint otherType,
                                               boolean expectedAssignable,
                                               @Nls String elementTitle)