Substitute underlying constructor when substituting type alias constructor
KT-17426 Constructor call of typealiased class gets suspicious type arguemnts
This commit is contained in:
+4
-6
@@ -18,14 +18,12 @@ FILE /delegatingConstructorCallToTypeAliasConstructor.kt
|
|||||||
CLASS CLASS C1
|
CLASS CLASS C1
|
||||||
CONSTRUCTOR public constructor C1()
|
CONSTRUCTOR public constructor C1()
|
||||||
BLOCK_BODY
|
BLOCK_BODY
|
||||||
DELEGATING_CONSTRUCTOR_CALL 'constructor Cell(T)'
|
DELEGATING_CONSTRUCTOR_CALL 'constructor Cell(String)'
|
||||||
value: TYPE_OP type=T origin=IMPLICIT_CAST typeOperand=T
|
value: CONST String type=kotlin.String value='O'
|
||||||
CONST String type=kotlin.String value='O'
|
|
||||||
INSTANCE_INITIALIZER_CALL classDescriptor='C1'
|
INSTANCE_INITIALIZER_CALL classDescriptor='C1'
|
||||||
CLASS CLASS C2
|
CLASS CLASS C2
|
||||||
CONSTRUCTOR public constructor C2()
|
CONSTRUCTOR public constructor C2()
|
||||||
BLOCK_BODY
|
BLOCK_BODY
|
||||||
DELEGATING_CONSTRUCTOR_CALL 'constructor Cell(T)'
|
DELEGATING_CONSTRUCTOR_CALL 'constructor Cell(String)'
|
||||||
value: TYPE_OP type=T origin=IMPLICIT_CAST typeOperand=T
|
value: CONST String type=kotlin.String value='K'
|
||||||
CONST String type=kotlin.String value='K'
|
|
||||||
INSTANCE_INITIALIZER_CALL classDescriptor='C2'
|
INSTANCE_INITIALIZER_CALL classDescriptor='C2'
|
||||||
|
|||||||
@@ -0,0 +1,10 @@
|
|||||||
|
class A<Q>(val q: Q)
|
||||||
|
|
||||||
|
typealias B<X> = A<X>
|
||||||
|
|
||||||
|
typealias B2<T> = A<A<T>>
|
||||||
|
|
||||||
|
fun bar() {
|
||||||
|
val b = B(2)
|
||||||
|
val b2 = B2(b)
|
||||||
|
}
|
||||||
@@ -0,0 +1,25 @@
|
|||||||
|
FILE /typeAliasCtorForGenericClass.kt
|
||||||
|
CLASS CLASS A
|
||||||
|
CONSTRUCTOR public constructor A<Q>(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 <get-q>(): Q
|
||||||
|
BLOCK_BODY
|
||||||
|
RETURN type=kotlin.Nothing from='<get-q>(): Q'
|
||||||
|
GET_FIELD 'q: Q' type=Q origin=null
|
||||||
|
receiver: GET_VAR '<receiver: A>' type=A<Q> origin=null
|
||||||
|
TYPEALIAS typealias B = A<X> type=A<X>
|
||||||
|
TYPEALIAS typealias B2 = A<A<T>> type=A<A<T>>
|
||||||
|
FUN public fun bar(): kotlin.Unit
|
||||||
|
BLOCK_BODY
|
||||||
|
VAR val b: B<kotlin.Int> /* = A<kotlin.Int> */
|
||||||
|
CALL 'constructor A(Int)' type=A<kotlin.Int> origin=null
|
||||||
|
q: CONST Int type=kotlin.Int value='2'
|
||||||
|
VAR val b2: B2<kotlin.Int> /* = A<A<kotlin.Int>> */
|
||||||
|
CALL 'constructor A(A<Int>)' type=A<A<kotlin.Int>> origin=null
|
||||||
|
q: GET_VAR 'b: B<Int> /* = A<Int> */' type=B<kotlin.Int> /* = A<kotlin.Int> */ origin=null
|
||||||
@@ -901,6 +901,12 @@ public class IrTextTestCaseGenerated extends AbstractIrTextTestCase {
|
|||||||
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/ir/irText/regressions/integerCoercionToT.kt");
|
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/ir/irText/regressions/integerCoercionToT.kt");
|
||||||
doTest(fileName);
|
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")
|
@TestMetadata("compiler/testData/ir/irText/singletons")
|
||||||
|
|||||||
+43
-22
@@ -34,7 +34,7 @@ interface TypeAliasConstructorDescriptor : ConstructorDescriptor {
|
|||||||
|
|
||||||
override fun getOriginal(): TypeAliasConstructorDescriptor
|
override fun getOriginal(): TypeAliasConstructorDescriptor
|
||||||
|
|
||||||
override fun substitute(substitutor: TypeSubstitutor): TypeAliasConstructorDescriptor
|
override fun substitute(substitutor: TypeSubstitutor): TypeAliasConstructorDescriptor?
|
||||||
|
|
||||||
val withDispatchReceiver: TypeAliasConstructorDescriptor?
|
val withDispatchReceiver: TypeAliasConstructorDescriptor?
|
||||||
|
|
||||||
@@ -50,7 +50,7 @@ interface TypeAliasConstructorDescriptor : ConstructorDescriptor {
|
|||||||
class TypeAliasConstructorDescriptorImpl private constructor(
|
class TypeAliasConstructorDescriptorImpl private constructor(
|
||||||
val storageManager: StorageManager,
|
val storageManager: StorageManager,
|
||||||
override val typeAliasDescriptor: TypeAliasDescriptor,
|
override val typeAliasDescriptor: TypeAliasDescriptor,
|
||||||
override val underlyingConstructorDescriptor: ClassConstructorDescriptor,
|
underlyingConstructorDescriptor: ClassConstructorDescriptor,
|
||||||
original: TypeAliasConstructorDescriptor?,
|
original: TypeAliasConstructorDescriptor?,
|
||||||
annotations: Annotations,
|
annotations: Annotations,
|
||||||
kind: Kind,
|
kind: Kind,
|
||||||
@@ -58,32 +58,38 @@ class TypeAliasConstructorDescriptorImpl private constructor(
|
|||||||
) : TypeAliasConstructorDescriptor,
|
) : TypeAliasConstructorDescriptor,
|
||||||
FunctionDescriptorImpl(typeAliasDescriptor, original, annotations, Name.special("<init>"), kind, source)
|
FunctionDescriptorImpl(typeAliasDescriptor, original, annotations, Name.special("<init>"), kind, source)
|
||||||
{
|
{
|
||||||
|
|
||||||
// When resolution is ran for common calls, type aliases constructors are resolved as extensions
|
// When resolution is ran for common calls, type aliases constructors are resolved as extensions
|
||||||
// (i.e. after members, and with extension receiver)
|
// (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
|
// But when resolving super-calls (with known set of candidates) constructors of inner classes are expected to have
|
||||||
// a dispatch receiver
|
// a dispatch receiver
|
||||||
override val withDispatchReceiver: TypeAliasConstructorDescriptor? by storageManager.createNullableLazyValue {
|
override val withDispatchReceiver: TypeAliasConstructorDescriptor? by storageManager.createNullableLazyValue {
|
||||||
val typeAliasConstructor = TypeAliasConstructorDescriptorImpl(storageManager,
|
TypeAliasConstructorDescriptorImpl(
|
||||||
typeAliasDescriptor,
|
storageManager,
|
||||||
underlyingConstructorDescriptor,
|
typeAliasDescriptor,
|
||||||
this,
|
underlyingConstructorDescriptor,
|
||||||
underlyingConstructorDescriptor.annotations,
|
this,
|
||||||
underlyingConstructorDescriptor.kind,
|
underlyingConstructorDescriptor.annotations,
|
||||||
typeAliasDescriptor.source)
|
underlyingConstructorDescriptor.kind,
|
||||||
val substitutorForUnderlyingClass = typeAliasDescriptor.getTypeSubstitutorForUnderlyingClass() ?: return@createNullableLazyValue null
|
typeAliasDescriptor.source
|
||||||
|
).also { typeAliasConstructor ->
|
||||||
|
val substitutorForUnderlyingClass = typeAliasDescriptor.getTypeSubstitutorForUnderlyingClass() ?:
|
||||||
|
return@createNullableLazyValue null
|
||||||
|
|
||||||
typeAliasConstructor.initialize(null,
|
typeAliasConstructor.initialize(
|
||||||
underlyingConstructorDescriptor.dispatchReceiverParameter?.substitute(substitutorForUnderlyingClass),
|
null,
|
||||||
typeAliasDescriptor.declaredTypeParameters,
|
underlyingConstructorDescriptor.dispatchReceiverParameter?.substitute(substitutorForUnderlyingClass),
|
||||||
valueParameters,
|
typeAliasDescriptor.declaredTypeParameters,
|
||||||
returnType,
|
valueParameters,
|
||||||
Modality.FINAL,
|
returnType,
|
||||||
typeAliasDescriptor.visibility)
|
Modality.FINAL,
|
||||||
|
typeAliasDescriptor.visibility
|
||||||
return@createNullableLazyValue typeAliasConstructor
|
)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
override var underlyingConstructorDescriptor: ClassConstructorDescriptor = underlyingConstructorDescriptor
|
||||||
|
private set
|
||||||
|
|
||||||
override fun isPrimary(): Boolean =
|
override fun isPrimary(): Boolean =
|
||||||
underlyingConstructorDescriptor.isPrimary
|
underlyingConstructorDescriptor.isPrimary
|
||||||
|
|
||||||
@@ -99,8 +105,23 @@ class TypeAliasConstructorDescriptorImpl private constructor(
|
|||||||
override fun getOriginal(): TypeAliasConstructorDescriptor =
|
override fun getOriginal(): TypeAliasConstructorDescriptor =
|
||||||
super.getOriginal() as TypeAliasConstructorDescriptor
|
super.getOriginal() as TypeAliasConstructorDescriptor
|
||||||
|
|
||||||
override fun substitute(substitutor: TypeSubstitutor): TypeAliasConstructorDescriptor =
|
override fun substitute(substitutor: TypeSubstitutor): TypeAliasConstructorDescriptor? {
|
||||||
super.substitute(substitutor) as TypeAliasConstructorDescriptor
|
// class C<T>(val x: T)
|
||||||
|
// typealias A<Q> = C<List<Q>>
|
||||||
|
//
|
||||||
|
// val test = A(listOf(42))
|
||||||
|
//
|
||||||
|
// Here return type for substituted type alias constructor is 'C<List<Int>>',
|
||||||
|
// which yields us a substitution [T -> List<Int>] that should be applied to
|
||||||
|
// the unsubstituted underlying constructor with signature '<T> (T) -> C<T>'
|
||||||
|
// producing substituted underlying constructor with signature '(List<Int>) -> C<List<Int>>'.
|
||||||
|
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(
|
override fun copy(
|
||||||
newOwner: DeclarationDescriptor,
|
newOwner: DeclarationDescriptor,
|
||||||
|
|||||||
Reference in New Issue
Block a user