Type variable with non-trivial upper bound cannot capture 'in' projection
This commit is contained in:
@@ -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.resolve.name.Name;
|
||||||
import org.jetbrains.jet.lang.types.*;
|
import org.jetbrains.jet.lang.types.*;
|
||||||
import org.jetbrains.jet.lang.types.checker.JetTypeChecker;
|
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.DescriptorRenderer;
|
||||||
import org.jetbrains.jet.renderer.Renderer;
|
import org.jetbrains.jet.renderer.Renderer;
|
||||||
|
|
||||||
@@ -412,10 +413,20 @@ public class Renderers {
|
|||||||
return result;
|
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() + "'" +
|
result.text(newText().normal("'" + typeParameterWithCapturedConstraint.getName() + "'" +
|
||||||
" cannot capture " +
|
" cannot capture " +
|
||||||
"'" + capturedTypeConstructor.getTypeProjection() + "'. " +
|
"'" + capturedTypeConstructor.getTypeProjection() + "'. " +
|
||||||
"Only top level type projections can be captured"));
|
explanation));
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+16
@@ -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)
|
||||||
|
}
|
||||||
+6
@@ -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);
|
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")
|
@TestMetadata("captureForNullableTypes.kt")
|
||||||
public void testCaptureForNullableTypes() throws Exception {
|
public void testCaptureForNullableTypes() throws Exception {
|
||||||
String fileName = JetTestUtils.navigationMetadata("compiler/testData/diagnostics/tests/inference/capturedTypes/captureForNullableTypes.kt");
|
String fileName = JetTestUtils.navigationMetadata("compiler/testData/diagnostics/tests/inference/capturedTypes/captureForNullableTypes.kt");
|
||||||
|
|||||||
+6
-1
@@ -379,7 +379,12 @@ public class ConstraintSystemImpl : ConstraintSystem {
|
|||||||
constrainingTypeProjection: TypeProjection,
|
constrainingTypeProjection: TypeProjection,
|
||||||
constraintPosition: ConstraintPosition
|
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()) {
|
val typeProjection = if (parameterType.isMarkedNullable()) {
|
||||||
TypeProjectionImpl(constrainingTypeProjection.getProjectionKind(), TypeUtils.makeNotNullable(constrainingTypeProjection.getType()))
|
TypeProjectionImpl(constrainingTypeProjection.getProjectionKind(), TypeUtils.makeNotNullable(constrainingTypeProjection.getType()))
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -878,6 +878,10 @@ public class KotlinBuiltIns {
|
|||||||
return isConstructedFromGivenClass(type, FQ_NAMES.any);
|
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) {
|
public static boolean isUnit(@NotNull JetType type) {
|
||||||
return isNotNullConstructedFromGivenClass(type, FQ_NAMES.unit);
|
return isNotNullConstructedFromGivenClass(type, FQ_NAMES.unit);
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user