Don't approximate abbreviation during substitution it as it can't be projected at top-level

^KT-42036 Fixed
This commit is contained in:
Victor Petukhov
2020-12-29 14:21:08 +03:00
parent 009add2b41
commit 30a5eee481
17 changed files with 258 additions and 4 deletions
@@ -12426,6 +12426,12 @@ public class FirOldFrontendDiagnosticsTestGenerated extends AbstractFirDiagnosti
runTest("compiler/testData/diagnostics/tests/inference/capturedTypes/capturedTypeWithTypeVariableSubtyping.kt");
}
@Test
@TestMetadata("capturedTypesSubstitutionIntoAbbreviation.kt")
public void testCapturedTypesSubstitutionIntoAbbreviation() throws Exception {
runTest("compiler/testData/diagnostics/tests/inference/capturedTypes/capturedTypesSubstitutionIntoAbbreviation.kt");
}
@Test
@TestMetadata("capturingFromArgumentOfFlexibleType.kt")
public void testCapturingFromArgumentOfFlexibleType() throws Exception {
@@ -13301,6 +13301,11 @@ public class FirBlackBoxCodegenTestGenerated extends AbstractFirBlackBoxCodegenT
runTest("compiler/testData/codegen/box/inference/capturedStarProjection.kt");
}
@TestMetadata("capturedTypesSubstitutionIntoAbbreviation.kt")
public void testCapturedTypesSubstitutionIntoAbbreviation() throws Exception {
runTest("compiler/testData/codegen/box/inference/capturedTypesSubstitutionIntoAbbreviation.kt");
}
@TestMetadata("coercionToUnitForLambdaReturnTypeWithFlexibleConstraint.kt")
public void testCoercionToUnitForLambdaReturnTypeWithFlexibleConstraint() throws Exception {
runTest("compiler/testData/codegen/box/inference/coercionToUnitForLambdaReturnTypeWithFlexibleConstraint.kt");
@@ -0,0 +1,32 @@
typealias Action<K> = (@UnsafeVariance K) -> Unit
typealias Action2<K> = (@UnsafeVariance K) -> K
data class Tag<L>(val action: Action<L>)
data class Tag2<L>(val action: Action<in L>)
data class Tag3<in L>(val action: Action<L>)
data class Tag4<in L>(val action: Action<in L>)
data class Tag5<L>(val action: Action2<L>)
data class Tag6<out L>(val action: Action<in L>)
data class Tag7<out L>(val action: Action<L>)
data class Tag8<out L>(val action: Action2<L>)
fun getTag(): Tag<*> = Tag<Int> {}
fun getTag2(): Tag2<*> = Tag2<Int> {}
fun getTag3(): Tag3<*> = Tag3<Int> {}
fun getTag4(): Tag4<*> = Tag4<Int> {}
fun getTag5(): Tag5<*> = Tag5<Int> { 1 }
fun getTag6(): Tag6<*> = Tag6<Int> { }
fun getTag7(): Tag7<*> = Tag7<Int> { }
fun getTag8(): Tag8<*> = Tag8<Int> { 1 }
fun box(): String {
getTag().action
getTag2().action
getTag3().action
getTag4().action
getTag5().action
getTag6().action
getTag7().action
getTag8().action
return "OK"
}
@@ -0,0 +1,31 @@
typealias Action<K> = (@UnsafeVariance K) -> Unit
typealias Action2<K> = (@UnsafeVariance K) -> K
data class Tag<L>(val action: Action<L>)
data class Tag2<L>(val action: Action<in L>)
data class Tag3<in L>(val action: Action<L>)
data class Tag4<in L>(val action: Action<in L>)
data class Tag5<L>(val action: Action2<L>)
data class Tag6<out L>(val action: Action<in L>)
data class Tag7<out L>(val action: Action<L>)
data class Tag8<out L>(val action: Action2<L>)
fun getTag(): Tag<*> = Tag<Int> {}
fun getTag2(): Tag2<*> = Tag2<Int> {}
fun getTag3(): Tag3<*> = Tag3<Int> {}
fun getTag4(): Tag4<*> = Tag4<Int> {}
fun getTag5(): Tag5<*> = Tag5<Int> { 1 }
fun getTag6(): Tag6<*> = Tag6<Int> { }
fun getTag7(): Tag7<*> = Tag7<Int> { }
fun getTag8(): Tag8<*> = Tag8<Int> { 1 }
fun main() {
<!DEBUG_INFO_EXPRESSION_TYPE("kotlin.Function1<kotlin.Nothing, kotlin.Unit>")!>getTag().action<!>
<!DEBUG_INFO_EXPRESSION_TYPE("kotlin.Function1<kotlin.Nothing, kotlin.Unit>")!>getTag2().action<!>
<!DEBUG_INFO_EXPRESSION_TYPE("kotlin.Function1<kotlin.Nothing, kotlin.Unit>")!>getTag3().action<!>
<!DEBUG_INFO_EXPRESSION_TYPE("kotlin.Function1<kotlin.Nothing, kotlin.Unit>")!>getTag4().action<!>
<!DEBUG_INFO_EXPRESSION_TYPE("kotlin.Function1<kotlin.Nothing, kotlin.Any?>")!>getTag5().action<!>
<!DEBUG_INFO_EXPRESSION_TYPE("kotlin.Function1<kotlin.Nothing, kotlin.Unit>")!>getTag6().action<!>
<!DEBUG_INFO_EXPRESSION_TYPE("kotlin.Function1<kotlin.Nothing, kotlin.Unit>")!>getTag7().action<!>
<!DEBUG_INFO_EXPRESSION_TYPE("kotlin.Function1<kotlin.Nothing, kotlin.Any?>")!>getTag8().action<!>
}
@@ -0,0 +1,31 @@
typealias Action<K> = (@UnsafeVariance K) -> Unit
typealias Action2<K> = (@UnsafeVariance K) -> K
data class Tag<L>(val action: Action<L>)
data class Tag2<L>(val action: Action<in L>)
data class Tag3<in L>(val action: Action<L>)
data class Tag4<in L>(val action: Action<in L>)
data class Tag5<L>(val action: Action2<L>)
data class Tag6<out L>(val action: Action<in L>)
data class Tag7<out L>(val action: Action<L>)
data class Tag8<out L>(val action: Action2<L>)
fun getTag(): Tag<*> = Tag<Int> {}
fun getTag2(): Tag2<*> = Tag2<Int> {}
fun getTag3(): Tag3<*> = Tag3<Int> {}
fun getTag4(): Tag4<*> = Tag4<Int> {}
fun getTag5(): Tag5<*> = Tag5<Int> { 1 }
fun getTag6(): Tag6<*> = Tag6<Int> { }
fun getTag7(): Tag7<*> = Tag7<Int> { }
fun getTag8(): Tag8<*> = Tag8<Int> { 1 }
fun main() {
<!DEBUG_INFO_EXPRESSION_TYPE("Action<CapturedType(*)> /* = (kotlin.Any?) -> kotlin.Unit */")!>getTag().action<!>
<!DEBUG_INFO_EXPRESSION_TYPE("Action<in CapturedType(*)> /* = (kotlin.Any?) -> kotlin.Unit */")!>getTag2().action<!>
<!DEBUG_INFO_EXPRESSION_TYPE("Action<CapturedType(*)> /* = (kotlin.Any?) -> kotlin.Unit */")!>getTag3().action<!>
<!DEBUG_INFO_EXPRESSION_TYPE("Action<in CapturedType(*)> /* = (kotlin.Any?) -> kotlin.Unit */")!>getTag4().action<!>
<!DEBUG_INFO_EXPRESSION_TYPE("(kotlin.Any?) -> kotlin.Any?")!>getTag5().action<!>
<!DEBUG_INFO_EXPRESSION_TYPE("Action<in CapturedType(*)> /* = (kotlin.Any?) -> kotlin.Unit */")!>getTag6().action<!>
<!DEBUG_INFO_EXPRESSION_TYPE("Action<CapturedType(*)> /* = (kotlin.Any?) -> kotlin.Unit */")!>getTag7().action<!>
<!DEBUG_INFO_EXPRESSION_TYPE("(kotlin.Any?) -> kotlin.Any?")!>getTag8().action<!>
}
@@ -0,0 +1,93 @@
package
public fun getTag(): Tag<*>
public fun getTag2(): Tag2<*>
public fun getTag3(): Tag3<*>
public fun getTag4(): Tag4<*>
public fun getTag5(): Tag5<*>
public fun getTag6(): Tag6<*>
public fun getTag7(): Tag7<*>
public fun getTag8(): Tag8<*>
public fun main(): kotlin.Unit
public final data class Tag</*0*/ L> {
public constructor Tag</*0*/ L>(/*0*/ action: Action<L> /* = (@kotlin.UnsafeVariance L) -> kotlin.Unit */)
public final val action: Action<L> /* = (@kotlin.UnsafeVariance L) -> kotlin.Unit */
public final operator /*synthesized*/ fun component1(): Action<L> /* = (@kotlin.UnsafeVariance L) -> kotlin.Unit */
public final /*synthesized*/ fun copy(/*0*/ action: Action<L> /* = (@kotlin.UnsafeVariance L) -> kotlin.Unit */ = ...): Tag<L>
public open override /*1*/ /*synthesized*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean
public open override /*1*/ /*synthesized*/ fun hashCode(): kotlin.Int
public open override /*1*/ /*synthesized*/ fun toString(): kotlin.String
}
public final data class Tag2</*0*/ L> {
public constructor Tag2</*0*/ L>(/*0*/ action: Action<in L> /* = (in @kotlin.UnsafeVariance L) -> kotlin.Unit */)
public final val action: Action<in L> /* = (in @kotlin.UnsafeVariance L) -> kotlin.Unit */
public final operator /*synthesized*/ fun component1(): Action<in L> /* = (in @kotlin.UnsafeVariance L) -> kotlin.Unit */
public final /*synthesized*/ fun copy(/*0*/ action: Action<in L> /* = (in @kotlin.UnsafeVariance L) -> kotlin.Unit */ = ...): Tag2<L>
public open override /*1*/ /*synthesized*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean
public open override /*1*/ /*synthesized*/ fun hashCode(): kotlin.Int
public open override /*1*/ /*synthesized*/ fun toString(): kotlin.String
}
public final data class Tag3</*0*/ in L> {
public constructor Tag3</*0*/ in L>(/*0*/ action: Action<L> /* = (@kotlin.UnsafeVariance L) -> kotlin.Unit */)
public final val action: Action<L> /* = (@kotlin.UnsafeVariance L) -> kotlin.Unit */
public final operator /*synthesized*/ fun component1(): Action<L> /* = (@kotlin.UnsafeVariance L) -> kotlin.Unit */
public final /*synthesized*/ fun copy(/*0*/ action: Action<L> /* = (@kotlin.UnsafeVariance L) -> kotlin.Unit */ = ...): Tag3<L>
public open override /*1*/ /*synthesized*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean
public open override /*1*/ /*synthesized*/ fun hashCode(): kotlin.Int
public open override /*1*/ /*synthesized*/ fun toString(): kotlin.String
}
public final data class Tag4</*0*/ in L> {
public constructor Tag4</*0*/ in L>(/*0*/ action: Action<in L> /* = (in @kotlin.UnsafeVariance L) -> kotlin.Unit */)
public final val action: Action<in L> /* = (in @kotlin.UnsafeVariance L) -> kotlin.Unit */
public final operator /*synthesized*/ fun component1(): Action<in L> /* = (in @kotlin.UnsafeVariance L) -> kotlin.Unit */
public final /*synthesized*/ fun copy(/*0*/ action: Action<in L> /* = (in @kotlin.UnsafeVariance L) -> kotlin.Unit */ = ...): Tag4<L>
public open override /*1*/ /*synthesized*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean
public open override /*1*/ /*synthesized*/ fun hashCode(): kotlin.Int
public open override /*1*/ /*synthesized*/ fun toString(): kotlin.String
}
public final data class Tag5</*0*/ L> {
public constructor Tag5</*0*/ L>(/*0*/ action: Action2<L> /* = (@kotlin.UnsafeVariance L) -> L */)
public final val action: Action2<L> /* = (@kotlin.UnsafeVariance L) -> L */
public final operator /*synthesized*/ fun component1(): Action2<L> /* = (@kotlin.UnsafeVariance L) -> L */
public final /*synthesized*/ fun copy(/*0*/ action: Action2<L> /* = (@kotlin.UnsafeVariance L) -> L */ = ...): Tag5<L>
public open override /*1*/ /*synthesized*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean
public open override /*1*/ /*synthesized*/ fun hashCode(): kotlin.Int
public open override /*1*/ /*synthesized*/ fun toString(): kotlin.String
}
public final data class Tag6</*0*/ out L> {
public constructor Tag6</*0*/ out L>(/*0*/ action: Action<in L> /* = (in @kotlin.UnsafeVariance L) -> kotlin.Unit */)
public final val action: Action<in L> /* = (in @kotlin.UnsafeVariance L) -> kotlin.Unit */
public final operator /*synthesized*/ fun component1(): Action<in L> /* = (in @kotlin.UnsafeVariance L) -> kotlin.Unit */
public final /*synthesized*/ fun copy(/*0*/ action: Action<in L> /* = (in @kotlin.UnsafeVariance L) -> kotlin.Unit */ = ...): Tag6<L>
public open override /*1*/ /*synthesized*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean
public open override /*1*/ /*synthesized*/ fun hashCode(): kotlin.Int
public open override /*1*/ /*synthesized*/ fun toString(): kotlin.String
}
public final data class Tag7</*0*/ out L> {
public constructor Tag7</*0*/ out L>(/*0*/ action: Action<L> /* = (@kotlin.UnsafeVariance L) -> kotlin.Unit */)
public final val action: Action<L> /* = (@kotlin.UnsafeVariance L) -> kotlin.Unit */
public final operator /*synthesized*/ fun component1(): Action<L> /* = (@kotlin.UnsafeVariance L) -> kotlin.Unit */
public final /*synthesized*/ fun copy(/*0*/ action: Action<L> /* = (@kotlin.UnsafeVariance L) -> kotlin.Unit */ = ...): Tag7<L>
public open override /*1*/ /*synthesized*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean
public open override /*1*/ /*synthesized*/ fun hashCode(): kotlin.Int
public open override /*1*/ /*synthesized*/ fun toString(): kotlin.String
}
public final data class Tag8</*0*/ out L> {
public constructor Tag8</*0*/ out L>(/*0*/ action: Action2<L> /* = (@kotlin.UnsafeVariance L) -> L */)
public final val action: Action2<L> /* = (@kotlin.UnsafeVariance L) -> L */
public final operator /*synthesized*/ fun component1(): Action2<L> /* = (@kotlin.UnsafeVariance L) -> L */
public final /*synthesized*/ fun copy(/*0*/ action: Action2<L> /* = (@kotlin.UnsafeVariance L) -> L */ = ...): Tag8<L>
public open override /*1*/ /*synthesized*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean
public open override /*1*/ /*synthesized*/ fun hashCode(): kotlin.Int
public open override /*1*/ /*synthesized*/ fun toString(): kotlin.String
}
public typealias Action</*0*/ K> = (@kotlin.UnsafeVariance K) -> kotlin.Unit
public typealias Action2</*0*/ K> = (@kotlin.UnsafeVariance K) -> K
@@ -12432,6 +12432,12 @@ public class DiagnosticTestGenerated extends AbstractDiagnosticTest {
runTest("compiler/testData/diagnostics/tests/inference/capturedTypes/capturedTypeWithTypeVariableSubtyping.kt");
}
@Test
@TestMetadata("capturedTypesSubstitutionIntoAbbreviation.kt")
public void testCapturedTypesSubstitutionIntoAbbreviation() throws Exception {
runTest("compiler/testData/diagnostics/tests/inference/capturedTypes/capturedTypesSubstitutionIntoAbbreviation.kt");
}
@Test
@TestMetadata("capturingFromArgumentOfFlexibleType.kt")
public void testCapturingFromArgumentOfFlexibleType() throws Exception {
@@ -13301,6 +13301,11 @@ public class BlackBoxCodegenTestGenerated extends AbstractBlackBoxCodegenTest {
runTest("compiler/testData/codegen/box/inference/capturedStarProjection.kt");
}
@TestMetadata("capturedTypesSubstitutionIntoAbbreviation.kt")
public void testCapturedTypesSubstitutionIntoAbbreviation() throws Exception {
runTest("compiler/testData/codegen/box/inference/capturedTypesSubstitutionIntoAbbreviation.kt");
}
@TestMetadata("coercionToUnitForLambdaReturnTypeWithFlexibleConstraint.kt")
public void testCoercionToUnitForLambdaReturnTypeWithFlexibleConstraint() throws Exception {
runTest("compiler/testData/codegen/box/inference/coercionToUnitForLambdaReturnTypeWithFlexibleConstraint.kt");
@@ -13301,6 +13301,11 @@ public class LightAnalysisModeTestGenerated extends AbstractLightAnalysisModeTes
runTest("compiler/testData/codegen/box/inference/capturedStarProjection.kt");
}
@TestMetadata("capturedTypesSubstitutionIntoAbbreviation.kt")
public void testCapturedTypesSubstitutionIntoAbbreviation() throws Exception {
runTest("compiler/testData/codegen/box/inference/capturedTypesSubstitutionIntoAbbreviation.kt");
}
@TestMetadata("coercionToUnitForLambdaReturnTypeWithFlexibleConstraint.kt")
public void testCoercionToUnitForLambdaReturnTypeWithFlexibleConstraint() throws Exception {
runTest("compiler/testData/codegen/box/inference/coercionToUnitForLambdaReturnTypeWithFlexibleConstraint.kt");
@@ -13301,6 +13301,11 @@ public class IrBlackBoxCodegenTestGenerated extends AbstractIrBlackBoxCodegenTes
runTest("compiler/testData/codegen/box/inference/capturedStarProjection.kt");
}
@TestMetadata("capturedTypesSubstitutionIntoAbbreviation.kt")
public void testCapturedTypesSubstitutionIntoAbbreviation() throws Exception {
runTest("compiler/testData/codegen/box/inference/capturedTypesSubstitutionIntoAbbreviation.kt");
}
@TestMetadata("coercionToUnitForLambdaReturnTypeWithFlexibleConstraint.kt")
public void testCoercionToUnitForLambdaReturnTypeWithFlexibleConstraint() throws Exception {
runTest("compiler/testData/codegen/box/inference/coercionToUnitForLambdaReturnTypeWithFlexibleConstraint.kt");
@@ -122,7 +122,7 @@ fun TypeSubstitution.wrapWithCapturingSubstitution(needApproximation: Boolean =
this.arguments.zip(this.parameters).map {
it.first.createCapturedIfNeeded(it.second)
}.toTypedArray(),
approximateCapturedTypes = needApproximation
approximateContravariantCapturedTypes = needApproximation
)
else
object : DelegatedTypeSubstitution(this@wrapWithCapturingSubstitution) {
@@ -88,7 +88,7 @@ abstract class TypeConstructorSubstitution : TypeSubstitution() {
class IndexedParametersSubstitution(
val parameters: Array<TypeParameterDescriptor>,
val arguments: Array<TypeProjection>,
private val approximateCapturedTypes: Boolean = false
private val approximateContravariantCapturedTypes: Boolean = false
) : TypeSubstitution() {
init {
assert(parameters.size <= arguments.size) {
@@ -103,7 +103,7 @@ class IndexedParametersSubstitution(
override fun isEmpty(): Boolean = arguments.isEmpty()
override fun approximateContravariantCapturedTypes() = approximateCapturedTypes
override fun approximateContravariantCapturedTypes() = approximateContravariantCapturedTypes
override fun get(key: KotlinType): TypeProjection? {
val parameter = key.constructor.declarationDescriptor as? TypeParameterDescriptor ?: return null
@@ -54,6 +54,19 @@ public class TypeSubstitutor implements TypeSubstitutorMarker {
return new TypeSubstitutor(substitution);
}
@NotNull
public TypeSubstitutor replaceWithNonApproximatingSubstitution() {
if (!(substitution instanceof IndexedParametersSubstitution) || !substitution.approximateContravariantCapturedTypes()) return this;
return new TypeSubstitutor(
new IndexedParametersSubstitution(
((IndexedParametersSubstitution) substitution).getParameters(),
((IndexedParametersSubstitution) substitution).getArguments(),
false
)
);
}
@NotNull
public static TypeSubstitutor createChainedSubstitutor(@NotNull TypeSubstitution first, @NotNull TypeSubstitution second) {
return create(DisjointKeysUnionTypeSubstitution.create(first, second));
@@ -302,7 +315,9 @@ public class TypeSubstitutor implements TypeSubstitutorMarker {
KotlinType substitutedAbbreviation = null;
SimpleType abbreviation = SpecialTypesKt.getAbbreviation(type);
if (abbreviation != null) {
substitutedAbbreviation = substitute(abbreviation, Variance.INVARIANT);
// We shouldn't approximate abbreviation at the top-level as they can't be projected: below we substitute this always as invariant
TypeSubstitutor substitutorForAbbreviation = replaceWithNonApproximatingSubstitution();
substitutedAbbreviation = substitutorForAbbreviation.substitute(abbreviation, Variance.INVARIANT);
}
List<TypeProjection> substitutedArguments = substituteTypeArguments(
@@ -11386,6 +11386,11 @@ public class IrJsCodegenBoxES6TestGenerated extends AbstractIrJsCodegenBoxES6Tes
runTest("compiler/testData/codegen/box/inference/capturedStarProjection.kt");
}
@TestMetadata("capturedTypesSubstitutionIntoAbbreviation.kt")
public void testCapturedTypesSubstitutionIntoAbbreviation() throws Exception {
runTest("compiler/testData/codegen/box/inference/capturedTypesSubstitutionIntoAbbreviation.kt");
}
@TestMetadata("coercionToUnitWithLastLambdaExpression.kt")
public void testCoercionToUnitWithLastLambdaExpression() throws Exception {
runTest("compiler/testData/codegen/box/inference/coercionToUnitWithLastLambdaExpression.kt");
@@ -11386,6 +11386,11 @@ public class IrJsCodegenBoxTestGenerated extends AbstractIrJsCodegenBoxTest {
runTest("compiler/testData/codegen/box/inference/capturedStarProjection.kt");
}
@TestMetadata("capturedTypesSubstitutionIntoAbbreviation.kt")
public void testCapturedTypesSubstitutionIntoAbbreviation() throws Exception {
runTest("compiler/testData/codegen/box/inference/capturedTypesSubstitutionIntoAbbreviation.kt");
}
@TestMetadata("coercionToUnitWithLastLambdaExpression.kt")
public void testCoercionToUnitWithLastLambdaExpression() throws Exception {
runTest("compiler/testData/codegen/box/inference/coercionToUnitWithLastLambdaExpression.kt");
@@ -11451,6 +11451,11 @@ public class JsCodegenBoxTestGenerated extends AbstractJsCodegenBoxTest {
runTest("compiler/testData/codegen/box/inference/capturedStarProjection.kt");
}
@TestMetadata("capturedTypesSubstitutionIntoAbbreviation.kt")
public void testCapturedTypesSubstitutionIntoAbbreviation() throws Exception {
runTest("compiler/testData/codegen/box/inference/capturedTypesSubstitutionIntoAbbreviation.kt");
}
@TestMetadata("coercionToUnitWithLastLambdaExpression.kt")
public void testCoercionToUnitWithLastLambdaExpression() throws Exception {
runTest("compiler/testData/codegen/box/inference/coercionToUnitWithLastLambdaExpression.kt");
@@ -6092,6 +6092,11 @@ public class IrCodegenBoxWasmTestGenerated extends AbstractIrCodegenBoxWasmTest
runTest("compiler/testData/codegen/box/inference/capturedStarProjection.kt");
}
@TestMetadata("capturedTypesSubstitutionIntoAbbreviation.kt")
public void testCapturedTypesSubstitutionIntoAbbreviation() throws Exception {
runTest("compiler/testData/codegen/box/inference/capturedTypesSubstitutionIntoAbbreviation.kt");
}
@TestMetadata("earlyReturnInsideCrossinlineLambda.kt")
public void testEarlyReturnInsideCrossinlineLambda() throws Exception {
runTest("compiler/testData/codegen/box/inference/earlyReturnInsideCrossinlineLambda.kt");