Type variable with non-trivial upper bound cannot capture 'in' projection

This commit is contained in:
Svetlana Isakova
2014-12-11 18:49:16 +03:00
parent 8b0707b15d
commit 1f6f607f40
6 changed files with 50 additions and 2 deletions
@@ -36,6 +36,7 @@ import org.jetbrains.jet.lang.resolve.calls.model.ResolvedCall;
import org.jetbrains.jet.lang.resolve.name.Name;
import org.jetbrains.jet.lang.types.*;
import org.jetbrains.jet.lang.types.checker.JetTypeChecker;
import org.jetbrains.jet.lang.types.lang.KotlinBuiltIns;
import org.jetbrains.jet.renderer.DescriptorRenderer;
import org.jetbrains.jet.renderer.Renderer;
@@ -412,10 +413,20 @@ public class Renderers {
return result;
}
String explanation;
JetType upperBound = typeParameterWithCapturedConstraint.getUpperBoundsAsType();
if (!KotlinBuiltIns.isNullableAny(upperBound)
&& capturedTypeConstructor.getTypeProjection().getProjectionKind() == Variance.IN_VARIANCE) {
explanation = "Type parameter has an upper bound '" + result.getTypeRenderer().render(upperBound) + "'" +
" that cannot be satisfied capturing 'in' projection";
}
else {
explanation = "Only top level type projections can be captured";
}
result.text(newText().normal("'" + typeParameterWithCapturedConstraint.getName() + "'" +
" cannot capture " +
"'" + capturedTypeConstructor.getTypeProjection() + "'. " +
"Only top level type projections can be captured"));
explanation));
return result;
}
@@ -0,0 +1,16 @@
// !DIAGNOSTICS: -UNUSED_VARIABLE -UNUSED_PARAMETER
// !CHECK_TYPE
fun <T: Any> bar(a: Array<T>): Array<T?> = null!!
fun test1(a: Array<in Int>) {
val r: Array<in Int?> = <!TYPE_INFERENCE_CANNOT_CAPTURE_TYPES!>bar<!>(a)
<!TYPE_INFERENCE_CANNOT_CAPTURE_TYPES!>bar<!>(a)
}
fun <T: Any> foo(l: Array<T>): Array<Array<T?>> = null!!
fun test2(a: Array<in Int>) {
val r: Array<out Array<in Int?>> = <!TYPE_INFERENCE_CANNOT_CAPTURE_TYPES!>foo<!>(a)
<!TYPE_INFERENCE_CANNOT_CAPTURE_TYPES!>foo<!>(a)
}
@@ -0,0 +1,6 @@
package
internal fun </*0*/ T : kotlin.Any> bar(/*0*/ a: kotlin.Array<T>): kotlin.Array<T?>
internal fun </*0*/ T : kotlin.Any> foo(/*0*/ l: kotlin.Array<T>): kotlin.Array<kotlin.Array<T?>>
internal fun test1(/*0*/ a: kotlin.Array<in kotlin.Int>): kotlin.Unit
internal fun test2(/*0*/ a: kotlin.Array<in kotlin.Int>): kotlin.Unit
@@ -5094,6 +5094,12 @@ public class JetDiagnosticsTestGenerated extends AbstractJetDiagnosticsTest {
JetTestUtils.assertAllTestsPresentByMetadata(this.getClass(), new File("compiler/testData/diagnostics/tests/inference/capturedTypes"), Pattern.compile("^(.+)\\.kt$"), true);
}
@TestMetadata("cannotCaptureInProjection.kt")
public void testCannotCaptureInProjection() throws Exception {
String fileName = JetTestUtils.navigationMetadata("compiler/testData/diagnostics/tests/inference/capturedTypes/cannotCaptureInProjection.kt");
doTest(fileName);
}
@TestMetadata("captureForNullableTypes.kt")
public void testCaptureForNullableTypes() throws Exception {
String fileName = JetTestUtils.navigationMetadata("compiler/testData/diagnostics/tests/inference/capturedTypes/captureForNullableTypes.kt");
@@ -379,7 +379,12 @@ public class ConstraintSystemImpl : ConstraintSystem {
constrainingTypeProjection: TypeProjection,
constraintPosition: ConstraintPosition
) {
val typeBounds = getTypeBounds(parameterType)
val typeVariable = getMyTypeVariable(parameterType)!!
if (!KotlinBuiltIns.isNullableAny(typeVariable.getUpperBoundsAsType())
&& constrainingTypeProjection.getProjectionKind() == Variance.IN_VARIANCE) {
cannotCaptureTypesError = true
}
val typeBounds = getTypeBounds(typeVariable)
val typeProjection = if (parameterType.isMarkedNullable()) {
TypeProjectionImpl(constrainingTypeProjection.getProjectionKind(), TypeUtils.makeNotNullable(constrainingTypeProjection.getType()))
}
@@ -878,6 +878,10 @@ public class KotlinBuiltIns {
return isConstructedFromGivenClass(type, FQ_NAMES.any);
}
public static boolean isNullableAny(@NotNull JetType type) {
return isAnyOrNullableAny(type) && type.isMarkedNullable();
}
public static boolean isUnit(@NotNull JetType type) {
return isNotNullConstructedFromGivenClass(type, FQ_NAMES.unit);
}