PsiType (PsiSubstitutor substitutor, InferenceVariable var) { PsiType eqBound = getEqualsBound(var, substitutor); if (eqBound != PsiTypes.nullType() && eqBound instanceof PsiPrimitiveType) return PsiTypes.nullType(); PsiType lowerBound = getLowerBound(var, substitutor); if (eqBound == PsiTypes.nullType()) { lowerBound = myPolicy.adjustInferredType(myManager, lowerBound, ConstraintType.SUBTYPE); } final PsiType upperBound = getUpperBound(var, substitutor); PsiType type; if (eqBound != PsiTypes.nullType() && (myErased || eqBound != null)) { PsiClass aClass = PsiUtil.resolveClassInClassTypeOnly(eqBound); if (aClass instanceof PsiTypeParameter && TypeConversionUtil.isFreshVariable((PsiTypeParameter)aClass)) { PsiCapturedWildcardType capturedWildcard = var.getUserData(ORIGINAL_CAPTURE); //restore captured wildcard from method return type when no additional constraints were inferred //to preserve equality of type arguments if (capturedWildcard != null && capturedWildcard.getUpperBound().equals(TypeConversionUtil.getInferredUpperBoundForSynthetic((PsiTypeParameter)aClass))) { eqBound = capturedWildcard; } } if (isLowerBoundNotAssignable(var, eqBound, true)) { final String incompatibleBoundsMessage = incompatibleBoundsMessage(var, substitutor, InferenceBound.EQ, EQUALITY_CONSTRAINTS_PRESENTATION, InferenceBound.LOWER, LOWER_BOUNDS_PRESENTATION); registerIncompatibleErrorMessage(incompatibleBoundsMessage); return PsiTypes.nullType(); } else { type = eqBound; if (isLowerBoundNotAssignable(var, eqBound, false)) { setErased(); } } } else { type = lowerBound; } if (type == PsiTypes.nullType()) { if (var.isThrownBound() && myPolicy.inferRuntimeExceptionForThrownBoundWithNoConstraints() && isThrowable(var.getBounds(InferenceBound.UPPER))) { type = PsiType.getJavaLangRuntimeException(myManager, GlobalSearchScope.allScope(myManager.getProject())); } else { type = var.getBounds(InferenceBound.UPPER).size() == 1 ? myPolicy.getInferredTypeWithNoConstraint(myManager, upperBound).first : upperBound; } if (myErrorMessages == null && type instanceof PsiIntersectionType) { String conflictingConjunctsMessage = ((PsiIntersectionType)type).getConflictingConjunctsMessage(); if (conflictingConjunctsMessage == null) { if (findParameterizationOfTheSameGenericClass(var.getBounds(InferenceBound.UPPER), pair -> pair.first == null || pair.second == null || Comparing.equal(substituteNonProperBound(pair.first, substitutor), substituteNonProperBound(pair.second, substitutor))) != null) { //warn if upper bounds has same generic class with different type arguments conflictingConjunctsMessage = type.getPresentableText(false); } else { conflictingConjunctsMessage = getConjunctsConflict((PsiIntersectionType)type); } } if (conflictingConjunctsMessage != null) { registerIncompatibleErrorMessage(JavaPsiBundle.message("error.type.parameter.has.incompatible.upper.bounds", var.getParameter().getName(), conflictingConjunctsMessage)); return PsiTypes.nullType(); } } } else { for (PsiType upperType : var.getBounds(InferenceBound.UPPER)) { if (myErrorMessages == null && isProperType(upperType)) { if (type != lowerBound && !TypeConversionUtil.isAssignable(upperType, type)) { registerIncompatibleErrorMessage(incompatibleBoundsMessage(var, substitutor, InferenceBound.EQ, EQUALITY_CONSTRAINTS_PRESENTATION, InferenceBound.UPPER, UPPER_BOUNDS_PRESENTATION)); return PsiTypes.nullType(); } else if (type == lowerBound) { for (PsiType lowerBoundConjunct : var.getBounds(InferenceBound.LOWER)) { if (isProperType(lowerBoundConjunct) && !TypeConversionUtil.isAssignable(upperType, lowerBoundConjunct)) { registerIncompatibleErrorMessage(incompatibleBoundsMessage(var, substitutor, InferenceBound.LOWER, LOWER_BOUNDS_PRESENTATION, InferenceBound.UPPER, UPPER_BOUNDS_PRESENTATION)); return PsiTypes.nullType(); } } } } } } if (type == PsiTypes.nullType()) { registerIncompatibleErrorMessage( JavaPsiBundle.message("error.incompatible.upper.bounds", StringUtil.join(var.getBounds(InferenceBound.UPPER), bound -> { final PsiType substituted = substituteNonProperBound(bound, substitutor); return getPresentableText(substituted != null ? substituted : bound); }, ", "))); } return type; }