diff --git a/compiler/frontend/src/org/jetbrains/kotlin/resolve/TypeAliasExpander.kt b/compiler/frontend/src/org/jetbrains/kotlin/resolve/TypeAliasExpander.kt index 653d4c8098a..2cc9411bfbb 100644 --- a/compiler/frontend/src/org/jetbrains/kotlin/resolve/TypeAliasExpander.kt +++ b/compiler/frontend/src/org/jetbrains/kotlin/resolve/TypeAliasExpander.kt @@ -40,8 +40,8 @@ class TypeAliasExpander( recursionDepth: Int, withAbbreviatedType: Boolean ): SimpleType { - val originalProjection = TypeProjectionImpl(Variance.INVARIANT, typeAliasExpansion.descriptor.underlyingType) - val expandedProjection = expandTypeProjection(originalProjection, typeAliasExpansion, null, recursionDepth) + val underlyingProjection = TypeProjectionImpl(Variance.INVARIANT, typeAliasExpansion.descriptor.underlyingType) + val expandedProjection = expandTypeProjection(underlyingProjection, typeAliasExpansion, null, recursionDepth) val expandedType = expandedProjection.type.asSimpleType() if (expandedType.isError) return expandedType @@ -53,7 +53,7 @@ class TypeAliasExpander( val expandedTypeWithExtraAnnotations = combineAnnotations(expandedType, annotations) return if (withAbbreviatedType) - expandedTypeWithExtraAnnotations.withAbbreviation(typeAliasExpansion.createAbbreviation(originalProjection, annotations)) + expandedTypeWithExtraAnnotations.withAbbreviation(typeAliasExpansion.createAbbreviation(underlyingProjection, annotations)) else expandedTypeWithExtraAnnotations } @@ -80,50 +80,52 @@ class TypeAliasExpander( ) private fun expandTypeProjection( - originalProjection: TypeProjection, + underlyingProjection: TypeProjection, typeAliasExpansion: TypeAliasExpansion, typeParameterDescriptor: TypeParameterDescriptor?, recursionDepth: Int ): TypeProjection { assertRecursionDepth(recursionDepth, typeAliasExpansion.descriptor) - val originalType = originalProjection.type + if (underlyingProjection.isStarProjection) return TypeUtils.makeStarProjection(typeParameterDescriptor!!) - val typeAliasArgument = typeAliasExpansion.getReplacement(originalType.constructor) - - if (typeAliasArgument == null) { - return expandNonArgumentTypeProjection(originalProjection, typeAliasExpansion, recursionDepth) + val underlyingType = underlyingProjection.type + val argument = typeAliasExpansion.getReplacement(underlyingType.constructor) + if (argument == null) { + return expandNonArgumentTypeProjection(underlyingProjection, typeAliasExpansion, recursionDepth) } - val originalVariance = - if (originalProjection.projectionKind != Variance.INVARIANT) - originalProjection.projectionKind - else - typeParameterDescriptor?.variance ?: Variance.INVARIANT + if (argument.isStarProjection) return TypeUtils.makeStarProjection(typeParameterDescriptor!!) - val argumentVariance = typeAliasArgument.projectionKind + val argumentVariance = argument.projectionKind + val underlyingVariance = underlyingProjection.projectionKind - val substitutedVariance = - if (argumentVariance == Variance.INVARIANT) - originalVariance - else if (originalVariance == Variance.INVARIANT || originalVariance == argumentVariance) - argumentVariance - else if (typeAliasArgument.isStarProjection) - argumentVariance - else { - if (originalVariance != argumentVariance && !typeAliasArgument.isStarProjection) { - reportStrategy.conflictingProjection(typeAliasExpansion.descriptor, typeParameterDescriptor, typeAliasArgument.type) + val substitutionVariance = + when { + underlyingVariance == argumentVariance -> argumentVariance + underlyingVariance == Variance.INVARIANT -> argumentVariance + argumentVariance == Variance.INVARIANT -> underlyingVariance + else -> { + reportStrategy.conflictingProjection(typeAliasExpansion.descriptor, typeParameterDescriptor, argument.type) + argumentVariance } - argumentVariance } - if (typeAliasArgument.isStarProjection) { - return TypeUtils.makeStarProjection(typeParameterDescriptor!!) - } + val parameterVariance = typeParameterDescriptor?.variance ?: Variance.INVARIANT + val resultingVariance = + when { + parameterVariance == substitutionVariance -> Variance.INVARIANT + parameterVariance == Variance.INVARIANT -> substitutionVariance + substitutionVariance == Variance.INVARIANT -> Variance.INVARIANT + else -> { + reportStrategy.conflictingProjection(typeAliasExpansion.descriptor, typeParameterDescriptor, argument.type) + substitutionVariance + } + } - val substitutedType = TypeUtils.makeNullableIfNeeded(typeAliasArgument.type, originalType.isMarkedNullable) + val substitutedType = TypeUtils.makeNullableIfNeeded(argument.type, underlyingType.isMarkedNullable) - return TypeProjectionImpl(substitutedVariance, substitutedType) + return TypeProjectionImpl(resultingVariance, substitutedType) } private fun expandNonArgumentTypeProjection( diff --git a/compiler/testData/diagnostics/tests/generics/innerClasses/implicitArguments/fromSuperClasses.txt b/compiler/testData/diagnostics/tests/generics/innerClasses/implicitArguments/fromSuperClasses.txt index 5b81fecbd57..f999463f66c 100644 --- a/compiler/testData/diagnostics/tests/generics/innerClasses/implicitArguments/fromSuperClasses.txt +++ b/compiler/testData/diagnostics/tests/generics/innerClasses/implicitArguments/fromSuperClasses.txt @@ -14,13 +14,13 @@ public final class A : Outer { public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String - public final fun x(): Outer.Alias /* = kotlin.collections.Map */ + public final fun x(): Outer.Alias /* = kotlin.collections.Map */ } } public final class Derived : Outer { public constructor Derived() - public final fun baz(): Outer.Alias /* = kotlin.collections.Map */ + public final fun baz(): Outer.Alias /* = kotlin.collections.Map */ public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean public final fun foo(): Outer.Inner public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int diff --git a/compiler/testData/diagnostics/tests/generics/innerClasses/implicitArguments/fromSuperClassesTransitive.txt b/compiler/testData/diagnostics/tests/generics/innerClasses/implicitArguments/fromSuperClassesTransitive.txt index 91780e3ab8d..0694ed52405 100644 --- a/compiler/testData/diagnostics/tests/generics/innerClasses/implicitArguments/fromSuperClassesTransitive.txt +++ b/compiler/testData/diagnostics/tests/generics/innerClasses/implicitArguments/fromSuperClassesTransitive.txt @@ -18,7 +18,7 @@ public open class BaseDerived2 : BaseDerived1 { public final class Derived : BaseDerived2 { public constructor Derived() - public final fun baz(): Outer.Alias /* = kotlin.collections.Map */ + public final fun baz(): Outer.Alias /* = kotlin.collections.Map */ public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean public final fun foo(): Outer.Inner public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int diff --git a/compiler/testData/diagnostics/tests/typealias/boundsViolationInTypeAliasExpansion.txt b/compiler/testData/diagnostics/tests/typealias/boundsViolationInTypeAliasExpansion.txt index 6c427b1aba4..37d9bc08247 100644 --- a/compiler/testData/diagnostics/tests/typealias/boundsViolationInTypeAliasExpansion.txt +++ b/compiler/testData/diagnostics/tests/typealias/boundsViolationInTypeAliasExpansion.txt @@ -13,8 +13,8 @@ public fun test10(/*0*/ x: TC> /* = TColl> */): kotlin.Unit public fun test12(/*0*/ x: TC> /* = TColl> */): kotlin.Unit public fun test2(/*0*/ x: NA /* = Num */): kotlin.Unit -public fun test3(/*0*/ x: NL /* = NumColl> */): kotlin.Unit -public fun test4(/*0*/ x: NL /* = NumColl> */): kotlin.Unit +public fun test3(/*0*/ x: NL /* = NumColl> */): kotlin.Unit +public fun test4(/*0*/ x: NL /* = NumColl> */): kotlin.Unit public fun test9(/*0*/ x: TC> /* = TColl> */): kotlin.Unit public final class Num { diff --git a/compiler/testData/diagnostics/tests/typealias/kt14498.txt b/compiler/testData/diagnostics/tests/typealias/kt14498.txt index e8eb39f2dae..de026cd17a1 100644 --- a/compiler/testData/diagnostics/tests/typealias/kt14498.txt +++ b/compiler/testData/diagnostics/tests/typealias/kt14498.txt @@ -32,21 +32,21 @@ public final class Test2 : A2 /* = I1 */ { public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String } -public final class Test3 : AOut /* = Out */ { +public final class Test3 : AOut /* = Out */ { public constructor Test3() public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String } -public final class Test4 : AInvOut /* = InvOut */ { +public final class Test4 : AInvOut /* = InvOut */ { public constructor Test4() public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String } -public final class Test5 : AInvOutTT /* = InvOut */ { +public final class Test5 : AInvOutTT /* = InvOut */ { public constructor Test5() public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int diff --git a/compiler/testData/diagnostics/tests/typealias/kt14498a.txt b/compiler/testData/diagnostics/tests/typealias/kt14498a.txt index d2a1cdd8bd2..f6afb359612 100644 --- a/compiler/testData/diagnostics/tests/typealias/kt14498a.txt +++ b/compiler/testData/diagnostics/tests/typealias/kt14498a.txt @@ -12,19 +12,19 @@ public interface Out { public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String } -public interface Q1 : Out /* = Out> */> { +public interface Q1 : Out /* = Out> */> { public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String } -public interface Q2 : Out /* = Out> */> { +public interface Q2 : Out /* = Out> */> { public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String } -public interface Q3 : Out /* = Inv> */> { +public interface Q3 : Out /* = Inv> */> { public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String diff --git a/compiler/testData/diagnostics/tests/typealias/noApproximationInTypeAliasArgumentSubstitution.txt b/compiler/testData/diagnostics/tests/typealias/noApproximationInTypeAliasArgumentSubstitution.txt index 939591cc9b5..261ee50bd38 100644 --- a/compiler/testData/diagnostics/tests/typealias/noApproximationInTypeAliasArgumentSubstitution.txt +++ b/compiler/testData/diagnostics/tests/typealias/noApproximationInTypeAliasArgumentSubstitution.txt @@ -3,6 +3,6 @@ package public fun bar1(/*0*/ a: Array2D /* = kotlin.Array> */): Array2D /* = kotlin.Array> */ public fun bar2(/*0*/ m: TMap<*> /* = kotlin.collections.Map<*, *> */): [ERROR : Error function type] public fun foo1(/*0*/ a: Array2D /* = kotlin.Array> */): Array2D /* = kotlin.Array> */ -public fun foo2(/*0*/ m: TMap /* = kotlin.collections.Map */): TMap /* = kotlin.collections.Map */ +public fun foo2(/*0*/ m: TMap /* = kotlin.collections.Map */): TMap /* = kotlin.collections.Map */ public typealias Array2D = kotlin.Array> public typealias TMap = kotlin.collections.Map diff --git a/compiler/testData/diagnostics/tests/typealias/substitutionVariance.kt b/compiler/testData/diagnostics/tests/typealias/substitutionVariance.kt index f0542062fb3..3bb8e0dfc19 100644 --- a/compiler/testData/diagnostics/tests/typealias/substitutionVariance.kt +++ b/compiler/testData/diagnostics/tests/typealias/substitutionVariance.kt @@ -18,3 +18,48 @@ typealias Inv3 = Inv typealias Inv4<T> = Inv<*> val inv1: Inv1 = Inv() + +fun inInv_Inv(x: In1) = x +fun inInv_In(x: In1) = x +fun inInv_Out(x: In1) = x +fun inInv_Star(x: In1<*>) = x + +fun inIn_Inv(x: In2) = x +fun inIn_In(x: In2) = x +fun inIn_Out(x: In2) = x +fun inIn_Star(x: In2<*>) = x + +fun inOut_Inv(x: In3) = x +fun inOut_In(x: In3) = x +fun inOut_Out(x: In3) = x +fun inOut_Star(x: In3<*>) = x + +fun outInv_Inv(x: Out1) = x +fun outInv_In(x: Out1) = x +fun outInv_Out(x: Out1) = x +fun outInv_Star(x: Out1<*>) = x + +fun outIn_Inv(x: Out2) = x +fun outIn_In(x: Out2) = x +fun outIn_Out(x: Out2) = x +fun outIn_Star(x: Out2<*>) = x + +fun outOut_Inv(x: Out3) = x +fun outOut_In(x: Out3) = x +fun outOut_Out(x: Out3) = x +fun outOut_Star(x: Out3<*>) = x + +fun invInv_Inv(x: Inv1) = x +fun invInv_In(x: Inv1) = x +fun invInv_Out(x: Inv1) = x +fun invInv_Star(x: Inv1<*>) = x + +fun invIn_Inv(x: Inv2) = x +fun invIn_In(x: Inv2) = x +fun invIn_Out(x: Inv2) = x +fun invIn_Star(x: Inv2<*>) = x + +fun invOut_Inv(x: Inv3) = x +fun invOut_In(x: Inv3) = x +fun invOut_Out(x: Inv3) = x +fun invOut_Star(x: Inv3<*>) = x diff --git a/compiler/testData/diagnostics/tests/typealias/substitutionVariance.txt b/compiler/testData/diagnostics/tests/typealias/substitutionVariance.txt index df29a342767..a764a2aaf82 100644 --- a/compiler/testData/diagnostics/tests/typealias/substitutionVariance.txt +++ b/compiler/testData/diagnostics/tests/typealias/substitutionVariance.txt @@ -1,6 +1,42 @@ package public val inv1: Inv1 /* = Inv */ +public fun inIn_In(/*0*/ x: In2 /* = In */): In2 /* = In */ +public fun inIn_Inv(/*0*/ x: In2 /* = In */): In2 /* = In */ +public fun inIn_Out(/*0*/ x: In2 /* = In */): In2 /* = In */ +public fun inIn_Star(/*0*/ x: In2<*> /* = In<*> */): In2<*> /* = In<*> */ +public fun inInv_In(/*0*/ x: In1 /* = In */): In1 /* = In */ +public fun inInv_Inv(/*0*/ x: In1 /* = In */): In1 /* = In */ +public fun inInv_Out(/*0*/ x: In1 /* = In */): In1 /* = In */ +public fun inInv_Star(/*0*/ x: In1<*> /* = In<*> */): In1<*> /* = In<*> */ +public fun inOut_In(/*0*/ x: In3 /* = In */): In3 /* = In */ +public fun inOut_Inv(/*0*/ x: In3 /* = In */): In3 /* = In */ +public fun inOut_Out(/*0*/ x: In3 /* = In */): In3 /* = In */ +public fun inOut_Star(/*0*/ x: In3<*> /* = In<*> */): In3<*> /* = In<*> */ +public fun invIn_In(/*0*/ x: Inv2 /* = Inv */): Inv2 /* = Inv */ +public fun invIn_Inv(/*0*/ x: Inv2 /* = Inv */): Inv2 /* = Inv */ +public fun invIn_Out(/*0*/ x: Inv2 /* = Inv */): Inv2 /* = Inv */ +public fun invIn_Star(/*0*/ x: Inv2<*> /* = Inv<*> */): Inv2<*> /* = Inv<*> */ +public fun invInv_In(/*0*/ x: Inv1 /* = Inv */): Inv1 /* = Inv */ +public fun invInv_Inv(/*0*/ x: Inv1 /* = Inv */): Inv1 /* = Inv */ +public fun invInv_Out(/*0*/ x: Inv1 /* = Inv */): Inv1 /* = Inv */ +public fun invInv_Star(/*0*/ x: Inv1<*> /* = Inv<*> */): Inv1<*> /* = Inv<*> */ +public fun invOut_In(/*0*/ x: Inv3 /* = Inv */): Inv3 /* = Inv */ +public fun invOut_Inv(/*0*/ x: Inv3 /* = Inv */): Inv3 /* = Inv */ +public fun invOut_Out(/*0*/ x: Inv3 /* = Inv */): Inv3 /* = Inv */ +public fun invOut_Star(/*0*/ x: Inv3<*> /* = Inv<*> */): Inv3<*> /* = Inv<*> */ +public fun outIn_In(/*0*/ x: Out2 /* = Out */): Out2 /* = Out */ +public fun outIn_Inv(/*0*/ x: Out2 /* = Out */): Out2 /* = Out */ +public fun outIn_Out(/*0*/ x: Out2 /* = Out */): Out2 /* = Out */ +public fun outIn_Star(/*0*/ x: Out2<*> /* = Out<*> */): Out2<*> /* = Out<*> */ +public fun outInv_In(/*0*/ x: Out1 /* = Out */): Out1 /* = Out */ +public fun outInv_Inv(/*0*/ x: Out1 /* = Out */): Out1 /* = Out */ +public fun outInv_Out(/*0*/ x: Out1 /* = Out */): Out1 /* = Out */ +public fun outInv_Star(/*0*/ x: Out1<*> /* = Out<*> */): Out1<*> /* = Out<*> */ +public fun outOut_In(/*0*/ x: Out3 /* = Out */): Out3 /* = Out */ +public fun outOut_Inv(/*0*/ x: Out3 /* = Out */): Out3 /* = Out */ +public fun outOut_Out(/*0*/ x: Out3 /* = Out */): Out3 /* = Out */ +public fun outOut_Star(/*0*/ x: Out3<*> /* = Out<*> */): Out3<*> /* = Out<*> */ public final class In { public constructor In()