diff --git a/compiler/testData/ir/irText/classes/delegatingConstructorCallToTypeAliasConstructor.txt b/compiler/testData/ir/irText/classes/delegatingConstructorCallToTypeAliasConstructor.txt index f1f680a6732..7ea372e4e66 100644 --- a/compiler/testData/ir/irText/classes/delegatingConstructorCallToTypeAliasConstructor.txt +++ b/compiler/testData/ir/irText/classes/delegatingConstructorCallToTypeAliasConstructor.txt @@ -18,14 +18,12 @@ FILE /delegatingConstructorCallToTypeAliasConstructor.kt CLASS CLASS C1 CONSTRUCTOR public constructor C1() BLOCK_BODY - DELEGATING_CONSTRUCTOR_CALL 'constructor Cell(T)' - value: TYPE_OP type=T origin=IMPLICIT_CAST typeOperand=T - CONST String type=kotlin.String value='O' + DELEGATING_CONSTRUCTOR_CALL 'constructor Cell(String)' + value: CONST String type=kotlin.String value='O' INSTANCE_INITIALIZER_CALL classDescriptor='C1' CLASS CLASS C2 CONSTRUCTOR public constructor C2() BLOCK_BODY - DELEGATING_CONSTRUCTOR_CALL 'constructor Cell(T)' - value: TYPE_OP type=T origin=IMPLICIT_CAST typeOperand=T - CONST String type=kotlin.String value='K' + DELEGATING_CONSTRUCTOR_CALL 'constructor Cell(String)' + value: CONST String type=kotlin.String value='K' INSTANCE_INITIALIZER_CALL classDescriptor='C2' diff --git a/compiler/testData/ir/irText/regressions/typeAliasCtorForGenericClass.kt b/compiler/testData/ir/irText/regressions/typeAliasCtorForGenericClass.kt new file mode 100644 index 00000000000..75b3f283029 --- /dev/null +++ b/compiler/testData/ir/irText/regressions/typeAliasCtorForGenericClass.kt @@ -0,0 +1,10 @@ +class A(val q: Q) + +typealias B = A + +typealias B2 = A> + +fun bar() { + val b = B(2) + val b2 = B2(b) +} \ No newline at end of file diff --git a/compiler/testData/ir/irText/regressions/typeAliasCtorForGenericClass.txt b/compiler/testData/ir/irText/regressions/typeAliasCtorForGenericClass.txt new file mode 100644 index 00000000000..9c89b02cf6e --- /dev/null +++ b/compiler/testData/ir/irText/regressions/typeAliasCtorForGenericClass.txt @@ -0,0 +1,25 @@ +FILE /typeAliasCtorForGenericClass.kt + CLASS CLASS A + CONSTRUCTOR public constructor A(q: Q) + BLOCK_BODY + DELEGATING_CONSTRUCTOR_CALL 'constructor Any()' + INSTANCE_INITIALIZER_CALL classDescriptor='A' + PROPERTY public final val q: Q + FIELD PROPERTY_BACKING_FIELD public final val q: Q + EXPRESSION_BODY + GET_VAR 'value-parameter q: Q' type=Q origin=INITIALIZE_PROPERTY_FROM_PARAMETER + FUN DEFAULT_PROPERTY_ACCESSOR public final fun (): Q + BLOCK_BODY + RETURN type=kotlin.Nothing from='(): Q' + GET_FIELD 'q: Q' type=Q origin=null + receiver: GET_VAR '' type=A origin=null + TYPEALIAS typealias B = A type=A + TYPEALIAS typealias B2 = A> type=A> + FUN public fun bar(): kotlin.Unit + BLOCK_BODY + VAR val b: B /* = A */ + CALL 'constructor A(Int)' type=A origin=null + q: CONST Int type=kotlin.Int value='2' + VAR val b2: B2 /* = A> */ + CALL 'constructor A(A)' type=A> origin=null + q: GET_VAR 'b: B /* = A */' type=B /* = A */ origin=null diff --git a/compiler/tests/org/jetbrains/kotlin/ir/IrTextTestCaseGenerated.java b/compiler/tests/org/jetbrains/kotlin/ir/IrTextTestCaseGenerated.java index df532121ee2..c4c039c2590 100644 --- a/compiler/tests/org/jetbrains/kotlin/ir/IrTextTestCaseGenerated.java +++ b/compiler/tests/org/jetbrains/kotlin/ir/IrTextTestCaseGenerated.java @@ -901,6 +901,12 @@ public class IrTextTestCaseGenerated extends AbstractIrTextTestCase { String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/ir/irText/regressions/integerCoercionToT.kt"); doTest(fileName); } + + @TestMetadata("typeAliasCtorForGenericClass.kt") + public void testTypeAliasCtorForGenericClass() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/ir/irText/regressions/typeAliasCtorForGenericClass.kt"); + doTest(fileName); + } } @TestMetadata("compiler/testData/ir/irText/singletons") diff --git a/core/descriptors/src/org/jetbrains/kotlin/descriptors/impl/TypeAliasConstructorDescriptor.kt b/core/descriptors/src/org/jetbrains/kotlin/descriptors/impl/TypeAliasConstructorDescriptor.kt index f5fb3d395a0..3e8af2f299e 100644 --- a/core/descriptors/src/org/jetbrains/kotlin/descriptors/impl/TypeAliasConstructorDescriptor.kt +++ b/core/descriptors/src/org/jetbrains/kotlin/descriptors/impl/TypeAliasConstructorDescriptor.kt @@ -34,7 +34,7 @@ interface TypeAliasConstructorDescriptor : ConstructorDescriptor { override fun getOriginal(): TypeAliasConstructorDescriptor - override fun substitute(substitutor: TypeSubstitutor): TypeAliasConstructorDescriptor + override fun substitute(substitutor: TypeSubstitutor): TypeAliasConstructorDescriptor? val withDispatchReceiver: TypeAliasConstructorDescriptor? @@ -50,7 +50,7 @@ interface TypeAliasConstructorDescriptor : ConstructorDescriptor { class TypeAliasConstructorDescriptorImpl private constructor( val storageManager: StorageManager, override val typeAliasDescriptor: TypeAliasDescriptor, - override val underlyingConstructorDescriptor: ClassConstructorDescriptor, + underlyingConstructorDescriptor: ClassConstructorDescriptor, original: TypeAliasConstructorDescriptor?, annotations: Annotations, kind: Kind, @@ -58,32 +58,38 @@ class TypeAliasConstructorDescriptorImpl private constructor( ) : TypeAliasConstructorDescriptor, FunctionDescriptorImpl(typeAliasDescriptor, original, annotations, Name.special(""), kind, source) { - // When resolution is ran for common calls, type aliases constructors are resolved as extensions // (i.e. after members, and with extension receiver) // But when resolving super-calls (with known set of candidates) constructors of inner classes are expected to have // a dispatch receiver override val withDispatchReceiver: TypeAliasConstructorDescriptor? by storageManager.createNullableLazyValue { - val typeAliasConstructor = TypeAliasConstructorDescriptorImpl(storageManager, - typeAliasDescriptor, - underlyingConstructorDescriptor, - this, - underlyingConstructorDescriptor.annotations, - underlyingConstructorDescriptor.kind, - typeAliasDescriptor.source) - val substitutorForUnderlyingClass = typeAliasDescriptor.getTypeSubstitutorForUnderlyingClass() ?: return@createNullableLazyValue null + TypeAliasConstructorDescriptorImpl( + storageManager, + typeAliasDescriptor, + underlyingConstructorDescriptor, + this, + underlyingConstructorDescriptor.annotations, + underlyingConstructorDescriptor.kind, + typeAliasDescriptor.source + ).also { typeAliasConstructor -> + val substitutorForUnderlyingClass = typeAliasDescriptor.getTypeSubstitutorForUnderlyingClass() ?: + return@createNullableLazyValue null - typeAliasConstructor.initialize(null, - underlyingConstructorDescriptor.dispatchReceiverParameter?.substitute(substitutorForUnderlyingClass), - typeAliasDescriptor.declaredTypeParameters, - valueParameters, - returnType, - Modality.FINAL, - typeAliasDescriptor.visibility) - - return@createNullableLazyValue typeAliasConstructor + typeAliasConstructor.initialize( + null, + underlyingConstructorDescriptor.dispatchReceiverParameter?.substitute(substitutorForUnderlyingClass), + typeAliasDescriptor.declaredTypeParameters, + valueParameters, + returnType, + Modality.FINAL, + typeAliasDescriptor.visibility + ) + } } + override var underlyingConstructorDescriptor: ClassConstructorDescriptor = underlyingConstructorDescriptor + private set + override fun isPrimary(): Boolean = underlyingConstructorDescriptor.isPrimary @@ -99,8 +105,23 @@ class TypeAliasConstructorDescriptorImpl private constructor( override fun getOriginal(): TypeAliasConstructorDescriptor = super.getOriginal() as TypeAliasConstructorDescriptor - override fun substitute(substitutor: TypeSubstitutor): TypeAliasConstructorDescriptor = - super.substitute(substitutor) as TypeAliasConstructorDescriptor + override fun substitute(substitutor: TypeSubstitutor): TypeAliasConstructorDescriptor? { + // class C(val x: T) + // typealias A = C> + // + // val test = A(listOf(42)) + // + // Here return type for substituted type alias constructor is 'C>', + // which yields us a substitution [T -> List] that should be applied to + // the unsubstituted underlying constructor with signature ' (T) -> C' + // producing substituted underlying constructor with signature '(List) -> C>'. + val substitutedTypeAliasConstructor = super.substitute(substitutor) as TypeAliasConstructorDescriptorImpl + val underlyingConstructorSubstitutor = TypeSubstitutor.create(substitutedTypeAliasConstructor.returnType) + val substitutedUnderlyingConstructor = underlyingConstructorDescriptor.original.substitute(underlyingConstructorSubstitutor) + ?: return null + substitutedTypeAliasConstructor.underlyingConstructorDescriptor = substitutedUnderlyingConstructor + return substitutedTypeAliasConstructor + } override fun copy( newOwner: DeclarationDescriptor,