From f7de0e274ccf0427dfcc3dc2582d989c3b84f100 Mon Sep 17 00:00:00 2001 From: Andrey Breslav Date: Tue, 24 Jun 2014 20:07:46 +0400 Subject: [PATCH] TypeSubstitutor respects flexible types --- .../methodCall/javaCollectionToKotlin.kt | 9 ++++++++ .../platformTypes/methodCall/javaToJava.kt | 20 ++++++++++++++++ .../platformTypes/methodCall/javaToKotlin.kt | 18 +++++++++++++++ .../methodCall/kotlinCollectionToJava.kt | 7 ++++++ .../checkers/JetDiagnosticsTestGenerated.java | 20 ++++++++++++++++ .../jet/lang/types/TypeSubstitutor.java | 23 ++++++++++++++++--- 6 files changed, 94 insertions(+), 3 deletions(-) create mode 100644 compiler/testData/diagnostics/tests/platformTypes/methodCall/javaCollectionToKotlin.kt create mode 100644 compiler/testData/diagnostics/tests/platformTypes/methodCall/javaToJava.kt create mode 100644 compiler/testData/diagnostics/tests/platformTypes/methodCall/javaToKotlin.kt create mode 100644 compiler/testData/diagnostics/tests/platformTypes/methodCall/kotlinCollectionToJava.kt diff --git a/compiler/testData/diagnostics/tests/platformTypes/methodCall/javaCollectionToKotlin.kt b/compiler/testData/diagnostics/tests/platformTypes/methodCall/javaCollectionToKotlin.kt new file mode 100644 index 00000000000..fa1baddc8f9 --- /dev/null +++ b/compiler/testData/diagnostics/tests/platformTypes/methodCall/javaCollectionToKotlin.kt @@ -0,0 +1,9 @@ +// !DIAGNOSTICS: -UNUSED_PARAMETER + +import java.util.* + +fun takeJ(map: Map) {} + +fun test() { + takeJ(HashMap()) +} \ No newline at end of file diff --git a/compiler/testData/diagnostics/tests/platformTypes/methodCall/javaToJava.kt b/compiler/testData/diagnostics/tests/platformTypes/methodCall/javaToJava.kt new file mode 100644 index 00000000000..cbd9d0da968 --- /dev/null +++ b/compiler/testData/diagnostics/tests/platformTypes/methodCall/javaToJava.kt @@ -0,0 +1,20 @@ +// FILE: p/J.java + +package p; + +import java.util.ArrayList; + +public class J { + public ArrayList list() { return null; } + public void takeList(ArrayList list) { } +} + +// FILE: k.kt + +import p.* + +fun test(j: J) { + j.takeList(j.list()) + val l = j.list() + j.takeList(l) +} \ No newline at end of file diff --git a/compiler/testData/diagnostics/tests/platformTypes/methodCall/javaToKotlin.kt b/compiler/testData/diagnostics/tests/platformTypes/methodCall/javaToKotlin.kt new file mode 100644 index 00000000000..e454e5b2dca --- /dev/null +++ b/compiler/testData/diagnostics/tests/platformTypes/methodCall/javaToKotlin.kt @@ -0,0 +1,18 @@ +// !DIAGNOSTICS: -UNUSED_PARAMETER +// FILE: p/J.java + +package p; + +public class J { + public J j() { return this; } +} + +// FILE: k.kt + +import p.* + +fun takeJ(j: J) {} + +fun test() { + takeJ(J().j()) +} \ No newline at end of file diff --git a/compiler/testData/diagnostics/tests/platformTypes/methodCall/kotlinCollectionToJava.kt b/compiler/testData/diagnostics/tests/platformTypes/methodCall/kotlinCollectionToJava.kt new file mode 100644 index 00000000000..d08d6cf52fa --- /dev/null +++ b/compiler/testData/diagnostics/tests/platformTypes/methodCall/kotlinCollectionToJava.kt @@ -0,0 +1,7 @@ +// !DIAGNOSTICS: -UNUSED_PARAMETER + +import java.util.* + +fun test(map: Map) { + HashMap(map) +} \ No newline at end of file diff --git a/compiler/tests/org/jetbrains/jet/checkers/JetDiagnosticsTestGenerated.java b/compiler/tests/org/jetbrains/jet/checkers/JetDiagnosticsTestGenerated.java index eaaacc7410f..e5ed4a63a01 100644 --- a/compiler/tests/org/jetbrains/jet/checkers/JetDiagnosticsTestGenerated.java +++ b/compiler/tests/org/jetbrains/jet/checkers/JetDiagnosticsTestGenerated.java @@ -7715,6 +7715,26 @@ public class JetDiagnosticsTestGenerated extends AbstractJetDiagnosticsTest { doTest(fileName); } + @TestMetadata("javaCollectionToKotlin.kt") + public void testJavaCollectionToKotlin() throws Exception { + doTest("compiler/testData/diagnostics/tests/platformTypes/methodCall/javaCollectionToKotlin.kt"); + } + + @TestMetadata("javaToJava.kt") + public void testJavaToJava() throws Exception { + doTest("compiler/testData/diagnostics/tests/platformTypes/methodCall/javaToJava.kt"); + } + + @TestMetadata("javaToKotlin.kt") + public void testJavaToKotlin() throws Exception { + doTest("compiler/testData/diagnostics/tests/platformTypes/methodCall/javaToKotlin.kt"); + } + + @TestMetadata("kotlinCollectionToJava.kt") + public void testKotlinCollectionToJava() throws Exception { + doTest("compiler/testData/diagnostics/tests/platformTypes/methodCall/kotlinCollectionToJava.kt"); + } + @TestMetadata("list.kt") public void testList() throws Exception { String fileName = JetTestUtils.navigationMetadata("compiler/testData/diagnostics/tests/platformTypes/methodCall/list.kt"); diff --git a/core/descriptors/src/org/jetbrains/jet/lang/types/TypeSubstitutor.java b/core/descriptors/src/org/jetbrains/jet/lang/types/TypeSubstitutor.java index 65c096b770c..a68baa3a6b1 100644 --- a/core/descriptors/src/org/jetbrains/jet/lang/types/TypeSubstitutor.java +++ b/core/descriptors/src/org/jetbrains/jet/lang/types/TypeSubstitutor.java @@ -151,8 +151,25 @@ public class TypeSubstitutor { @NotNull private TypeProjection unsafeSubstitute(@NotNull TypeProjection originalProjection, int recursionDepth) throws SubstitutionException { assertRecursionDepth(recursionDepth, originalProjection, substitution); + // The type is within the substitution range, i.e. T or T? JetType type = originalProjection.getType(); + Variance originalProjectionKind = originalProjection.getProjectionKind(); + if (type instanceof FlexibleType) { + FlexibleType flexibleType = (FlexibleType) type; + TypeProjection substitutedLower = + unsafeSubstitute(new TypeProjectionImpl(originalProjectionKind, flexibleType.getLowerBound()), recursionDepth + 1); + TypeProjection substitutedUpper = + unsafeSubstitute(new TypeProjectionImpl(originalProjectionKind, flexibleType.getUpperBound()), recursionDepth + 1); + // todo: projection kind is neglected + return new TypeProjectionImpl(originalProjectionKind, + new DelegatingFlexibleType( + substitutedLower.getType(), + substitutedUpper.getType() + ) + ); + } + if (KotlinBuiltIns.getInstance().isNothing(type) || type.isError()) return originalProjection; TypeProjection replacement = substitution.get(type.getConstructor()); @@ -161,7 +178,7 @@ public class TypeSubstitutor { // It must be a type parameter: only they can be directly substituted for TypeParameterDescriptor typeParameter = (TypeParameterDescriptor) type.getConstructor().getDeclarationDescriptor(); - switch (conflictType(originalProjection.getProjectionKind(), replacement.getProjectionKind())) { + switch (conflictType(originalProjectionKind, replacement.getProjectionKind())) { case OUT_IN_IN_POSITION: throw new SubstitutionException("Out-projection in in-position"); case IN_IN_OUT_POSITION: @@ -170,7 +187,7 @@ public class TypeSubstitutor { case NO_CONFLICT: boolean resultingIsNullable = type.isNullable() || replacement.getType().isNullable(); JetType substitutedType = TypeUtils.makeNullableAsSpecified(replacement.getType(), resultingIsNullable); - Variance resultingProjectionKind = combine(originalProjection.getProjectionKind(), replacement.getProjectionKind()); + Variance resultingProjectionKind = combine(originalProjectionKind, replacement.getProjectionKind()); return new TypeProjectionImpl(resultingProjectionKind, substitutedType); default: @@ -187,7 +204,7 @@ public class TypeSubstitutor { type.isNullable(), // Same nullability substitutedArguments, new SubstitutingScope(type.getMemberScope(), this)); - return new TypeProjectionImpl(originalProjection.getProjectionKind(), substitutedType); + return new TypeProjectionImpl(originalProjectionKind, substitutedType); } }