mirror of
https://gitflic.ru/project/openide/openide.git
synced 2026-09-27 10:03:11 +07:00
inference: treat only non-proper bounds of inference variables as unchecked conversion (IDEA-204125)
This commit is contained in:
+2
-2
@@ -310,7 +310,7 @@ public class InferenceIncorporationPhase {
|
||||
for (PsiType eqBound : eqBounds) {
|
||||
if (eqBound == null || PsiType.NULL.equals(eqBound) || eqBound instanceof PsiWildcardType) continue;
|
||||
if (Registry.is("javac.unchecked.subtyping.during.incorporation", true)) {
|
||||
if (TypeCompatibilityConstraint.isUncheckedConversion(upperBound, eqBound)) {
|
||||
if (TypeCompatibilityConstraint.isUncheckedConversion(upperBound, eqBound, mySession)) {
|
||||
if (PsiUtil.resolveClassInType(eqBound) instanceof PsiTypeParameter && !mySession.isProperType(upperBound)) {
|
||||
mySession.setErased();
|
||||
}
|
||||
@@ -319,7 +319,7 @@ public class InferenceIncorporationPhase {
|
||||
|
||||
if (!mySession.isProperType(upperBound) &&
|
||||
eqBound instanceof PsiCapturedWildcardType &&
|
||||
TypeCompatibilityConstraint.isUncheckedConversion(upperBound, ((PsiCapturedWildcardType)eqBound).getUpperBound())) {
|
||||
TypeCompatibilityConstraint.isUncheckedConversion(upperBound, ((PsiCapturedWildcardType)eqBound).getUpperBound(), mySession)) {
|
||||
mySession.setErased();
|
||||
continue;
|
||||
}
|
||||
|
||||
+5
-3
@@ -739,7 +739,7 @@ public class InferenceSession {
|
||||
return inferenceVariable;
|
||||
}
|
||||
if (targetType instanceof PsiClassType) {
|
||||
if (hasUncheckedBounds(inferenceVariable, (PsiClassType)targetType) ||
|
||||
if (hasUncheckedBounds(inferenceVariable, (PsiClassType)targetType, this) ||
|
||||
hasWildcardParameterization(inferenceVariable, (PsiClassType)targetType)) {
|
||||
return inferenceVariable;
|
||||
}
|
||||
@@ -761,13 +761,15 @@ public class InferenceSession {
|
||||
return false;
|
||||
}
|
||||
|
||||
private static boolean hasUncheckedBounds(InferenceVariable inferenceVariable, PsiClassType targetType) {
|
||||
private static boolean hasUncheckedBounds(InferenceVariable inferenceVariable,
|
||||
PsiClassType targetType,
|
||||
InferenceSession session) {
|
||||
if (!targetType.isRaw()) {
|
||||
final InferenceBound[] boundTypes = {InferenceBound.EQ, InferenceBound.LOWER};
|
||||
for (InferenceBound inferenceBound : boundTypes) {
|
||||
final List<PsiType> bounds = inferenceVariable.getBounds(inferenceBound);
|
||||
for (PsiType bound : bounds) {
|
||||
if (TypeCompatibilityConstraint.isUncheckedConversion(targetType, bound)) {
|
||||
if (TypeCompatibilityConstraint.isUncheckedConversion(targetType, bound, session)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
+1
-1
@@ -37,7 +37,7 @@ public class ExpressionCompatibilityConstraint extends InputOutputConstraintForm
|
||||
final PsiType type = myExpression.getType();
|
||||
session.registerIncompatibleErrorMessage((type != null ? type.getPresentableText() : myExpression.getText()) + " is not compatible with " + session.getPresentableText(myT));
|
||||
}
|
||||
else if (TypeCompatibilityConstraint.isUncheckedConversion(myT, exprType) && !JavaGenericsUtil.isReifiableType(myT)) {
|
||||
else if (TypeCompatibilityConstraint.isUncheckedConversion(myT, exprType, session) && !JavaGenericsUtil.isReifiableType(myT)) {
|
||||
session.setErased();
|
||||
}
|
||||
return assignmentCompatible;
|
||||
|
||||
+21
-8
@@ -16,8 +16,10 @@
|
||||
package com.intellij.psi.impl.source.resolve.graphInference.constraints;
|
||||
|
||||
import com.intellij.psi.*;
|
||||
import com.intellij.psi.impl.source.resolve.graphInference.InferenceBound;
|
||||
import com.intellij.psi.impl.source.resolve.graphInference.InferenceSession;
|
||||
import com.intellij.psi.impl.source.resolve.graphInference.InferenceVariable;
|
||||
import com.intellij.psi.util.InheritanceUtil;
|
||||
import com.intellij.psi.util.PsiUtil;
|
||||
import com.intellij.psi.util.TypeConversionUtil;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
@@ -57,7 +59,7 @@ public class TypeCompatibilityConstraint implements ConstraintFormula {
|
||||
}
|
||||
}
|
||||
|
||||
if (isUncheckedConversion(myT, myS)) {
|
||||
if (isUncheckedConversion(myT, myS, session)) {
|
||||
session.setErased();
|
||||
return true;
|
||||
}
|
||||
@@ -66,28 +68,32 @@ public class TypeCompatibilityConstraint implements ConstraintFormula {
|
||||
return true;
|
||||
}
|
||||
|
||||
public static boolean isUncheckedConversion(final PsiType t, final PsiType s) {
|
||||
public static boolean isUncheckedConversion(final PsiType t,
|
||||
final PsiType s,
|
||||
InferenceSession session) {
|
||||
if (t instanceof PsiClassType && !((PsiClassType)t).isRaw()) {
|
||||
final PsiClassType.ClassResolveResult tResult = ((PsiClassType)t).resolveGenerics();
|
||||
final PsiClass tClass = tResult.getElement();
|
||||
if (s instanceof PsiClassType && isUncheckedConversion(tClass, (PsiClassType)s)) {
|
||||
if (s instanceof PsiClassType && isUncheckedConversion(tClass, (PsiClassType)s, session)) {
|
||||
return true;
|
||||
}
|
||||
else if (s instanceof PsiIntersectionType) {
|
||||
for (PsiType conjunct : ((PsiIntersectionType)s).getConjuncts()) {
|
||||
if (conjunct instanceof PsiClassType && isUncheckedConversion(tClass, (PsiClassType)conjunct)) {
|
||||
if (conjunct instanceof PsiClassType && isUncheckedConversion(tClass, (PsiClassType)conjunct, session)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (t instanceof PsiArrayType && s != null && t.getArrayDimensions() == s.getArrayDimensions()) {
|
||||
return isUncheckedConversion(t.getDeepComponentType(), s.getDeepComponentType());
|
||||
return isUncheckedConversion(t.getDeepComponentType(), s.getDeepComponentType(), session);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
private static boolean isUncheckedConversion(PsiClass tClass, PsiClassType s) {
|
||||
private static boolean isUncheckedConversion(PsiClass tClass,
|
||||
PsiClassType s,
|
||||
InferenceSession session) {
|
||||
final PsiClassType.ClassResolveResult sResult = s.resolveGenerics();
|
||||
final PsiClass sClass = sResult.getElement();
|
||||
if (tClass != null && sClass != null && !(sClass instanceof InferenceVariable)) {
|
||||
@@ -97,8 +103,15 @@ public class TypeCompatibilityConstraint implements ConstraintFormula {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
else if (tClass instanceof InferenceVariable && s.isRaw() && tClass.isInheritor(sClass, true)) {
|
||||
return true;
|
||||
else if (tClass instanceof InferenceVariable && s.isRaw()) {
|
||||
for (PsiType bound : ((InferenceVariable)tClass).getBounds(InferenceBound.UPPER)) {
|
||||
if (!session.isProperType(bound)) {
|
||||
PsiClass boundClass = PsiUtil.resolveClassInClassTypeOnly(bound);
|
||||
if (boundClass != null && InheritanceUtil.isInheritorOrSelf(boundClass, sClass, true)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return false;
|
||||
|
||||
+27
@@ -0,0 +1,27 @@
|
||||
class Test_3 {
|
||||
|
||||
public static void main(String[] aArgs) {
|
||||
Info info = null;
|
||||
update(info)
|
||||
.withSuper()
|
||||
.withChild();
|
||||
}
|
||||
|
||||
public interface Info<_Info> { }
|
||||
|
||||
public static <Type extends Info<?>> C<?> update(Type aType) {
|
||||
return null;
|
||||
}
|
||||
|
||||
public static class C<_Builder extends C< _Builder>> extends A<_Builder> {
|
||||
public _Builder withChild() {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
public static class A<_B extends A<_B>> {
|
||||
public _B withSuper() {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
||||
+1
@@ -1043,4 +1043,5 @@ public class GenericsHighlighting8Test extends LightDaemonAnalyzerTestCase {
|
||||
public void testNestedWildcardsWithImplicitBounds() { doTest(); }
|
||||
public void testCallOnRawWithExplicitTypeArguments() { doTest(); }
|
||||
public void testNoCaptureConversionDuringDetectingSupertypesDeepInHierarchy() { doTest(); }
|
||||
public void testIgnoreErasureForProperTypeBound() { doTest(); }
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user