Captured type might be substituted in an opposite projection
out Captured (in Int) = out Int in Captured (out Int) = in Int
This commit is contained in:
+14
@@ -0,0 +1,14 @@
|
|||||||
|
// !DIAGNOSTICS: -UNUSED_PARAMETER
|
||||||
|
// !CHECK_TYPE
|
||||||
|
|
||||||
|
fun <T> foo1(a1: Array<in T>, a2: Array<T>): T = null!!
|
||||||
|
|
||||||
|
fun test1(a1: Array<Int>, a2: Array<out Int>) {
|
||||||
|
foo1(a1, a2) checkType { it : _<Int> }
|
||||||
|
}
|
||||||
|
|
||||||
|
fun <T> foo2(a1: Array<T>, a2: Array<out T>): T = null!!
|
||||||
|
|
||||||
|
fun test2(a1: Array<in Int>, a2: Array<Int>) {
|
||||||
|
foo2(a1, a2) checkType { it : _<Any?>}
|
||||||
|
}
|
||||||
+6
@@ -0,0 +1,6 @@
|
|||||||
|
package
|
||||||
|
|
||||||
|
internal fun </*0*/ T> foo1(/*0*/ a1: kotlin.Array<in T>, /*1*/ a2: kotlin.Array<T>): T
|
||||||
|
internal fun </*0*/ T> foo2(/*0*/ a1: kotlin.Array<T>, /*1*/ a2: kotlin.Array<out T>): T
|
||||||
|
internal fun test1(/*0*/ a1: kotlin.Array<kotlin.Int>, /*1*/ a2: kotlin.Array<out kotlin.Int>): kotlin.Unit
|
||||||
|
internal fun test2(/*0*/ a1: kotlin.Array<in kotlin.Int>, /*1*/ a2: kotlin.Array<kotlin.Int>): kotlin.Unit
|
||||||
@@ -5136,6 +5136,12 @@ public class JetDiagnosticsTestGenerated extends AbstractJetDiagnosticsTest {
|
|||||||
doTest(fileName);
|
doTest(fileName);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@TestMetadata("capturedTypeSubstitutedIntoOppositeProjection.kt")
|
||||||
|
public void testCapturedTypeSubstitutedIntoOppositeProjection() throws Exception {
|
||||||
|
String fileName = JetTestUtils.navigationMetadata("compiler/testData/diagnostics/tests/inference/capturedTypes/capturedTypeSubstitutedIntoOppositeProjection.kt");
|
||||||
|
doTest(fileName);
|
||||||
|
}
|
||||||
|
|
||||||
@TestMetadata("kt2570.kt")
|
@TestMetadata("kt2570.kt")
|
||||||
public void testKt2570() throws Exception {
|
public void testKt2570() throws Exception {
|
||||||
String fileName = JetTestUtils.navigationMetadata("compiler/testData/diagnostics/tests/inference/capturedTypes/kt2570.kt");
|
String fileName = JetTestUtils.navigationMetadata("compiler/testData/diagnostics/tests/inference/capturedTypes/kt2570.kt");
|
||||||
|
|||||||
@@ -19,6 +19,7 @@ package org.jetbrains.jet.lang.types;
|
|||||||
import org.jetbrains.annotations.NotNull;
|
import org.jetbrains.annotations.NotNull;
|
||||||
import org.jetbrains.annotations.Nullable;
|
import org.jetbrains.annotations.Nullable;
|
||||||
import org.jetbrains.jet.lang.descriptors.TypeParameterDescriptor;
|
import org.jetbrains.jet.lang.descriptors.TypeParameterDescriptor;
|
||||||
|
import org.jetbrains.jet.lang.resolve.calls.inference.InferencePackage;
|
||||||
import org.jetbrains.jet.lang.resolve.scopes.SubstitutingScope;
|
import org.jetbrains.jet.lang.resolve.scopes.SubstitutingScope;
|
||||||
import org.jetbrains.jet.lang.types.lang.KotlinBuiltIns;
|
import org.jetbrains.jet.lang.types.lang.KotlinBuiltIns;
|
||||||
import org.jetbrains.jet.lang.types.typeUtil.TypeUtilPackage;
|
import org.jetbrains.jet.lang.types.typeUtil.TypeUtilPackage;
|
||||||
@@ -186,28 +187,36 @@ public class TypeSubstitutor {
|
|||||||
TypeProjection replacement = substitution.get(type.getConstructor());
|
TypeProjection replacement = substitution.get(type.getConstructor());
|
||||||
|
|
||||||
if (replacement != null) {
|
if (replacement != null) {
|
||||||
switch (conflictType(originalProjectionKind, replacement.getProjectionKind())) {
|
VarianceConflictType varianceConflict = conflictType(originalProjectionKind, replacement.getProjectionKind());
|
||||||
case OUT_IN_IN_POSITION:
|
|
||||||
throw new SubstitutionException("Out-projection in in-position");
|
|
||||||
case IN_IN_OUT_POSITION:
|
|
||||||
// todo use the right type parameter variance and upper bound
|
|
||||||
return new TypeProjectionImpl(Variance.OUT_VARIANCE, KotlinBuiltIns.getInstance().getNullableAnyType());
|
|
||||||
case NO_CONFLICT:
|
|
||||||
JetType substitutedType;
|
|
||||||
CustomTypeVariable typeVariable = TypesPackage.getCustomTypeVariable(type);
|
|
||||||
if (typeVariable != null) {
|
|
||||||
substitutedType = typeVariable.substitutionResult(replacement.getType());
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
// this is a simple type T or T?: if it's T, we should just take replacement, if T? - we make replacement nullable
|
|
||||||
substitutedType = TypeUtils.makeNullableIfNeeded(replacement.getType(), type.isMarkedNullable());
|
|
||||||
}
|
|
||||||
|
|
||||||
Variance resultingProjectionKind = combine(originalProjectionKind, replacement.getProjectionKind());
|
// Captured type might be substituted in an opposite projection:
|
||||||
return new TypeProjectionImpl(resultingProjectionKind, substitutedType);
|
// out 'Captured (in Int)' = out Int
|
||||||
default:
|
// in 'Captured (out Int)' = in Int
|
||||||
throw new IllegalStateException();
|
boolean allowVarianceConflict = InferencePackage.isCaptured(type);
|
||||||
|
if (!allowVarianceConflict) {
|
||||||
|
//noinspection EnumSwitchStatementWhichMissesCases
|
||||||
|
switch (varianceConflict) {
|
||||||
|
case OUT_IN_IN_POSITION:
|
||||||
|
throw new SubstitutionException("Out-projection in in-position");
|
||||||
|
case IN_IN_OUT_POSITION:
|
||||||
|
// todo use the right type parameter variance and upper bound
|
||||||
|
return new TypeProjectionImpl(Variance.OUT_VARIANCE, KotlinBuiltIns.getInstance().getNullableAnyType());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
JetType substitutedType;
|
||||||
|
CustomTypeVariable typeVariable = TypesPackage.getCustomTypeVariable(type);
|
||||||
|
if (typeVariable != null) {
|
||||||
|
substitutedType = typeVariable.substitutionResult(replacement.getType());
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
// this is a simple type T or T?: if it's T, we should just take replacement, if T? - we make replacement nullable
|
||||||
|
substitutedType = TypeUtils.makeNullableIfNeeded(replacement.getType(), type.isMarkedNullable());
|
||||||
|
}
|
||||||
|
|
||||||
|
Variance resultingProjectionKind = varianceConflict == VarianceConflictType.NO_CONFLICT
|
||||||
|
? combine(originalProjectionKind, replacement.getProjectionKind())
|
||||||
|
: originalProjectionKind;
|
||||||
|
return new TypeProjectionImpl(resultingProjectionKind, substitutedType);
|
||||||
}
|
}
|
||||||
// The type is not within the substitution range, i.e. Foo, Bar<T> etc.
|
// The type is not within the substitution range, i.e. Foo, Bar<T> etc.
|
||||||
return substituteCompoundType(originalProjection, recursionDepth);
|
return substituteCompoundType(originalProjection, recursionDepth);
|
||||||
|
|||||||
Reference in New Issue
Block a user