From 154657a37480e653f8f39cd8d956fd16db0126fe Mon Sep 17 00:00:00 2001 From: Denis Zharkov Date: Mon, 14 Dec 2015 16:49:53 +0300 Subject: [PATCH] Fix wildcards for invariant arguments See test with Java, we want preserve the invariant that if return type and value parameter types are same in Kotlin, than we can use such return-value as argument for that parameter --- .../kotlin/codegen/state/TypeMappingMode.kt | 13 +++++++++++-- .../invariantArgumentsNoWildcard/JavaClass.java | 5 +++++ .../invariantArgumentsNoWildcard/main.kt | 11 +++++++++++ .../wildcardOptimization/arrays.kt | 2 +- .../wildcardOptimization/finalReturnType.kt | 4 ++++ .../wildcardOptimization/topLevelInv.kt | 11 ++++++++++- .../BlackBoxWithJavaCodegenTestGenerated.java | 6 ++++++ 7 files changed, 48 insertions(+), 4 deletions(-) create mode 100644 compiler/testData/codegen/boxWithJava/invariantArgumentsNoWildcard/JavaClass.java create mode 100644 compiler/testData/codegen/boxWithJava/invariantArgumentsNoWildcard/main.kt diff --git a/compiler/backend/src/org/jetbrains/kotlin/codegen/state/TypeMappingMode.kt b/compiler/backend/src/org/jetbrains/kotlin/codegen/state/TypeMappingMode.kt index 202a6dddba1..9a1a8ee2ef9 100644 --- a/compiler/backend/src/org/jetbrains/kotlin/codegen/state/TypeMappingMode.kt +++ b/compiler/backend/src/org/jetbrains/kotlin/codegen/state/TypeMappingMode.kt @@ -26,7 +26,8 @@ internal class TypeMappingMode private constructor( val skipDeclarationSiteWildcards: Boolean = false, val skipDeclarationSiteWildcardsIfPossible: Boolean = false, private val genericArgumentMode: TypeMappingMode? = null, - private val genericContravariantArgumentMode: TypeMappingMode? = genericArgumentMode + private val genericContravariantArgumentMode: TypeMappingMode? = genericArgumentMode, + private val genericInvariantArgumentMode: TypeMappingMode? = genericArgumentMode ) { companion object { /** @@ -86,11 +87,18 @@ internal class TypeMappingMode private constructor( else null + val invariantArgumentMode = + if (canBeUsedInSupertypePosition) + getOptimalModeForSignaturePart(type, isForAnnotationParameter, canBeUsedInSupertypePosition = false) + else + null + return TypeMappingMode( isForAnnotationParameter = isForAnnotationParameter, skipDeclarationSiteWildcards = !canBeUsedInSupertypePosition, skipDeclarationSiteWildcardsIfPossible = true, - genericContravariantArgumentMode = contravariantArgumentMode) + genericContravariantArgumentMode = contravariantArgumentMode, + genericInvariantArgumentMode = invariantArgumentMode) } @JvmStatic @@ -107,6 +115,7 @@ internal class TypeMappingMode private constructor( fun toGenericArgumentMode(effectiveVariance: Variance): TypeMappingMode = when (effectiveVariance) { Variance.IN_VARIANCE -> genericContravariantArgumentMode ?: this + Variance.INVARIANT -> genericInvariantArgumentMode ?: this else -> genericArgumentMode ?: this } } diff --git a/compiler/testData/codegen/boxWithJava/invariantArgumentsNoWildcard/JavaClass.java b/compiler/testData/codegen/boxWithJava/invariantArgumentsNoWildcard/JavaClass.java new file mode 100644 index 00000000000..8a74860ebce --- /dev/null +++ b/compiler/testData/codegen/boxWithJava/invariantArgumentsNoWildcard/JavaClass.java @@ -0,0 +1,5 @@ +public class JavaClass { + public static String test() { + return MainKt.bar(MainKt.foo()); + } +} diff --git a/compiler/testData/codegen/boxWithJava/invariantArgumentsNoWildcard/main.kt b/compiler/testData/codegen/boxWithJava/invariantArgumentsNoWildcard/main.kt new file mode 100644 index 00000000000..5b49da06360 --- /dev/null +++ b/compiler/testData/codegen/boxWithJava/invariantArgumentsNoWildcard/main.kt @@ -0,0 +1,11 @@ +class Pair(val x: X, val y: Y) + +class Inv(val x: T) + +fun foo(): Inv> = Inv(Pair("O", "K")) + +fun bar(inv: Inv>) = inv.x.x.toString() + inv.x.y + +fun box(): String { + return JavaClass.test(); +} diff --git a/compiler/testData/writeSignature/declarationSiteVariance/wildcardOptimization/arrays.kt b/compiler/testData/writeSignature/declarationSiteVariance/wildcardOptimization/arrays.kt index 56d05c125da..3ce2d3188dd 100644 --- a/compiler/testData/writeSignature/declarationSiteVariance/wildcardOptimization/arrays.kt +++ b/compiler/testData/writeSignature/declarationSiteVariance/wildcardOptimization/arrays.kt @@ -8,7 +8,7 @@ open class Open fun arrayOfOutOpen(x: Array>) {} // method: ArraysKt::arrayOfOutOpen -// generic signature: ([LOut<+LOpen;>;)V +// generic signature: ([LOut;)V fun arrayOfOutFinal(x: Array>) {} // method: ArraysKt::arrayOfOutFinal diff --git a/compiler/testData/writeSignature/declarationSiteVariance/wildcardOptimization/finalReturnType.kt b/compiler/testData/writeSignature/declarationSiteVariance/wildcardOptimization/finalReturnType.kt index 60ce5ef71f3..b2b66903eee 100644 --- a/compiler/testData/writeSignature/declarationSiteVariance/wildcardOptimization/finalReturnType.kt +++ b/compiler/testData/writeSignature/declarationSiteVariance/wildcardOptimization/finalReturnType.kt @@ -10,6 +10,10 @@ fun skipAllOutInvWildcards(): Inv>>> = null!! // method: FinalReturnTypeKt::skipAllOutInvWildcards // generic signature: ()LInv;>;>;>; +fun skipAllInvWildcards(): Inv>> = null!! +// method: FinalReturnTypeKt::skipAllInvWildcards +// generic signature: ()LInv;>;>; + fun notDeepIn(): In = null!! // method: FinalReturnTypeKt::notDeepIn // generic signature: ()LIn; diff --git a/compiler/testData/writeSignature/declarationSiteVariance/wildcardOptimization/topLevelInv.kt b/compiler/testData/writeSignature/declarationSiteVariance/wildcardOptimization/topLevelInv.kt index b83b6b94188..fee1e10eb6b 100644 --- a/compiler/testData/writeSignature/declarationSiteVariance/wildcardOptimization/topLevelInv.kt +++ b/compiler/testData/writeSignature/declarationSiteVariance/wildcardOptimization/topLevelInv.kt @@ -1,4 +1,5 @@ class Inv +class In class Out class Final open class Open @@ -13,12 +14,20 @@ fun invFinal(x: Inv) {} fun invOutOpen(x: Inv>) {} // method: TopLevelInvKt::invOutOpen -// generic signature: (LInv;>;)V +// generic signature: (LInv;>;)V fun invOutFinal(x: Inv>) {} // method: TopLevelInvKt::invOutFinal // generic signature: (LInv;>;)V +fun invInOutOpen(x: Inv>>) {} +// method: TopLevelInvKt::invInOutOpen +// generic signature: (LInv;>;>;)V + +fun invInOutFinal(x: Inv>>) {} +// method: TopLevelInvKt::invInOutFinal +// generic signature: (LInv;>;>;)V + fun invOutProjectedOutFinal(x: Inv>) {} // method: TopLevelInvKt::invOutProjectedOutFinal // generic signature: (LInv<+LOut;>;)V diff --git a/compiler/tests/org/jetbrains/kotlin/codegen/generated/BlackBoxWithJavaCodegenTestGenerated.java b/compiler/tests/org/jetbrains/kotlin/codegen/generated/BlackBoxWithJavaCodegenTestGenerated.java index 8cceb623974..4c2949b6bbd 100644 --- a/compiler/tests/org/jetbrains/kotlin/codegen/generated/BlackBoxWithJavaCodegenTestGenerated.java +++ b/compiler/tests/org/jetbrains/kotlin/codegen/generated/BlackBoxWithJavaCodegenTestGenerated.java @@ -107,6 +107,12 @@ public class BlackBoxWithJavaCodegenTestGenerated extends AbstractBlackBoxCodege doTestWithJava(fileName); } + @TestMetadata("invariantArgumentsNoWildcard") + public void testInvariantArgumentsNoWildcard() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/boxWithJava/invariantArgumentsNoWildcard/"); + doTestWithJava(fileName); + } + @TestMetadata("jvmName") public void testJvmName() throws Exception { String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/boxWithJava/jvmName/");