Inner type aliases.

Type alias is considered "inner" if it captures outer class type parameters (implicitly or explicitly).
This commit is contained in:
Dmitry Petrov
2016-11-09 13:14:10 +03:00
parent 63fed20249
commit 718e8ebf9e
16 changed files with 244 additions and 27 deletions
@@ -710,18 +710,25 @@ public class DescriptorResolver {
else {
typeAliasDescriptor.initialize(
typeParameterDescriptors,
storageManager.createLazyValue(new Function0<SimpleType>() {
@Override
public SimpleType invoke() {
return typeResolver.resolveAbbreviatedType(scopeWithTypeParameters, typeReference, trace);
}
}),
storageManager.createLazyValue(new Function0<SimpleType>() {
@Override
public SimpleType invoke() {
return typeResolver.resolveExpandedTypeForTypeAlias(typeAliasDescriptor);
}
}));
storageManager.createRecursionTolerantLazyValue(
new Function0<SimpleType>() {
@Override
public SimpleType invoke() {
return typeResolver.resolveAbbreviatedType(scopeWithTypeParameters, typeReference, trace);
}
},
ErrorUtils.createErrorType("Recursive type alias expansion for " + typeAliasDescriptor.getName().asString())
),
storageManager.createRecursionTolerantLazyValue(
new Function0<SimpleType>() {
@Override
public SimpleType invoke() {
return typeResolver.resolveExpandedTypeForTypeAlias(typeAliasDescriptor);
}
},
ErrorUtils.createErrorType("Recursive type alias expansion for " + typeAliasDescriptor.getName().asString())
)
);
}
trace.record(TYPE_ALIAS, typeAlias, typeAliasDescriptor);
@@ -48,7 +48,7 @@ class TypeAliasExpansion private constructor(
typeAliasDescriptor: TypeAliasDescriptor,
arguments: List<TypeProjection>
): TypeAliasExpansion {
val typeParameters = typeAliasDescriptor.typeConstructor.parameters.map { it.original as TypeParameterDescriptor }
val typeParameters = typeAliasDescriptor.typeConstructor.parameters.map { it.original }
val mappedArguments = typeParameters.zip(arguments).toMap()
return TypeAliasExpansion(parent, typeAliasDescriptor, arguments, mappedArguments)
}
@@ -22,6 +22,7 @@ import org.jetbrains.kotlin.descriptors.impl.AbstractTypeAliasDescriptor
import org.jetbrains.kotlin.name.Name
import org.jetbrains.kotlin.resolve.BindingTrace
import org.jetbrains.kotlin.storage.NotNullLazyValue
import org.jetbrains.kotlin.storage.NullableLazyValue
import org.jetbrains.kotlin.storage.StorageManager
import org.jetbrains.kotlin.types.SimpleType
import org.jetbrains.kotlin.types.TypeSubstitutor
@@ -42,9 +43,11 @@ class LazyTypeAliasDescriptor(
private lateinit var underlyingTypeImpl: NotNullLazyValue<SimpleType>
private lateinit var expandedTypeImpl: NotNullLazyValue<SimpleType>
private lateinit var defaultTypeImpl: NotNullLazyValue<SimpleType>
private lateinit var classDescriptorImpl: NullableLazyValue<ClassDescriptor>
override val underlyingType: SimpleType get() = underlyingTypeImpl()
override val expandedType: SimpleType get() = expandedTypeImpl()
override val classDescriptor: ClassDescriptor? get() = classDescriptorImpl()
override fun getDefaultType(): SimpleType = defaultTypeImpl()
fun initialize(
@@ -56,10 +59,21 @@ class LazyTypeAliasDescriptor(
this.underlyingTypeImpl = lazyUnderlyingType
this.expandedTypeImpl = lazyExpandedType
this.defaultTypeImpl = storageManager.createLazyValue { computeDefaultType() }
this.classDescriptorImpl = storageManager.createRecursionTolerantNullableLazyValue({ computeClassDescriptor() }, null)
}
private fun computeClassDescriptor(): ClassDescriptor? {
if (underlyingType.isError) return null
val underlyingTypeDescriptor = underlyingType.constructor.declarationDescriptor
return when (underlyingTypeDescriptor) {
is ClassDescriptor -> underlyingTypeDescriptor
is TypeAliasDescriptor -> underlyingTypeDescriptor.classDescriptor
else -> null
}
}
private val lazyTypeConstructorParameters =
storageManager.createLazyValue { this.computeConstructorTypeParameters() }
storageManager.createRecursionTolerantLazyValue({ this.computeConstructorTypeParameters() }, emptyList())
fun initialize(
declaredTypeParameters: List<TypeParameterDescriptor>,
@@ -21,10 +21,10 @@ public final class Outer</*0*/ TO> {
public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String
public typealias LTI /*captured type parameters: /*0*/ TI, /*1*/ TN*/ = kotlin.collections.List<TI>
public typealias LTN /*captured type parameters: /*0*/ TI, /*1*/ TN*/ = kotlin.collections.List<TN>
public typealias LTO /*captured type parameters: /*0*/ TI, /*1*/ TN*/ = kotlin.collections.List<[ERROR : TO]>
public typealias LTO = kotlin.collections.List<[ERROR : TO]>
}
public typealias LTN /*captured type parameters: /*0*/ TN*/ = kotlin.collections.List<TN>
public typealias LTO /*captured type parameters: /*0*/ TN*/ = kotlin.collections.List<[ERROR : TO]>
public typealias LTO = kotlin.collections.List<[ERROR : TO]>
}
public typealias LTO /*captured type parameters: /*0*/ TO*/ = kotlin.collections.List<TO>
}
@@ -0,0 +1,32 @@
class Outer<T> {
class Nested
class GenericNested<TT>
inner class Inner
inner class GenericInner<TT>
typealias NestedAlias = Nested
typealias GenericNestedAlias<TT> = GenericNested<TT>
typealias InnerAlias = Inner
typealias GenericInnerAlias<TT> = GenericInner<TT>
fun test1(x: NestedAlias) = x
fun test2(x: GenericNestedAlias<Int>) = x
fun <T> test3(x: GenericNestedAlias<T>) = x
fun test4(x: InnerAlias) = x
fun test5(x: GenericInnerAlias<Int>) = x
fun <T> test6(x: GenericInnerAlias<T>) = x
}
fun test1(x: Outer<!TYPE_ARGUMENTS_FOR_OUTER_CLASS_WHEN_NESTED_REFERENCED!><Int><!>.NestedAlias) = <!DEBUG_INFO_ELEMENT_WITH_ERROR_TYPE!>x<!>
fun <T> test2(x: Outer<!TYPE_ARGUMENTS_FOR_OUTER_CLASS_WHEN_NESTED_REFERENCED!><T><!>.NestedAlias) = <!DEBUG_INFO_ELEMENT_WITH_ERROR_TYPE!>x<!>
fun test3(x: Outer.NestedAlias) = x
fun test4(x: Outer<!TYPE_ARGUMENTS_FOR_OUTER_CLASS_WHEN_NESTED_REFERENCED!><Int><!>.GenericNestedAlias<Int>) = <!DEBUG_INFO_ELEMENT_WITH_ERROR_TYPE!>x<!>
fun <T> test5(x: Outer<!TYPE_ARGUMENTS_FOR_OUTER_CLASS_WHEN_NESTED_REFERENCED!><T><!>.GenericNestedAlias<Int>) = <!DEBUG_INFO_ELEMENT_WITH_ERROR_TYPE!>x<!>
fun <T> test6(x: Outer<!TYPE_ARGUMENTS_FOR_OUTER_CLASS_WHEN_NESTED_REFERENCED!><Int><!>.GenericNestedAlias<T>) = <!DEBUG_INFO_ELEMENT_WITH_ERROR_TYPE!>x<!>
fun test7(x: Outer.GenericNestedAlias<Int>) = x
fun <T> test8(x: Outer.GenericNestedAlias<T>) = x
fun test9(x: <!WRONG_NUMBER_OF_TYPE_ARGUMENTS!>Outer<!>.InnerAlias) = <!DEBUG_INFO_ELEMENT_WITH_ERROR_TYPE!>x<!>
fun test10(x: Outer<Int>.InnerAlias) = x
fun <T> test11(x: Outer<T>.InnerAlias) = x
fun test12(x: <!WRONG_NUMBER_OF_TYPE_ARGUMENTS!>Outer<!>.GenericInnerAlias<Int>) = <!DEBUG_INFO_ELEMENT_WITH_ERROR_TYPE!>x<!>
fun test13(x: Outer<Int>.GenericInnerAlias<Int>) = x
fun <T> test14(x: Outer<T>.GenericInnerAlias<Int>) = x
@@ -0,0 +1,61 @@
package
public fun test1(/*0*/ x: [ERROR : NestedAlias]<kotlin.Int>): [ERROR : NestedAlias]<kotlin.Int>
public fun test10(/*0*/ x: Outer<kotlin.Int>.InnerAlias /* = Outer<kotlin.Int>.Inner */): Outer<kotlin.Int>.InnerAlias /* = Outer<kotlin.Int>.Inner */
public fun </*0*/ T> test11(/*0*/ x: Outer<T>.InnerAlias /* = Outer<T>.Inner */): Outer<T>.InnerAlias /* = Outer<T>.Inner */
public fun test12(/*0*/ x: [ERROR : GenericInnerAlias]<kotlin.Int>): [ERROR : GenericInnerAlias]<kotlin.Int>
public fun test13(/*0*/ x: Outer<kotlin.Int>.GenericInnerAlias<kotlin.Int> /* = Outer<kotlin.Int>.GenericInner<kotlin.Int> */): Outer<kotlin.Int>.GenericInnerAlias<kotlin.Int> /* = Outer<kotlin.Int>.GenericInner<kotlin.Int> */
public fun </*0*/ T> test14(/*0*/ x: Outer<T>.GenericInnerAlias<kotlin.Int> /* = Outer<T>.GenericInner<kotlin.Int> */): Outer<T>.GenericInnerAlias<kotlin.Int> /* = Outer<T>.GenericInner<kotlin.Int> */
public fun </*0*/ T> test2(/*0*/ x: [ERROR : NestedAlias]<T>): [ERROR : NestedAlias]<T>
public fun test3(/*0*/ x: Outer.NestedAlias /* = Outer.Nested */): Outer.NestedAlias /* = Outer.Nested */
public fun test4(/*0*/ x: [ERROR : GenericNestedAlias]<kotlin.Int, kotlin.Int>): [ERROR : GenericNestedAlias]<kotlin.Int, kotlin.Int>
public fun </*0*/ T> test5(/*0*/ x: [ERROR : GenericNestedAlias]<T, kotlin.Int>): [ERROR : GenericNestedAlias]<T, kotlin.Int>
public fun </*0*/ T> test6(/*0*/ x: [ERROR : GenericNestedAlias]<kotlin.Int, T>): [ERROR : GenericNestedAlias]<kotlin.Int, T>
public fun test7(/*0*/ x: Outer.GenericNestedAlias<kotlin.Int> /* = Outer.GenericNested<kotlin.Int> */): Outer.GenericNestedAlias<kotlin.Int> /* = Outer.GenericNested<kotlin.Int> */
public fun </*0*/ T> test8(/*0*/ x: Outer.GenericNestedAlias<T> /* = Outer.GenericNested<T> */): Outer.GenericNestedAlias<T> /* = Outer.GenericNested<T> */
public fun test9(/*0*/ x: [ERROR : InnerAlias]): [ERROR : InnerAlias]
public final class Outer</*0*/ T> {
public constructor Outer</*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 final fun test1(/*0*/ x: Outer.NestedAlias /* = Outer.Nested */): Outer.NestedAlias /* = Outer.Nested */
public final fun test2(/*0*/ x: Outer.GenericNestedAlias<kotlin.Int> /* = Outer.GenericNested<kotlin.Int> */): Outer.GenericNestedAlias<kotlin.Int> /* = Outer.GenericNested<kotlin.Int> */
public final fun </*0*/ T> test3(/*0*/ x: Outer.GenericNestedAlias<T> /* = Outer.GenericNested<T> */): Outer.GenericNestedAlias<T> /* = Outer.GenericNested<T> */
public final fun test4(/*0*/ x: Outer<T>.InnerAlias /* = Outer<T>.Inner */): Outer<T>.InnerAlias /* = Outer<T>.Inner */
public final fun test5(/*0*/ x: Outer<T>.GenericInnerAlias<kotlin.Int> /* = Outer<T>.GenericInner<kotlin.Int> */): Outer<T>.GenericInnerAlias<kotlin.Int> /* = Outer<T>.GenericInner<kotlin.Int> */
public final fun </*0*/ T> test6(/*0*/ x: Outer<T>.GenericInnerAlias<T> /* = Outer<T>.GenericInner<T> */): Outer<T>.GenericInnerAlias<T> /* = Outer<T>.GenericInner<T> */
public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String
public final inner class GenericInner</*0*/ TT> /*captured type parameters: /*1*/ T*/ {
public constructor GenericInner</*0*/ TT>()
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 GenericNested</*0*/ TT> {
public constructor GenericNested</*0*/ TT>()
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 inner class Inner /*captured type parameters: /*0*/ T*/ {
public constructor Inner()
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 Nested {
public constructor Nested()
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 GenericInnerAlias</*0*/ TT> /*captured type parameters: /*1*/ T*/ = Outer<T>.GenericInner<TT>
public typealias GenericNestedAlias</*0*/ TT> = Outer.GenericNested<TT>
public typealias InnerAlias /*captured type parameters: /*0*/ T*/ = Outer<T>.Inner
public typealias NestedAlias = Outer.Nested
}
@@ -0,0 +1,22 @@
class C<T> {
inner class D
typealias DA = D
typealias SDA = C<Int>.D
typealias TSDA = C<T>.D
typealias TC = C<T>
typealias SSDA = C<*>.D
typealias SSC = C<*>
}
fun test1(x: C<Int>.DA) = x
fun test2(x: C.SDA) = x
fun test3(x: C<Int>.TSDA) = x
fun test4(x: C<Int>.TC) = x
fun test5(x: C<*>.DA) = x
fun test6(x: C<*>.TSDA) = x
fun test7(x: C<*>.TC) = x
fun test8(x: C.SSDA) = x
fun test9(x: C.SSC) = x
@@ -0,0 +1,31 @@
package
public fun test1(/*0*/ x: C<kotlin.Int>.DA /* = C<kotlin.Int>.D */): C<kotlin.Int>.DA /* = C<kotlin.Int>.D */
public fun test2(/*0*/ x: C.SDA /* = C<kotlin.Int>.D */): C.SDA /* = C<kotlin.Int>.D */
public fun test3(/*0*/ x: C<kotlin.Int>.TSDA /* = C<kotlin.Int>.D */): C<kotlin.Int>.TSDA /* = C<kotlin.Int>.D */
public fun test4(/*0*/ x: C<kotlin.Int>.TC /* = C<kotlin.Int> */): C<kotlin.Int>.TC /* = C<kotlin.Int> */
public fun test5(/*0*/ x: C<*>.DA /* = C<*>.D */): C<*>.DA /* = C<*>.D */
public fun test6(/*0*/ x: C<*>.TSDA /* = C<*>.D */): C<*>.TSDA /* = C<*>.D */
public fun test7(/*0*/ x: C<*>.TC /* = C<*> */): C<*>.TC /* = C<*> */
public fun test8(/*0*/ x: C.SSDA /* = C<*>.D */): C.SSDA /* = C<*>.D */
public fun test9(/*0*/ x: C.SSC /* = C<*> */): C.SSC /* = C<*> */
public final class C</*0*/ T> {
public constructor C</*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 final inner class D /*captured type parameters: /*0*/ T*/ {
public constructor D()
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 DA /*captured type parameters: /*0*/ T*/ = C<T>.D
public typealias SDA = C<kotlin.Int>.D
public typealias SSC = C<*>
public typealias SSDA = C<*>.D
public typealias TC /*captured type parameters: /*0*/ T*/ = C<T>
public typealias TSDA /*captured type parameters: /*0*/ T*/ = C<T>.D
}
@@ -0,0 +1,8 @@
class OuterClass<T1> {
class NestedClass<T2>
typealias NestedType<T> = NestedClass<T>
}
typealias ON1<T1, T2> = OuterClass<!TYPE_ARGUMENTS_FOR_OUTER_CLASS_WHEN_NESTED_REFERENCED!><T1><!>.NestedClass<T2>
typealias ON2<T1, T2> = OuterClass<!TYPE_ARGUMENTS_FOR_OUTER_CLASS_WHEN_NESTED_REFERENCED!><T1><!>.NestedType<T2>
typealias ON3<T2> = OuterClass.NestedType<T2>
@@ -0,0 +1,19 @@
package
public final class OuterClass</*0*/ T1> {
public constructor OuterClass</*0*/ T1>()
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 NestedClass</*0*/ T2> {
public constructor NestedClass</*0*/ T2>()
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 NestedType</*0*/ T> = OuterClass.NestedClass<T>
}
public typealias ON1</*0*/ T1, /*1*/ T2> = [ERROR : NestedClass]<T1, T2>
public typealias ON2</*0*/ T1, /*1*/ T2> = [ERROR : NestedType]<T1, T2>
public typealias ON3</*0*/ T2> = OuterClass.NestedType<T2>
@@ -32,7 +32,7 @@ public final class TestSuperForGenericBase</*0*/ T> : GB<T> /* = GenericBase<T>
public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int
public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String
public typealias MyBase /*captured type parameters: /*0*/ T*/ = GB<T>
public typealias MyBaseInt /*captured type parameters: /*0*/ T*/ = GB<kotlin.Int>
public typealias MyBaseInt = GB<kotlin.Int>
}
public final class Unrelated {
@@ -20926,6 +20926,18 @@ public class DiagnosticsTestGenerated extends AbstractDiagnosticsTest {
doTest(fileName);
}
@TestMetadata("innerTypeAliasAsType.kt")
public void testInnerTypeAliasAsType() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/diagnostics/tests/typealias/innerTypeAliasAsType.kt");
doTest(fileName);
}
@TestMetadata("innerTypeAliasAsType2.kt")
public void testInnerTypeAliasAsType2() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/diagnostics/tests/typealias/innerTypeAliasAsType2.kt");
doTest(fileName);
}
@TestMetadata("isAsWithTypeAlias.kt")
public void testIsAsWithTypeAlias() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/diagnostics/tests/typealias/isAsWithTypeAlias.kt");
@@ -20950,6 +20962,12 @@ public class DiagnosticsTestGenerated extends AbstractDiagnosticsTest {
doTest(fileName);
}
@TestMetadata("kt14518.kt")
public void testKt14518() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/diagnostics/tests/typealias/kt14518.kt");
doTest(fileName);
}
@TestMetadata("kt14641.kt")
public void testKt14641() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/diagnostics/tests/typealias/kt14641.kt");
@@ -47,14 +47,20 @@ abstract class AbstractTypeAliasDescriptor(
visitor.visitTypeAliasDescriptor(this, data)
override fun isInner(): Boolean =
containingDeclaration !is PackageFragmentDescriptor
// NB: it's ok to use underlyingType here, since referenced inner type aliases also capture type parameters.
// Using expandedType looks "proper", but in fact will cause a recursion in expandedType resolution,
// which will silently produce wrong result.
TypeUtils.contains(underlyingType) {
!it.isError && run {
val constructorDescriptor = it.constructor.declarationDescriptor
constructorDescriptor is TypeParameterDescriptor &&
constructorDescriptor.containingDeclaration != this@AbstractTypeAliasDescriptor
}
}
override fun getDeclaredTypeParameters(): List<TypeParameterDescriptor> =
declaredTypeParametersImpl
override val classDescriptor: ClassDescriptor?
get() = if (expandedType.isError) null else expandedType.constructor.declarationDescriptor as? ClassDescriptor
override fun getModality() = Modality.FINAL
override fun getVisibility() = visibilityImpl
@@ -133,6 +133,8 @@ class NotFoundClasses(private val storageManager: StorageManager, private val mo
get() = builtIns.nullableAnyType
override fun getDefaultType(): SimpleType =
builtIns.nullableAnyType
override val classDescriptor: ClassDescriptor?
get() = expandedType.constructor.declarationDescriptor as? ClassDescriptor
override fun substitute(substitutor: TypeSubstitutor) = this
@@ -169,6 +169,9 @@ class DeserializedTypeAliasDescriptor(
defaultTypeImpl = computeDefaultType()
}
override val classDescriptor: ClassDescriptor?
get() = if (expandedType.isError) null else expandedType.constructor.declarationDescriptor as? ClassDescriptor
override fun getDefaultType(): SimpleType =
defaultTypeImpl
@@ -7366,12 +7366,6 @@ public class JsCodegenBoxTestGenerated extends AbstractJsCodegenBoxTest {
doTest(fileName);
}
@TestMetadata("kt13557.kt")
public void testKt13557() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/delegatedProperty/local/kt13557.kt");
doTest(fileName);
}
@TestMetadata("localVal.kt")
public void testLocalVal() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/delegatedProperty/local/localVal.kt");