No variance elision in type alias substitution.

Add test with cyclic inheritance via type alias.
This commit is contained in:
Dmitry Petrov
2016-11-21 14:35:56 +03:00
parent 67fe28b8d8
commit e6fcf20cf2
10 changed files with 167 additions and 37 deletions
@@ -238,7 +238,10 @@ public class DescriptorResolver {
}
}
// If we have an abbreviated type (written with a type alias), it still can contain type projections in top-level arguments.
if (!type.isError() && SpecialTypesKt.getAbbreviatedType(type) != null && !hasProjectionsInWrittenArguments) {
// Only interface inheritance should be checked here.
// Corresponding check for classes is performed for type alias constructor calls in CandidateResolver.
if (TypeUtilsKt.isInterface(type) && TypeUtilsKt.containsTypeProjectionsInTopLevelArguments(type)) {
trace.report(EXPANDED_TYPE_CANNOT_BE_INHERITED.on(typeElement, type));
}
@@ -59,6 +59,8 @@ class TypeAliasExpander(
}
private fun SimpleType.combineAnnotations(annotations: Annotations): SimpleType {
if (isError) return this
val existingAnnotationTypes = this.annotations.getAllAnnotations().mapTo(hashSetOf<KotlinType>()) { it.annotation.type }
for (annotation in annotations) {
@@ -101,7 +103,8 @@ class TypeAliasExpander(
val argumentVariance = argument.projectionKind
val underlyingVariance = underlyingProjection.projectionKind
val argumentType = argument.type as? SimpleType ?: throw AssertionError("Non-simple type in type alias argument: $argument")
val argumentType = argument.type.unwrap() as? SimpleType ?:
throw AssertionError("Non-simple type in type alias argument: $argument")
val substitutionVariance =
when {
@@ -117,7 +120,7 @@ class TypeAliasExpander(
val parameterVariance = typeParameterDescriptor?.variance ?: Variance.INVARIANT
val resultingVariance =
when {
parameterVariance == substitutionVariance -> Variance.INVARIANT
parameterVariance == substitutionVariance -> substitutionVariance
parameterVariance == Variance.INVARIANT -> substitutionVariance
substitutionVariance == Variance.INVARIANT -> Variance.INVARIANT
else -> {
@@ -0,0 +1,7 @@
class A : <!CYCLIC_INHERITANCE_HIERARCHY!>B<!>() {
open class Nested<T>
}
typealias ANested<T> = A.Nested<T>
open class B : <!CYCLIC_INHERITANCE_HIERARCHY!>ANested<Int><!>()
@@ -0,0 +1,17 @@
package
public final class A {
public constructor A()
public open class Nested</*0*/ T> {
public constructor Nested</*0*/ T>()
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 open class B {
public constructor B()
}
public typealias ANested</*0*/ T> = A.Nested<T>
@@ -1,15 +1,15 @@
package
public val inv1: Inv1<kotlin.Int> /* = Inv<kotlin.Int> */
public fun inIn_In(/*0*/ x: In2<in kotlin.Int> /* = In<kotlin.Int> */): In2<in kotlin.Int> /* = In<kotlin.Int> */
public fun inIn_Inv(/*0*/ x: In2<kotlin.Int> /* = In<kotlin.Int> */): In2<kotlin.Int> /* = In<kotlin.Int> */
public fun inIn_In(/*0*/ x: In2<in kotlin.Int> /* = In<in kotlin.Int> */): In2<in kotlin.Int> /* = In<in kotlin.Int> */
public fun inIn_Inv(/*0*/ x: In2<kotlin.Int> /* = In<in kotlin.Int> */): In2<kotlin.Int> /* = In<in kotlin.Int> */
public fun inIn_Out(/*0*/ x: In2<out kotlin.Int> /* = In<out kotlin.Int> */): In2<out kotlin.Int> /* = In<out kotlin.Int> */
public fun inIn_Star(/*0*/ x: In2<*> /* = In<*> */): In2<*> /* = In<*> */
public fun inInv_In(/*0*/ x: In1<in kotlin.Int> /* = In<kotlin.Int> */): In1<in kotlin.Int> /* = In<kotlin.Int> */
public fun inInv_In(/*0*/ x: In1<in kotlin.Int> /* = In<in kotlin.Int> */): In1<in kotlin.Int> /* = In<in kotlin.Int> */
public fun inInv_Inv(/*0*/ x: In1<kotlin.Int> /* = In<kotlin.Int> */): In1<kotlin.Int> /* = In<kotlin.Int> */
public fun inInv_Out(/*0*/ x: In1<out kotlin.Int> /* = In<out kotlin.Int> */): In1<out kotlin.Int> /* = In<out kotlin.Int> */
public fun inInv_Star(/*0*/ x: In1<*> /* = In<*> */): In1<*> /* = In<*> */
public fun inOut_In(/*0*/ x: In3<in kotlin.Int> /* = In<kotlin.Int> */): In3<in kotlin.Int> /* = In<kotlin.Int> */
public fun inOut_In(/*0*/ x: In3<in kotlin.Int> /* = In<in kotlin.Int> */): In3<in kotlin.Int> /* = In<in kotlin.Int> */
public fun inOut_Inv(/*0*/ x: In3<kotlin.Int> /* = In<out kotlin.Int> */): In3<kotlin.Int> /* = In<out kotlin.Int> */
public fun inOut_Out(/*0*/ x: In3<out kotlin.Int> /* = In<out kotlin.Int> */): In3<out kotlin.Int> /* = In<out kotlin.Int> */
public fun inOut_Star(/*0*/ x: In3<*> /* = In<*> */): In3<*> /* = In<*> */
@@ -27,15 +27,15 @@ public fun invOut_Out(/*0*/ x: Inv3<out kotlin.Int> /* = Inv<out kotlin.Int> */)
public fun invOut_Star(/*0*/ x: Inv3<*> /* = Inv<*> */): Inv3<*> /* = Inv<*> */
public fun outIn_In(/*0*/ x: Out2<in kotlin.Int> /* = Out<in kotlin.Int> */): Out2<in kotlin.Int> /* = Out<in kotlin.Int> */
public fun outIn_Inv(/*0*/ x: Out2<kotlin.Int> /* = Out<in kotlin.Int> */): Out2<kotlin.Int> /* = Out<in kotlin.Int> */
public fun outIn_Out(/*0*/ x: Out2<out kotlin.Int> /* = Out<kotlin.Int> */): Out2<out kotlin.Int> /* = Out<kotlin.Int> */
public fun outIn_Out(/*0*/ x: Out2<out kotlin.Int> /* = Out<out kotlin.Int> */): Out2<out kotlin.Int> /* = Out<out kotlin.Int> */
public fun outIn_Star(/*0*/ x: Out2<*> /* = Out<*> */): Out2<*> /* = Out<*> */
public fun outInv_In(/*0*/ x: Out1<in kotlin.Int> /* = Out<in kotlin.Int> */): Out1<in kotlin.Int> /* = Out<in kotlin.Int> */
public fun outInv_Inv(/*0*/ x: Out1<kotlin.Int> /* = Out<kotlin.Int> */): Out1<kotlin.Int> /* = Out<kotlin.Int> */
public fun outInv_Out(/*0*/ x: Out1<out kotlin.Int> /* = Out<kotlin.Int> */): Out1<out kotlin.Int> /* = Out<kotlin.Int> */
public fun outInv_Out(/*0*/ x: Out1<out kotlin.Int> /* = Out<out kotlin.Int> */): Out1<out kotlin.Int> /* = Out<out kotlin.Int> */
public fun outInv_Star(/*0*/ x: Out1<*> /* = Out<*> */): Out1<*> /* = Out<*> */
public fun outOut_In(/*0*/ x: Out3<in kotlin.Int> /* = Out<in kotlin.Int> */): Out3<in kotlin.Int> /* = Out<in kotlin.Int> */
public fun outOut_Inv(/*0*/ x: Out3<kotlin.Int> /* = Out<kotlin.Int> */): Out3<kotlin.Int> /* = Out<kotlin.Int> */
public fun outOut_Out(/*0*/ x: Out3<out kotlin.Int> /* = Out<kotlin.Int> */): Out3<out kotlin.Int> /* = Out<kotlin.Int> */
public fun outOut_Inv(/*0*/ x: Out3<kotlin.Int> /* = Out<out kotlin.Int> */): Out3<kotlin.Int> /* = Out<out kotlin.Int> */
public fun outOut_Out(/*0*/ x: Out3<out kotlin.Int> /* = Out<out kotlin.Int> */): Out3<out kotlin.Int> /* = Out<out kotlin.Int> */
public fun outOut_Star(/*0*/ x: Out3<*> /* = Out<*> */): Out3<*> /* = Out<*> */
public final class In</*0*/ in T> {
@@ -1,12 +1,32 @@
interface I<T>
interface Inv<T>
interface Out<out T>
interface In<in T>
typealias IStar = I<*>
typealias IIn = I<in Int>
typealias IOut = I<out Int>
typealias IT<T> = I<T>
typealias InvStar = Inv<*>
typealias InvIn = Inv<in Int>
typealias InvOut = Inv<out Int>
typealias InvT<T> = Inv<T>
class Test1 : <!EXPANDED_TYPE_CANNOT_BE_INHERITED!>IStar<!>
class Test2 : <!EXPANDED_TYPE_CANNOT_BE_INHERITED!>IIn<!>
class Test3 : <!EXPANDED_TYPE_CANNOT_BE_INHERITED!>IOut<!>
class Test4 : IT<<!PROJECTION_IN_IMMEDIATE_ARGUMENT_TO_SUPERTYPE!>*<!>>
class Test5 : IT<IT<*>>
typealias OutStar = Out<*>
typealias OutOut = Out<<!REDUNDANT_PROJECTION!>out<!> Int>
typealias OutT<T> = Out<T>
typealias InStar = In<*>
typealias InIn = In<<!REDUNDANT_PROJECTION!>in<!> Int>
typealias InT<T> = In<T>
class Test1 : <!EXPANDED_TYPE_CANNOT_BE_INHERITED!>InvStar<!>
class Test2 : <!EXPANDED_TYPE_CANNOT_BE_INHERITED!>InvIn<!>
class Test3 : <!EXPANDED_TYPE_CANNOT_BE_INHERITED!>InvOut<!>
class Test4 : InvT<<!PROJECTION_IN_IMMEDIATE_ARGUMENT_TO_SUPERTYPE!>*<!>>
class Test5 : InvT<InvT<*>>
class Test6 : <!EXPANDED_TYPE_CANNOT_BE_INHERITED!>OutStar<!>
class Test7 : <!EXPANDED_TYPE_CANNOT_BE_INHERITED!>OutOut<!>
class Test8 : OutT<Int>
class Test9 : OutT<<!PROJECTION_IN_IMMEDIATE_ARGUMENT_TO_SUPERTYPE!>out<!> Int>
class Test10 : <!EXPANDED_TYPE_CANNOT_BE_INHERITED!>InStar<!>
class Test11 : <!EXPANDED_TYPE_CANNOT_BE_INHERITED!>InIn<!>
class Test12 : InT<Int>
class Test13 : InT<<!PROJECTION_IN_IMMEDIATE_ARGUMENT_TO_SUPERTYPE!>in<!> Int>
@@ -1,46 +1,120 @@
package
public interface I</*0*/ T> {
public interface In</*0*/ in T> {
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 Test1 : IStar /* = I<*> */ {
public interface Inv</*0*/ T> {
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 Out</*0*/ out T> {
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 Test1 : InvStar /* = Inv<*> */ {
public constructor Test1()
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 Test2 : IIn /* = I<in kotlin.Int> */ {
public final class Test10 : InStar /* = In<*> */ {
public constructor Test10()
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 Test11 : InIn /* = In<in kotlin.Int> */ {
public constructor Test11()
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 Test12 : InT<kotlin.Int> /* = In<kotlin.Int> */ {
public constructor Test12()
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 Test13 : InT<in kotlin.Int> /* = In<in kotlin.Int> */ {
public constructor Test13()
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 Test2 : InvIn /* = Inv<in kotlin.Int> */ {
public constructor Test2()
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 Test3 : IOut /* = I<out kotlin.Int> */ {
public final class Test3 : InvOut /* = Inv<out kotlin.Int> */ {
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 : IT<*> /* = I<*> */ {
public final class Test4 : InvT<*> /* = Inv<*> */ {
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 : IT<IT<*> /* = I<*> */> /* = I<I<*>> */ {
public final class Test5 : InvT<InvT<*> /* = Inv<*> */> /* = Inv<Inv<*>> */ {
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
public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String
}
public typealias IIn = I<in kotlin.Int>
public typealias IOut = I<out kotlin.Int>
public typealias IStar = I<*>
public typealias IT</*0*/ T> = I<T>
public final class Test6 : OutStar /* = Out<*> */ {
public constructor Test6()
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 Test7 : OutOut /* = Out<out kotlin.Int> */ {
public constructor Test7()
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 Test8 : OutT<kotlin.Int> /* = Out<kotlin.Int> */ {
public constructor Test8()
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 Test9 : OutT<out kotlin.Int> /* = Out<out kotlin.Int> */ {
public constructor Test9()
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 typealias InIn = In<in kotlin.Int>
public typealias InStar = In<*>
public typealias InT</*0*/ T> = In<T>
public typealias InvIn = Inv<in kotlin.Int>
public typealias InvOut = Inv<out kotlin.Int>
public typealias InvStar = Inv<*>
public typealias InvT</*0*/ T> = Inv<T>
public typealias OutOut = Out<out kotlin.Int>
public typealias OutStar = Out<*>
public typealias OutT</*0*/ T> = Out<T>
@@ -1,11 +1,11 @@
package test
public fun test1(/*0*/ x: test.L<kotlin.String> /* = kotlin.collections.List<out kotlin.String> */): kotlin.Unit
public fun test2(/*0*/ x: test.LL<kotlin.String> /* = kotlin.collections.List<out kotlin.String> */): kotlin.Unit
public fun test3(/*0*/ x: test.LLL<kotlin.String> /* = kotlin.collections.List<out kotlin.String> */): kotlin.Unit
public fun test4(/*0*/ x: test.L<test.L<kotlin.String> /* = kotlin.collections.List<out kotlin.String> */> /* = kotlin.collections.List<out test.L<kotlin.String> /* = kotlin.collections.List<out kotlin.String> */> */): kotlin.Unit
public fun test5(/*0*/ x: test.LL<test.LL<kotlin.String> /* = kotlin.collections.List<out kotlin.String> */> /* = kotlin.collections.List<out test.LL<kotlin.String> /* = kotlin.collections.List<out kotlin.String> */> */): kotlin.Unit
public fun test6(/*0*/ x: test.LLL<test.LLL<kotlin.String> /* = kotlin.collections.List<out kotlin.String> */> /* = kotlin.collections.List<out test.LLL<kotlin.String> /* = kotlin.collections.List<out kotlin.String> */> */): kotlin.Unit
public fun test1(/*0*/ x: test.L<kotlin.String> /* = kotlin.collections.List<kotlin.String> */): kotlin.Unit
public fun test2(/*0*/ x: test.LL<kotlin.String> /* = kotlin.collections.List<kotlin.String> */): kotlin.Unit
public fun test3(/*0*/ x: test.LLL<kotlin.String> /* = kotlin.collections.List<kotlin.String> */): kotlin.Unit
public fun test4(/*0*/ x: test.L<test.L<kotlin.String> /* = kotlin.collections.List<kotlin.String> */> /* = kotlin.collections.List<kotlin.collections.List<kotlin.String>> */): kotlin.Unit
public fun test5(/*0*/ x: test.LL<test.LL<kotlin.String> /* = kotlin.collections.List<kotlin.String> */> /* = kotlin.collections.List<kotlin.collections.List<kotlin.String>> */): kotlin.Unit
public fun test6(/*0*/ x: test.LLL<test.LLL<kotlin.String> /* = kotlin.collections.List<kotlin.String> */> /* = kotlin.collections.List<kotlin.collections.List<kotlin.String>> */): kotlin.Unit
public typealias L</*0*/ T> = kotlin.collections.List<T>
public typealias LL</*0*/ T> = test.L<T>
public typealias LLL</*0*/ T> = test.LL<T>
@@ -20866,6 +20866,12 @@ public class DiagnosticsTestGenerated extends AbstractDiagnosticsTest {
doTest(fileName);
}
@TestMetadata("cyclicInheritanceViaTypeAlias.kt")
public void testCyclicInheritanceViaTypeAlias() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/diagnostics/tests/typealias/cyclicInheritanceViaTypeAlias.kt");
doTest(fileName);
}
@TestMetadata("exposedExpandedType.kt")
public void testExposedExpandedType() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/diagnostics/tests/typealias/exposedExpandedType.kt");
@@ -1,2 +1,2 @@
<!-- typeVarianceConflictInTypeAliasExpansion1 -->
Type parameter S is declared as 'out' but occurs in 'invariant' position in abbreviated type AInvOutTT<S> /* = InvOut<S, out S> */
Type parameter S is declared as 'out' but occurs in 'invariant' position in abbreviated type AInvOutTT<S> /* = InvOut<S, S> */