type compatibility constrain: unchecked conversion: return type is inference variable case

This commit is contained in:
Anna Kozlova
2014-01-31 21:41:17 +04:00
parent 5a9c00a259
commit f26b80359a
4 changed files with 37 additions and 6 deletions
@@ -332,7 +332,8 @@ public class InferenceSession {
private InferenceVariable shouldResolveAndInstantiate(PsiType returnType, PsiType targetType) {
final InferenceVariable inferenceVariable = getInferenceVariable(returnType);
if (inferenceVariable != null) {
if (targetType instanceof PsiPrimitiveType && hasPrimitiveWrapperBound(inferenceVariable)) {
if (targetType instanceof PsiPrimitiveType && hasPrimitiveWrapperBound(inferenceVariable) ||
targetType instanceof PsiClassType && hasUncheckedBounds(inferenceVariable, (PsiClassType)targetType)) {
return inferenceVariable;
}
}
@@ -351,6 +352,21 @@ public class InferenceSession {
return false;
}
private static boolean hasUncheckedBounds(InferenceVariable inferenceVariable, PsiClassType targetType) {
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)) {
return true;
}
}
}
}
return false;
}
private PsiType getTargetType(final PsiExpression context) {
final PsiElement parent = PsiUtil.skipParenthesizedExprUp(context.getParent());
if (parent instanceof PsiExpressionList) {
@@ -19,7 +19,6 @@ import com.intellij.psi.*;
import com.intellij.psi.impl.source.resolve.graphInference.InferenceSession;
import com.intellij.psi.util.PsiUtil;
import com.intellij.psi.util.TypeConversionUtil;
import com.intellij.psi.util.TypesDistinctProver;
import org.jetbrains.annotations.NotNull;
import java.util.List;
@@ -56,13 +55,16 @@ public class TypeCompatibilityConstraint implements ConstraintFormula {
}
}
if (isUncheckedConversion(session, myT, myS)) return true;
if (isUncheckedConversion(myT, myS)) {
session.setErased();
return true;
}
constraints.add(new SubtypingConstraint(myT, myS, true));
return true;
}
private static boolean isUncheckedConversion(InferenceSession session, final PsiType t, final PsiType s) {
public static boolean isUncheckedConversion(final PsiType t, final PsiType s) {
if (t instanceof PsiClassType && !((PsiClassType)t).isRaw() && s instanceof PsiClassType) {
final PsiClassType.ClassResolveResult tResult = ((PsiClassType)t).resolveGenerics();
final PsiClassType.ClassResolveResult sResult = ((PsiClassType)s).resolveGenerics();
@@ -71,13 +73,12 @@ public class TypeCompatibilityConstraint implements ConstraintFormula {
if (tClass != null && sClass != null) {
final PsiSubstitutor sSubstitutor = TypeConversionUtil.getClassSubstitutor(tClass, sClass, sResult.getSubstitutor());
if (sSubstitutor != null && PsiUtil.isRawSubstitutor(tClass, sSubstitutor)) {
session.setErased();
return true;
}
}
}
else if (t instanceof PsiArrayType && t.getArrayDimensions() == s.getArrayDimensions()) {
return isUncheckedConversion(session, t.getDeepComponentType(), s.getDeepComponentType());
return isUncheckedConversion(t.getDeepComponentType(), s.getDeepComponentType());
}
return false;
}
@@ -0,0 +1,10 @@
public class Sample {
interface G<A> {}
interface G1 extends G {}
<B> B bar(B b) {return null;}
void f(G1 g1) {
G<String> l11 = bar(g1);
}
}
@@ -38,6 +38,10 @@ public class ConstraintsInferenceMiscTest extends LightDaemonAnalyzerTestCase {
doTest(false);
}
public void testTypeCompatibilityUncheckedConversionReturnConstraints() throws Exception {
doTest(false);
}
private void doTest(final boolean checkWarnings) {
doTestNewInference(BASE_PATH + "/" + getTestName(false) + ".java", checkWarnings, false);
}