mirror of
https://gitflic.ru/project/openide/openide.git
synced 2026-09-27 10:03:11 +07:00
new inference: erase return type if unchecked conversion was performed
This commit is contained in:
+12
-5
@@ -49,6 +49,8 @@ public class InferenceSession {
|
||||
private static final Logger LOG = Logger.getInstance("#" + InferenceSession.class.getName());
|
||||
public static final Key<PsiType> LOWER_BOUND = Key.create("LowBound");
|
||||
|
||||
private static final Key<Boolean> ERASED = Key.create("UNCHECKED_CONVERSION");
|
||||
|
||||
private final Map<PsiTypeParameter, InferenceVariable> myInferenceVariables = new LinkedHashMap<PsiTypeParameter, InferenceVariable>();
|
||||
private final List<ConstraintFormula> myConstraints = new ArrayList<ConstraintFormula>();
|
||||
|
||||
@@ -286,6 +288,9 @@ public class InferenceSession {
|
||||
|
||||
final PsiSubstitutor substitutor = resolveBounds(myInferenceVariables.values(), mySiteSubstitutor);
|
||||
if (substitutor != null) {
|
||||
if (myContext != null) {
|
||||
myContext.putUserData(ERASED, myErased);
|
||||
}
|
||||
mySiteSubstitutor = substitutor;
|
||||
for (PsiTypeParameter parameter : substitutor.getSubstitutionMap().keySet()) {
|
||||
final InferenceVariable variable = getInferenceVariable(parameter);
|
||||
@@ -396,9 +401,6 @@ public class InferenceSession {
|
||||
myConstraints.add(new TypeCompatibilityConstraint(targetType, PsiUtil.captureToplevelWildcards(substitutor.substitute(inferenceVariable.getParameter()), myContext)));
|
||||
}
|
||||
else {
|
||||
if (targetType instanceof PsiClassType && ((PsiClassType)targetType).isRaw()) {
|
||||
setErased();
|
||||
}
|
||||
if (FunctionalInterfaceParameterizationUtil.isWildcardParameterized(returnType)) {
|
||||
final PsiClassType.ClassResolveResult resolveResult = PsiUtil.resolveGenericsClassInType(returnType);
|
||||
final PsiClass psiClass = resolveResult.getElement();
|
||||
@@ -419,7 +421,7 @@ public class InferenceSession {
|
||||
myConstraints.add(new TypeCompatibilityConstraint(targetType, substitutedCapture));
|
||||
}
|
||||
} else {
|
||||
myConstraints.add(new TypeCompatibilityConstraint(myErased ? TypeConversionUtil.erasure(targetType) : targetType, returnType));
|
||||
myConstraints.add(new TypeCompatibilityConstraint(targetType, myErased ? TypeConversionUtil.erasure(returnType) : returnType));
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -470,7 +472,7 @@ public class InferenceSession {
|
||||
}
|
||||
|
||||
private static boolean hasWildcardParameterization(InferenceVariable inferenceVariable, PsiClassType targetType) {
|
||||
if (FunctionalInterfaceParameterizationUtil.isWildcardParameterized(targetType)) {
|
||||
if (!FunctionalInterfaceParameterizationUtil.isWildcardParameterized(targetType)) {
|
||||
final List<PsiType> bounds = inferenceVariable.getBounds(InferenceBound.LOWER);
|
||||
final Processor<Pair<PsiType, PsiType>> differentParameterizationProcessor = new Processor<Pair<PsiType, PsiType>>() {
|
||||
@Override
|
||||
@@ -1198,4 +1200,9 @@ public class InferenceSession {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static boolean wasUncheckedConversionPerformed(PsiElement call) {
|
||||
final Boolean erased = call.getUserData(ERASED);
|
||||
return erased != null && erased.booleanValue();
|
||||
}
|
||||
}
|
||||
|
||||
+7
@@ -24,6 +24,7 @@ import com.intellij.psi.*;
|
||||
import com.intellij.psi.impl.DebugUtil;
|
||||
import com.intellij.psi.impl.PsiImplUtil;
|
||||
import com.intellij.psi.impl.source.resolve.JavaResolveCache;
|
||||
import com.intellij.psi.impl.source.resolve.graphInference.InferenceSession;
|
||||
import com.intellij.psi.impl.source.tree.ChildRole;
|
||||
import com.intellij.psi.impl.source.tree.ElementType;
|
||||
import com.intellij.psi.impl.source.tree.JavaElementType;
|
||||
@@ -208,6 +209,12 @@ public class PsiMethodCallExpressionImpl extends ExpressionPsiElement implements
|
||||
PsiSubstitutor substitutor) {
|
||||
PsiType substitutedReturnType = substitutor.substitute(ret);
|
||||
if (substitutedReturnType == null) return TypeConversionUtil.erasure(ret);
|
||||
if (InferenceSession.wasUncheckedConversionPerformed(call)) {
|
||||
// 18.5.2
|
||||
// if unchecked conversion was necessary, then this substitution provides the parameter types of the invocation type,
|
||||
// while the return type and thrown types are given by the erasure of m's type (without applying θ').
|
||||
return TypeConversionUtil.erasure(substitutedReturnType);
|
||||
}
|
||||
if (PsiUtil.isRawSubstitutor(method, substitutor)) {
|
||||
final PsiType returnTypeErasure = TypeConversionUtil.erasure(ret);
|
||||
if (Comparing.equal(TypeConversionUtil.erasure(substitutedReturnType), returnTypeErasure)) {
|
||||
|
||||
+2
-2
@@ -7,8 +7,8 @@ public class Sample {
|
||||
<B> B bar(G<B> gb) {return null;}
|
||||
|
||||
void f(G1 g1) {
|
||||
<error descr="Incompatible types. Found: 'B', required: 'Sample.G<java.lang.String>'">G<String> l11 = bar(g1);</error>
|
||||
<error descr="Incompatible types. Found: 'B', required: 'java.lang.String'">String l1 = bar(g1);</error>
|
||||
<error descr="Incompatible types. Found: 'java.lang.Object', required: 'Sample.G<java.lang.String>'">G<String> l11 = bar(g1);</error>
|
||||
<error descr="Incompatible types. Found: 'java.lang.Object', required: 'java.lang.String'">String l1 = bar(g1);</error>
|
||||
Object o = bar(g1);
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user