String (@NotNull TypeConstraint otherType, boolean expectedAssignable, @Nls String elementTitle) { Exact exact = otherType.instanceOfTypes().collect(MoreCollectors.onlyOne()).orElse(null); if (exact == null) return null; if (expectedAssignable) { for (Exact inst : myInstanceOf) { if (exact.isAssignableFrom(inst)) { if (exact == inst) { return JavaAnalysisBundle.message("type.constraint.assignability.explanation.exact", elementTitle, inst.toShortString()); } else { return JavaAnalysisBundle.message("type.constraint.assignability.explanation.subtype.of.subtype", elementTitle, inst.toShortString(), exact.toShortString()); } } } } else { for (Exact notInst : myNotInstanceOf) { if (notInst.isAssignableFrom(exact)) { if (exact == notInst) { return JavaAnalysisBundle.message("type.constraint.assignability.explanation.not.instance.of", elementTitle, notInst.toShortString()); } else { return JavaAnalysisBundle.message("type.constraint.assignability.explanation.not.instance.of.supertype", elementTitle, notInst.toShortString(), exact.toShortString()); } } } for (Exact inst : myInstanceOf) { if (!exact.isConvertibleFrom(inst)) { return JavaAnalysisBundle.message("type.constraint.assignability.explanation.definitely.inconvertible", elementTitle, inst.toShortString(), exact.toShortString()); } } } return null; }