Change default rules for declaration-site wildcards

Mostly this commit is about skipping wildcards that are redundant in some sense.
The motivation is that they looks `long` in Java code.

There are basically two important parts: return types and value parameters.

1. For return types default behaviour is skipping all declaration-site wildcards.
The intuition behind this rule is simple: return types are basically used in subtype position
(as an argument for another call), and here everything works well in case of 'out'-variance.
For example we have 'Out<Out<T>>>' as subtype both for 'Out<Out<T>>>' and 'Out<? extends Out<? extends T>>>',
so values of such type is more flexible in contrast to `Out<? extends Out<? extends T>>>` that could be used only
for the second case.

But we have choosen to treat `in`-variance in a different way: argument itself
should be rendered without wildcard while nested arguments are rendered by the rules
described further (see second part).

For example: 'In<Out<OpenClass>>' will have generic signature 'In<Out<? extends OpenClass>>'.
If we omit all wildcards here, then value of type 'In<Out<OpenClass>>'
will be impossible to use as argument for function expecting 'In<? super Out<? extends Derived>>'
where Derived <: OpenClass (you can check it manually :]).

And this exception should not be very inconvinient because in-variance is rather rare.

2. For value parameters we decided to skip wildcards if it doesn't make obtained signature weaker
in a sense of set of acceptable arguments.

More precisely:
    a. We write wildcard for 'Out<T>' iff T ``can have subtypes ignoring nullability''
    b. We write wildcard for 'In<T>' iff T is not equal to it's class upper bound (ignoring nullability again)

Definition of ``can have subtypes ignoring nullability'' is straightforward and you can see it in commit.

 #KT-9801 Fixed
 #KT-9890 Fixed
This commit is contained in:
Denis Zharkov
2015-11-23 19:45:48 +03:00
parent 1731cb8b40
commit 406e31f54a
29 changed files with 620 additions and 60 deletions
@@ -3696,6 +3696,12 @@ public class BlackBoxWithStdlibCodegenTestGenerated extends AbstractBlackBoxCode
KotlinTestUtils.assertAllTestsPresentByMetadata(this.getClass(), new File("compiler/testData/codegen/boxWithStdlib/reflection/genericSignature"), Pattern.compile("^(.+)\\.kt$"), true);
}
@TestMetadata("covariantOverride.kt")
public void testCovariantOverride() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/boxWithStdlib/reflection/genericSignature/covariantOverride.kt");
doTestWithStdlib(fileName);
}
@TestMetadata("kt5112.kt")
public void testKt5112() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/boxWithStdlib/reflection/genericSignature/kt5112.kt");
@@ -223,6 +223,12 @@ public class WriteSignatureTestGenerated extends AbstractWriteSignatureTest {
doTest(fileName);
}
@TestMetadata("GenericOverrides.kt")
public void testGenericOverrides() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/writeSignature/declarationSiteVariance/GenericOverrides.kt");
doTest(fileName);
}
@TestMetadata("InInInPosition.kt")
public void testInInInPosition() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/writeSignature/declarationSiteVariance/InInInPosition.kt");
@@ -265,6 +271,18 @@ public class WriteSignatureTestGenerated extends AbstractWriteSignatureTest {
doTest(fileName);
}
@TestMetadata("OpenMembersReturnType.kt")
public void testOpenMembersReturnType() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/writeSignature/declarationSiteVariance/OpenMembersReturnType.kt");
doTest(fileName);
}
@TestMetadata("OpenMembersValueParameter.kt")
public void testOpenMembersValueParameter() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/writeSignature/declarationSiteVariance/OpenMembersValueParameter.kt");
doTest(fileName);
}
@TestMetadata("OutInField.kt")
public void testOutInField() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/writeSignature/declarationSiteVariance/OutInField.kt");
@@ -354,6 +372,75 @@ public class WriteSignatureTestGenerated extends AbstractWriteSignatureTest {
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/writeSignature/declarationSiteVariance/SuperTypeWithVarianceInArguments.kt");
doTest(fileName);
}
@TestMetadata("compiler/testData/writeSignature/declarationSiteVariance/wildcardOptimization")
@TestDataPath("$PROJECT_ROOT")
@RunWith(JUnit3RunnerWithInners.class)
public static class WildcardOptimization extends AbstractWriteSignatureTest {
public void testAllFilesPresentInWildcardOptimization() throws Exception {
KotlinTestUtils.assertAllTestsPresentByMetadata(this.getClass(), new File("compiler/testData/writeSignature/declarationSiteVariance/wildcardOptimization"), Pattern.compile("^(.+)\\.kt$"), true);
}
@TestMetadata("argumentOverridability.kt")
public void testArgumentOverridability() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/writeSignature/declarationSiteVariance/wildcardOptimization/argumentOverridability.kt");
doTest(fileName);
}
@TestMetadata("arrays.kt")
public void testArrays() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/writeSignature/declarationSiteVariance/wildcardOptimization/arrays.kt");
doTest(fileName);
}
@TestMetadata("complicatedInBounds.kt")
public void testComplicatedInBounds() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/writeSignature/declarationSiteVariance/wildcardOptimization/complicatedInBounds.kt");
doTest(fileName);
}
@TestMetadata("deepOut.kt")
public void testDeepOut() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/writeSignature/declarationSiteVariance/wildcardOptimization/deepOut.kt");
doTest(fileName);
}
@TestMetadata("finalReturnType.kt")
public void testFinalReturnType() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/writeSignature/declarationSiteVariance/wildcardOptimization/finalReturnType.kt");
doTest(fileName);
}
@TestMetadata("outIn.kt")
public void testOutIn() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/writeSignature/declarationSiteVariance/wildcardOptimization/outIn.kt");
doTest(fileName);
}
@TestMetadata("outInv.kt")
public void testOutInv() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/writeSignature/declarationSiteVariance/wildcardOptimization/outInv.kt");
doTest(fileName);
}
@TestMetadata("topLevelIn.kt")
public void testTopLevelIn() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/writeSignature/declarationSiteVariance/wildcardOptimization/topLevelIn.kt");
doTest(fileName);
}
@TestMetadata("topLevelInv.kt")
public void testTopLevelInv() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/writeSignature/declarationSiteVariance/wildcardOptimization/topLevelInv.kt");
doTest(fileName);
}
@TestMetadata("typeParameter.kt")
public void testTypeParameter() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/writeSignature/declarationSiteVariance/wildcardOptimization/typeParameter.kt");
doTest(fileName);
}
}
}
@TestMetadata("compiler/testData/writeSignature/nothing")