type compatibility constrain: boxing is not completeness-preserving: move treatment to return constraint

This commit is contained in:
Anna Kozlova
2014-01-31 21:41:14 +04:00
parent 4444fc1126
commit af8095f8b0
4 changed files with 46 additions and 5 deletions
@@ -300,8 +300,9 @@ public class InferenceSession {
private void initReturnTypeConstraint(PsiMethod method, final PsiCallExpression context) {
if (PsiPolyExpressionUtil.isMethodCallPolyExpression(context, method) ||
context instanceof PsiNewExpression && PsiDiamondType.ourDiamondGuard.currentStack().contains(context)) {
final PsiType returnType = method.getReturnType();
PsiType returnType = method.getReturnType();
if (!PsiType.VOID.equals(returnType) && returnType != null) {
returnType = PsiImplUtil.normalizeWildcardTypeByPosition(returnType, context);
PsiType targetType = PsiTypesUtil.getExpectedTypeByParent(context);
if (targetType == null) {
targetType = PsiResolveHelper.ourGraphGuard.doPreventingRecursion(context, true, new Computable<PsiType>() {
@@ -312,15 +313,44 @@ public class InferenceSession {
});
}
if (targetType != null) {
if (targetType instanceof PsiClassType && ((PsiClassType)targetType).isRaw()) {
setErased();
final InferenceVariable inferenceVariable = shouldResolveAndInstantiate(returnType, targetType);
if (inferenceVariable != null) {
resolveBounds(Collections.singletonList(inferenceVariable), mySiteSubstitutor, true);
myConstraints.add(new TypeCompatibilityConstraint(inferenceVariable.getInstantiation(), returnType));
}
else {
if (targetType instanceof PsiClassType && ((PsiClassType)targetType).isRaw()) {
setErased();
}
myConstraints.add(new TypeCompatibilityConstraint(myErased ? TypeConversionUtil.erasure(targetType) : GenericsUtil.eliminateWildcards(targetType, false), returnType));
}
myConstraints.add(new TypeCompatibilityConstraint(myErased ? TypeConversionUtil.erasure(targetType) : GenericsUtil.eliminateWildcards(targetType, false), PsiImplUtil.normalizeWildcardTypeByPosition(returnType, context)));
}
}
}
}
private InferenceVariable shouldResolveAndInstantiate(PsiType returnType, PsiType targetType) {
final InferenceVariable inferenceVariable = getInferenceVariable(returnType);
if (inferenceVariable != null) {
if (targetType instanceof PsiPrimitiveType && hasPrimitiveWrapperBound(inferenceVariable)) {
return inferenceVariable;
}
}
return null;
}
private static boolean hasPrimitiveWrapperBound(InferenceVariable inferenceVariable) {
for (InferenceBound inferenceBound : InferenceBound.values()) {
final List<PsiType> bounds = inferenceVariable.getBounds(inferenceBound);
for (PsiType bound : bounds) {
if (PsiPrimitiveType.getUnboxedType(bound) != null) {
return true;
}
}
}
return false;
}
private PsiType getTargetType(final PsiExpression context) {
final PsiElement parent = PsiUtil.skipParenthesizedExprUp(context.getParent());
if (parent instanceof PsiExpressionList) {
@@ -52,7 +52,7 @@ public class TypeCompatibilityConstraint implements ConstraintFormula {
if (myT instanceof PsiPrimitiveType) {
final PsiClassType boxedType = ((PsiPrimitiveType)myT).getBoxedType(session.getManager(), session.getScope());
if (boxedType != null) {
constraints.add(new TypeCompatibilityConstraint(boxedType, myS));
constraints.add(new TypeEqualityConstraint(boxedType, myS));
return true;
}
}
@@ -0,0 +1,7 @@
public class Sample {
static <T> T foo(T t) { return null; }
static {
long l11 = foo(1 );
}
}
@@ -30,6 +30,10 @@ public class ConstraintsInferenceMiscTest extends LightDaemonAnalyzerTestCase {
doTest(false);
}
public void testPrimitiveTypesCompatibility() throws Exception {
doTest(false);
}
private void doTest(final boolean checkWarnings) {
doTestNewInference(BASE_PATH + "/" + getTestName(false) + ".java", checkWarnings, false);
}