invocation type inference: don't create fresh variables for all type parameters but only for those where wildcards are used in return type (IDEA-155627; IDEA-151220; IDEA-151387)

This commit is contained in:
Anna.Kozlova
2016-05-06 18:00:16 +02:00
parent 364f281384
commit d85c70d870
4 changed files with 69 additions and 3 deletions
@@ -19,6 +19,7 @@ import com.intellij.openapi.diagnostic.Logger;
import com.intellij.openapi.util.Comparing;
import com.intellij.openapi.util.Key;
import com.intellij.openapi.util.Pair;
import com.intellij.openapi.util.registry.Registry;
import com.intellij.openapi.util.text.StringUtil;
import com.intellij.psi.*;
import com.intellij.psi.impl.source.resolve.graphInference.constraints.*;
@@ -700,15 +701,15 @@ public class InferenceSession {
LOG.assertTrue(returnType instanceof PsiClassType);
PsiClassType substitutedCapture = (PsiClassType)PsiUtil.captureToplevelWildcards(returnType, myContext);
final PsiTypeParameter[] typeParameters = psiClass.getTypeParameters();
final InferenceVariable[] copy = initBounds(null, typeParameters);
final PsiType[] parameters = substitutedCapture.getParameters();
final InferenceVariable[] copy = initFreshVariablesForCapturedBounds(typeParameters, parameters);
final PsiType[] newParameters = new PsiType[parameters.length];
final PsiElementFactory elementFactory = JavaPsiFacade.getElementFactory(myManager.getProject());
int idx = 0;
for (int i = 0; i < parameters.length; i++) {
newParameters[i] = parameters[i];
if (parameters[i] instanceof PsiCapturedWildcardType) {
newParameters[i] = elementFactory.createType(copy[i]);
newParameters[i] = elementFactory.createType(copy[idx++]);
}
}
substitutedCapture = elementFactory.createType(psiClass, newParameters);
@@ -731,6 +732,25 @@ public class InferenceSession {
}
}
private InferenceVariable[] initFreshVariablesForCapturedBounds(PsiTypeParameter[] typeParameters, PsiType[] parameters) {
if (Registry.is("javac.fresh.variables.for.captured.wildcards.only")) {
final List<PsiTypeParameter> capturedParams = new ArrayList<PsiTypeParameter>();
PsiSubstitutor restParamSubstitution = PsiSubstitutor.EMPTY;
for (int i = 0; i < parameters.length; i++) {
PsiType parameter = parameters[i];
if (parameter instanceof PsiCapturedWildcardType) {
capturedParams.add(typeParameters[i]);
}
else {
restParamSubstitution = restParamSubstitution.put(typeParameters[i], parameter);
}
}
return initBounds(null, restParamSubstitution, capturedParams.toArray(new PsiTypeParameter[0]));
}
return initBounds(null, typeParameters);
}
private InferenceVariable shouldResolveAndInstantiate(PsiType returnType, PsiType targetType) {
final InferenceVariable inferenceVariable = getInferenceVariable(returnType);
if (inferenceVariable != null) {
@@ -0,0 +1,38 @@
class Test {
static class IterableSubject<S extends IterableSubject<S, C>, C> {}
public static <J> IterableSubject<? extends IterableSubject<?, J>, J> bar(Iterable<J> target) {
return foo(target);
}
public static <J> IterableSubject<? extends IterableSubject<?, J>, J> foo(Iterable<J> target) {
return null;
}
}
abstract class Test1 {
private class XBreakpoint<P> {}
private class XBreakpointType<T extends XBreakpoint<P>, P> {}
abstract <B extends XBreakpoint<?>> XBreakpointType<B, ?>
findBreakpointType( Class<? extends XBreakpointType<B, ?>> typeClass);
<U extends XBreakpoint<?>> void createXBreakpoint(Class<? extends XBreakpointType<U, ?>> typeCls) {
final XBreakpointType<U, ?> type = findBreakpointType(typeCls);
}
}
class Test2 {
static abstract class AbstractIterableAssert<S extends AbstractIterableAssert<S, A, T>, A extends Iterable<? extends T>, T> {}
public static <T1> AbstractIterableAssert<?, ? extends Iterable<? extends T1>, T1> bar(Iterable<? extends T1> actual) {
return foo(actual);
}
public static <T> AbstractIterableAssert<?, ? extends Iterable<? extends T>, T> foo(Iterable<? extends T> actual) {
return null;
}
}
@@ -468,6 +468,10 @@ public class GraphInferenceHighlightingTest extends LightDaemonAnalyzerTestCase
}
}
public void testCreateFreshVariablesOnlyForWildcardPlacesDuringReturnTypeProcessing() throws Exception {
doTest();
}
private void doTest() throws Exception {
doTest(false);
}
@@ -623,6 +623,10 @@ linux.jdk.accessibility.atkwrapper.block=true
javac.unchecked.subtyping.during.incorporation=true
javac.unchecked.subtyping.during.incorporation.description=Javac performs unchecked subtyping during incorporation, accepting code which is rejected by the spec and by the eclipse compiler
javac.fresh.variables.for.captured.wildcards.only=true
javac.fresh.variables.for.captured.wildcards.only.description=JLS 18.5.2: if R \u03B8 is a parameterized type, G<A1, ..., An>, and one of A1, ..., An is a wildcard, then, for fresh inference variables \u03B21, ..., \u03B2n ... \
Javac creates fresh variables only for i: Ai is a wildcard
check.power.supply.for.mbp=false
check.power.supply.for.mbp.description=Check for discrete video card and power supply on MBPs