diff --git a/.idea/dictionaries/dmitriy_dolovov.xml b/.idea/dictionaries/dmitriy_dolovov.xml
index 526e23fd489..83f71f606da 100644
--- a/.idea/dictionaries/dmitriy_dolovov.xml
+++ b/.idea/dictionaries/dmitriy_dolovov.xml
@@ -5,6 +5,7 @@
commonize
commonized
commonizer
+ commonizers
konan
diff --git a/konan/commonizer/src/org/jetbrains/kotlin/descriptors/commonizer/builder/functionDescriptors.kt b/konan/commonizer/src/org/jetbrains/kotlin/descriptors/commonizer/builder/functionDescriptors.kt
index 0fcf3856835..18b4b8efbf8 100644
--- a/konan/commonizer/src/org/jetbrains/kotlin/descriptors/commonizer/builder/functionDescriptors.kt
+++ b/konan/commonizer/src/org/jetbrains/kotlin/descriptors/commonizer/builder/functionDescriptors.kt
@@ -59,18 +59,10 @@ private fun Function.buildDescriptor(
functionDescriptor.isExpect = isExpect
functionDescriptor.isActual = isActual
- val extensionReceiverDescriptor = DescriptorFactory.createExtensionReceiverParameterForCallable(
- functionDescriptor,
- extensionReceiver?.type,
- extensionReceiver?.annotations ?: Annotations.EMPTY
- )
-
- val dispatchReceiverDescriptor = DescriptorUtils.getDispatchReceiverParameterIfNeeded(containingDeclaration)
-
functionDescriptor.initialize(
- extensionReceiverDescriptor,
- dispatchReceiverDescriptor,
- emptyList(), // TODO: support type parameters
+ extensionReceiver?.buildExtensionReceiver(functionDescriptor),
+ buildDispatchReceiver(functionDescriptor),
+ typeParameters.buildDescriptors(functionDescriptor),
valueParameters.buildValueParameters(functionDescriptor),
returnType,
modality,
diff --git a/konan/commonizer/src/org/jetbrains/kotlin/descriptors/commonizer/builder/propertyDescriptors.kt b/konan/commonizer/src/org/jetbrains/kotlin/descriptors/commonizer/builder/propertyDescriptors.kt
index abb09930559..ec7fe2bdc5f 100644
--- a/konan/commonizer/src/org/jetbrains/kotlin/descriptors/commonizer/builder/propertyDescriptors.kt
+++ b/konan/commonizer/src/org/jetbrains/kotlin/descriptors/commonizer/builder/propertyDescriptors.kt
@@ -8,7 +8,6 @@ package org.jetbrains.kotlin.descriptors.commonizer.builder
import org.jetbrains.kotlin.descriptors.DeclarationDescriptor
import org.jetbrains.kotlin.descriptors.PropertyDescriptor
import org.jetbrains.kotlin.descriptors.SourceElement
-import org.jetbrains.kotlin.descriptors.annotations.Annotations
import org.jetbrains.kotlin.descriptors.commonizer.CommonizedGroup
import org.jetbrains.kotlin.descriptors.commonizer.mergedtree.ir.Property
import org.jetbrains.kotlin.descriptors.commonizer.mergedtree.ir.PropertyNode
@@ -16,7 +15,6 @@ import org.jetbrains.kotlin.descriptors.commonizer.mergedtree.ir.indexOfCommon
import org.jetbrains.kotlin.descriptors.impl.FieldDescriptorImpl
import org.jetbrains.kotlin.descriptors.impl.PropertyDescriptorImpl
import org.jetbrains.kotlin.resolve.DescriptorFactory
-import org.jetbrains.kotlin.resolve.DescriptorUtils
import org.jetbrains.kotlin.storage.StorageManager
internal fun PropertyNode.buildDescriptors(
@@ -60,19 +58,11 @@ private fun Property.buildDescriptor(
isDelegate
)
- val extensionReceiverDescriptor = DescriptorFactory.createExtensionReceiverParameterForCallable(
- propertyDescriptor,
- extensionReceiver?.type,
- extensionReceiver?.annotations ?: Annotations.EMPTY
- )
-
- val dispatchReceiverDescriptor = DescriptorUtils.getDispatchReceiverParameterIfNeeded(containingDeclaration)
-
propertyDescriptor.setType(
returnType,
- emptyList(), // TODO: support type parameters
- dispatchReceiverDescriptor,
- extensionReceiverDescriptor
+ typeParameters.buildDescriptors(propertyDescriptor),
+ buildDispatchReceiver(propertyDescriptor),
+ extensionReceiver?.buildExtensionReceiver(propertyDescriptor)
)
val getterDescriptor = getter?.let { getter ->
diff --git a/konan/commonizer/src/org/jetbrains/kotlin/descriptors/commonizer/builder/utils.kt b/konan/commonizer/src/org/jetbrains/kotlin/descriptors/commonizer/builder/utils.kt
new file mode 100644
index 00000000000..02ea97986ff
--- /dev/null
+++ b/konan/commonizer/src/org/jetbrains/kotlin/descriptors/commonizer/builder/utils.kt
@@ -0,0 +1,48 @@
+/*
+ * Copyright 2010-2019 JetBrains s.r.o. and Kotlin Programming Language contributors.
+ * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
+ */
+
+package org.jetbrains.kotlin.descriptors.commonizer.builder
+
+import org.jetbrains.kotlin.descriptors.CallableDescriptor
+import org.jetbrains.kotlin.descriptors.DeclarationDescriptor
+import org.jetbrains.kotlin.descriptors.SourceElement
+import org.jetbrains.kotlin.descriptors.TypeParameterDescriptor
+import org.jetbrains.kotlin.descriptors.commonizer.mergedtree.ir.ExtensionReceiver
+import org.jetbrains.kotlin.descriptors.commonizer.mergedtree.ir.TypeParameter
+import org.jetbrains.kotlin.descriptors.impl.TypeParameterDescriptorImpl
+import org.jetbrains.kotlin.resolve.DescriptorFactory
+import org.jetbrains.kotlin.resolve.DescriptorUtils
+
+internal fun List.buildDescriptors(
+ containingDeclaration: DeclarationDescriptor
+): List {
+ return mapIndexed { index, param ->
+ val descriptor = TypeParameterDescriptorImpl.createForFurtherModification(
+ containingDeclaration,
+ param.annotations,
+ param.isReified,
+ param.variance,
+ param.name,
+ index,
+ SourceElement.NO_SOURCE
+ )
+
+ param.upperBounds.forEach(descriptor::addUpperBound)
+ descriptor.setInitialized()
+
+ descriptor
+ }
+}
+
+internal fun ExtensionReceiver.buildExtensionReceiver(
+ containingDeclaration: CallableDescriptor
+) = DescriptorFactory.createExtensionReceiverParameterForCallable(
+ containingDeclaration,
+ type,
+ annotations
+)
+
+internal fun buildDispatchReceiver(callableDescriptor: CallableDescriptor) =
+ DescriptorUtils.getDispatchReceiverParameterIfNeeded(callableDescriptor.containingDeclaration)
diff --git a/konan/commonizer/src/org/jetbrains/kotlin/descriptors/commonizer/core/CallableMemberCommonizer.kt b/konan/commonizer/src/org/jetbrains/kotlin/descriptors/commonizer/core/AbstractCallableMemberCommonizer.kt
similarity index 86%
rename from konan/commonizer/src/org/jetbrains/kotlin/descriptors/commonizer/core/CallableMemberCommonizer.kt
rename to konan/commonizer/src/org/jetbrains/kotlin/descriptors/commonizer/core/AbstractCallableMemberCommonizer.kt
index 939c4bce6ec..93cafb22721 100644
--- a/konan/commonizer/src/org/jetbrains/kotlin/descriptors/commonizer/core/CallableMemberCommonizer.kt
+++ b/konan/commonizer/src/org/jetbrains/kotlin/descriptors/commonizer/core/AbstractCallableMemberCommonizer.kt
@@ -9,7 +9,7 @@ import org.jetbrains.kotlin.descriptors.CallableMemberDescriptor
import org.jetbrains.kotlin.descriptors.commonizer.mergedtree.ir.CallableMember
import org.jetbrains.kotlin.name.Name
-abstract class CallableMemberCommonizer : Commonizer {
+abstract class AbstractCallableMemberCommonizer : Commonizer {
protected enum class State {
EMPTY,
ERROR,
@@ -22,6 +22,7 @@ abstract class CallableMemberCommonizer(
+ private val subject: String,
+ private val singleElementCommonizerFactory: () -> Commonizer
+) : Commonizer, List> {
+ private var commonizers: List>? = null
+ private var error = false
+
+ final override val result: List
+ get() = commonizers?.takeIf { !error }?.map { it.result } ?: error("Can't commonize list of $subject")
+
+ final override fun commonizeWith(next: List): Boolean {
+ if (error)
+ return false
+
+ val commonizers = commonizers
+ ?: mutableListOf>().apply {
+ repeat(next.size) {
+ this += singleElementCommonizerFactory()
+ }
+ }.also {
+ this.commonizers = it
+ }
+
+ if (commonizers.size != next.size)
+ error = true
+ else
+ for (index in 0 until next.size) {
+ val commonizer = commonizers[index]
+ val nextElement = next[index]
+
+ if (!commonizer.commonizeWith(nextElement)) {
+ error = true
+ break
+ }
+ }
+
+ return !error
+ }
+}
diff --git a/konan/commonizer/src/org/jetbrains/kotlin/descriptors/commonizer/core/NamedListWrappedCommonizer.kt b/konan/commonizer/src/org/jetbrains/kotlin/descriptors/commonizer/core/AbstractNamedListCommonizer.kt
similarity index 62%
rename from konan/commonizer/src/org/jetbrains/kotlin/descriptors/commonizer/core/NamedListWrappedCommonizer.kt
rename to konan/commonizer/src/org/jetbrains/kotlin/descriptors/commonizer/core/AbstractNamedListCommonizer.kt
index af7a99c3d0d..4dd0b5dd6f4 100644
--- a/konan/commonizer/src/org/jetbrains/kotlin/descriptors/commonizer/core/NamedListWrappedCommonizer.kt
+++ b/konan/commonizer/src/org/jetbrains/kotlin/descriptors/commonizer/core/AbstractNamedListCommonizer.kt
@@ -8,28 +8,28 @@ package org.jetbrains.kotlin.descriptors.commonizer.core
import org.jetbrains.kotlin.descriptors.Named
import org.jetbrains.kotlin.name.Name
-abstract class NamedListWrappedCommonizer(
+abstract class AbstractNamedListCommonizer(
private val subject: String,
- private val wrappedCommonizerFactory: () -> Commonizer
+ private val singleElementCommonizerFactory: () -> Commonizer
) : Commonizer, List> {
- private var wrapped: List>>? = null
+ private var commonizers: List>>? = null
private var error = false
final override val result: List
- get() = wrapped?.takeIf { !error }?.map { it.second.result } ?: error("Can't commonize list of $subject")
+ get() = commonizers?.takeIf { !error }?.map { it.second.result } ?: error("Can't commonize list of $subject")
final override fun commonizeWith(next: List): Boolean {
if (error)
return false
- val wrapped = wrapped
- ?: next.map { it.name to wrappedCommonizerFactory() }.also { this.wrapped = it }
+ val commonizers = commonizers
+ ?: next.map { it.name to singleElementCommonizerFactory() }.also { this.commonizers = it }
- if (wrapped.size != next.size)
+ if (commonizers.size != next.size)
error = true
else
for (index in 0 until next.size) {
- val (name, commonizer) = wrapped[index]
+ val (name, commonizer) = commonizers[index]
val nextElement = next[index]
if (name != nextElement.name || !commonizer.commonizeWith(nextElement)) {
diff --git a/konan/commonizer/src/org/jetbrains/kotlin/descriptors/commonizer/core/NullableWrappedCommonizer.kt b/konan/commonizer/src/org/jetbrains/kotlin/descriptors/commonizer/core/AbstractNullableCommonizer.kt
similarity index 95%
rename from konan/commonizer/src/org/jetbrains/kotlin/descriptors/commonizer/core/NullableWrappedCommonizer.kt
rename to konan/commonizer/src/org/jetbrains/kotlin/descriptors/commonizer/core/AbstractNullableCommonizer.kt
index e0008e4a6cf..acd251b581b 100644
--- a/konan/commonizer/src/org/jetbrains/kotlin/descriptors/commonizer/core/NullableWrappedCommonizer.kt
+++ b/konan/commonizer/src/org/jetbrains/kotlin/descriptors/commonizer/core/AbstractNullableCommonizer.kt
@@ -5,7 +5,7 @@
package org.jetbrains.kotlin.descriptors.commonizer.core
-abstract class NullableWrappedCommonizer(
+abstract class AbstractNullableCommonizer(
private val subject: String,
private val wrappedCommonizerFactory: () -> Commonizer,
private val extractor: (T) -> WT,
diff --git a/konan/commonizer/src/org/jetbrains/kotlin/descriptors/commonizer/core/FunctionCommonizer.kt b/konan/commonizer/src/org/jetbrains/kotlin/descriptors/commonizer/core/FunctionCommonizer.kt
index cd540a94731..88789bd5ec0 100644
--- a/konan/commonizer/src/org/jetbrains/kotlin/descriptors/commonizer/core/FunctionCommonizer.kt
+++ b/konan/commonizer/src/org/jetbrains/kotlin/descriptors/commonizer/core/FunctionCommonizer.kt
@@ -10,7 +10,7 @@ import org.jetbrains.kotlin.descriptors.commonizer.mergedtree.ir.CommonFunction
import org.jetbrains.kotlin.descriptors.commonizer.mergedtree.ir.ExtensionReceiver.Companion.toReceiverNoAnnotations
import org.jetbrains.kotlin.descriptors.commonizer.mergedtree.ir.Function
-class FunctionCommonizer : CallableMemberCommonizer() {
+class FunctionCommonizer : AbstractCallableMemberCommonizer() {
private val modifiers = FunctionModifiersCommonizer.default()
private val valueParameters = ValueParameterListCommonizer.default()
@@ -24,16 +24,13 @@ class FunctionCommonizer : CallableMemberCommonizer() {
+class PropertyCommonizer : AbstractCallableMemberCommonizer() {
private val setter = PropertySetterCommonizer.default()
private var isExternal = true
@@ -24,7 +24,8 @@ class PropertyCommonizer : CallableMemberCommonizer(
+ AbstractNullableCommonizer(
subject = "Property",
wrappedCommonizerFactory = { VisibilityCommonizer.equalizing() },
extractor = { it.visibility },
diff --git a/konan/commonizer/src/org/jetbrains/kotlin/descriptors/commonizer/core/TypeCommonizer.kt b/konan/commonizer/src/org/jetbrains/kotlin/descriptors/commonizer/core/TypeCommonizer.kt
index f0f702ec88a..ff34421672d 100644
--- a/konan/commonizer/src/org/jetbrains/kotlin/descriptors/commonizer/core/TypeCommonizer.kt
+++ b/konan/commonizer/src/org/jetbrains/kotlin/descriptors/commonizer/core/TypeCommonizer.kt
@@ -82,19 +82,26 @@ private fun areAbbreviatedTypesEqual(a: SimpleType, aExpanded: SimpleType, b: Si
val aDescriptor = requireNotNull(a.constructor.declarationDescriptor, a::nonNullDescriptorExpectedErrorMessage)
val bDescriptor = requireNotNull(b.constructor.declarationDescriptor, b::nonNullDescriptorExpectedErrorMessage)
- val aFqName = aDescriptor.fqNameSafe
- val bFqName = bDescriptor.fqNameSafe
+ val isUnderStandardKotlinPackages = if (
+ aDescriptor is ClassifierDescriptorWithTypeParameters
+ && bDescriptor is ClassifierDescriptorWithTypeParameters
+ ) {
+ // N.B. only for descriptors that represent classes or type aliases, but not type parameters:
- if (aFqName.isUnderStandardKotlinPackages || bFqName.isUnderStandardKotlinPackages) {
- // make sure that FQ names of abbreviated types (e.g. representing type aliases) are equal
- return aFqName == bFqName
+ val aFqName = aDescriptor.fqNameSafe
+ val bFqName = bDescriptor.fqNameSafe
+
+ aFqName.isUnderStandardKotlinPackages
+ // make sure that FQ names of abbreviated types (e.g. representing type aliases) are equal
+ && aFqName == bFqName
// if classes are from the standard Kotlin packages, compare them only by type constructors
// effectively, this includes 1) comparison of FQ names and 2) number of type constructor parameters
// see org.jetbrains.kotlin.types.AbstractClassTypeConstructor.equals() for details
&& aExpanded.constructor == bExpandedType.constructor
- }
+ } else false
- val descriptorsCanBeCommonized = when (aDescriptor) {
+ val descriptorsCanBeCommonized = isUnderStandardKotlinPackages || when (aDescriptor) {
+ is TypeParameterDescriptor -> (bDescriptor is TypeParameterDescriptor) && canBeCommonized(aDescriptor, bDescriptor)
is TypeAliasDescriptor -> (bDescriptor is TypeAliasDescriptor) && canBeCommonized(aDescriptor, bDescriptor)
is ClassDescriptor -> (bDescriptor is ClassDescriptor) && canBeCommonized(aDescriptor, bDescriptor)
else -> false
@@ -103,8 +110,8 @@ private fun areAbbreviatedTypesEqual(a: SimpleType, aExpanded: SimpleType, b: Si
if (!descriptorsCanBeCommonized)
return false
- if (a.arguments === b.arguments)
- return true
+ if (a.arguments.size != b.arguments.size)
+ return false
for (i in 0 until a.arguments.size) {
val aArg = a.arguments[i]
@@ -162,6 +169,12 @@ private fun canBeCommonized(a: TypeAliasDescriptor, b: TypeAliasDescriptor): Boo
return areTypesEqual(aUnderlyingType, bUnderlyingType)
}
+private fun canBeCommonized(a: TypeParameterDescriptor, b: TypeParameterDescriptor): Boolean {
+ // N.B. real type parameter commonization is performed in TypeParameterCommonizer,
+ // here it is enough to check FQ names
+ return areFqNamesEqual(a, b)
+}
+
private fun areFqNamesEqual(d1: T, d2: T): Boolean {
val p1 = d1.parentsWithSelf.iterator()
val p2 = d2.parentsWithSelf.iterator()
diff --git a/konan/commonizer/src/org/jetbrains/kotlin/descriptors/commonizer/core/TypeParameterCommonizer.kt b/konan/commonizer/src/org/jetbrains/kotlin/descriptors/commonizer/core/TypeParameterCommonizer.kt
new file mode 100644
index 00000000000..b41125cee26
--- /dev/null
+++ b/konan/commonizer/src/org/jetbrains/kotlin/descriptors/commonizer/core/TypeParameterCommonizer.kt
@@ -0,0 +1,84 @@
+/*
+ * Copyright 2010-2019 JetBrains s.r.o. and Kotlin Programming Language contributors.
+ * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
+ */
+
+package org.jetbrains.kotlin.descriptors.commonizer.core
+
+import org.jetbrains.kotlin.descriptors.TypeParameterDescriptor
+import org.jetbrains.kotlin.descriptors.commonizer.mergedtree.ir.CommonTypeParameter
+import org.jetbrains.kotlin.descriptors.commonizer.mergedtree.ir.TypeParameter
+import org.jetbrains.kotlin.name.Name
+import org.jetbrains.kotlin.types.KotlinType
+import org.jetbrains.kotlin.types.UnwrappedType
+import org.jetbrains.kotlin.types.Variance
+
+interface TypeParameterCommonizer : Commonizer {
+ companion object {
+ fun default(): TypeParameterCommonizer = DefaultTypeParameterCommonizer()
+ }
+}
+
+private class DefaultTypeParameterCommonizer : TypeParameterCommonizer {
+ private enum class State {
+ EMPTY,
+ ERROR,
+ IN_PROGRESS
+ }
+
+ private var state = State.EMPTY
+ private lateinit var name: Name
+ private var isReified = false
+ private lateinit var variance: Variance
+ private val upperBounds = TypeParameterUpperBoundsCommonizer()
+
+ override val result: TypeParameter
+ get() = when (state) {
+ State.EMPTY, State.ERROR -> error("Can't commonize type parameter")
+ State.IN_PROGRESS -> CommonTypeParameter(
+ name = name,
+ isReified = isReified,
+ variance = variance,
+ upperBounds = upperBounds.result
+ )
+ }
+
+ override fun commonizeWith(next: TypeParameterDescriptor): Boolean {
+ state = when (state) {
+ State.ERROR -> State.ERROR
+ State.EMPTY -> {
+ name = next.name
+ isReified = next.isReified
+ variance = next.variance
+
+ if (!upperBounds.commonizeWith(next.upperBounds)) State.ERROR else State.IN_PROGRESS
+ }
+ State.IN_PROGRESS -> {
+ if (isReified != next.isReified
+ || variance != next.variance
+ || !upperBounds.commonizeWith(next.upperBounds)
+ ) State.ERROR else State.IN_PROGRESS
+ }
+ }
+
+ return state != State.ERROR
+ }
+}
+
+private class TypeParameterUpperBoundsCommonizer : AbstractListCommonizer(
+ subject = "type parameter upper bounds",
+ singleElementCommonizerFactory = { TypeCommonizer.default() }
+)
+
+interface TypeParameterListCommonizer : Commonizer, List> {
+ companion object {
+ fun default(): TypeParameterListCommonizer = DefaultTypeParameterListCommonizer()
+ }
+}
+
+private class DefaultTypeParameterListCommonizer :
+ TypeParameterListCommonizer,
+ AbstractNamedListCommonizer(
+ subject = "type parameters",
+ singleElementCommonizerFactory = { TypeParameterCommonizer.default() }
+ )
diff --git a/konan/commonizer/src/org/jetbrains/kotlin/descriptors/commonizer/core/ValueParameterCommonizer.kt b/konan/commonizer/src/org/jetbrains/kotlin/descriptors/commonizer/core/ValueParameterCommonizer.kt
index f63cc75af8b..f2d8109d7b0 100644
--- a/konan/commonizer/src/org/jetbrains/kotlin/descriptors/commonizer/core/ValueParameterCommonizer.kt
+++ b/konan/commonizer/src/org/jetbrains/kotlin/descriptors/commonizer/core/ValueParameterCommonizer.kt
@@ -82,7 +82,7 @@ interface ValueParameterListCommonizer : Commonizer(
+ AbstractNamedListCommonizer(
subject = "value parameters",
- wrappedCommonizerFactory = { ValueParameterCommonizer.default() }
+ singleElementCommonizerFactory = { ValueParameterCommonizer.default() }
)
diff --git a/konan/commonizer/src/org/jetbrains/kotlin/descriptors/commonizer/mergedtree/ir/CallableMember.kt b/konan/commonizer/src/org/jetbrains/kotlin/descriptors/commonizer/mergedtree/ir/CallableMember.kt
index c237becb521..836ed8f4b90 100644
--- a/konan/commonizer/src/org/jetbrains/kotlin/descriptors/commonizer/mergedtree/ir/CallableMember.kt
+++ b/konan/commonizer/src/org/jetbrains/kotlin/descriptors/commonizer/mergedtree/ir/CallableMember.kt
@@ -14,7 +14,7 @@ import org.jetbrains.kotlin.descriptors.commonizer.mergedtree.ir.ExtensionReceiv
import org.jetbrains.kotlin.name.Name
import org.jetbrains.kotlin.types.UnwrappedType
-interface CallableMember {
+interface CallableMember : DeclarationWithTypeParameters {
val annotations: Annotations
val name: Name
val modality: Modality
@@ -39,6 +39,7 @@ abstract class TargetCallableMember(protected val
final override val extensionReceiver: ExtensionReceiver? get() = descriptor.extensionReceiverParameter?.toReceiver()
final override val returnType: UnwrappedType get() = descriptor.returnType!!.unwrap()
final override val kind: CallableMemberDescriptor.Kind get() = descriptor.kind
+ final override val typeParameters: List get() = descriptor.typeParameters.map(::TargetTypeParameter)
}
data class ExtensionReceiver(
diff --git a/konan/commonizer/src/org/jetbrains/kotlin/descriptors/commonizer/mergedtree/ir/Function.kt b/konan/commonizer/src/org/jetbrains/kotlin/descriptors/commonizer/mergedtree/ir/Function.kt
index fe184f5a0db..e3562b98267 100644
--- a/konan/commonizer/src/org/jetbrains/kotlin/descriptors/commonizer/mergedtree/ir/Function.kt
+++ b/konan/commonizer/src/org/jetbrains/kotlin/descriptors/commonizer/mergedtree/ir/Function.kt
@@ -33,7 +33,8 @@ data class CommonFunction(
override val extensionReceiver: ExtensionReceiver?,
override val returnType: UnwrappedType,
private val modifiers: FunctionModifiers,
- override val valueParameters: List
+ override val valueParameters: List,
+ override val typeParameters: List
) : CommonCallableMember(), Function, FunctionModifiers by modifiers
class TargetFunction(descriptor: SimpleFunctionDescriptor) : TargetCallableMember(descriptor), Function {
diff --git a/konan/commonizer/src/org/jetbrains/kotlin/descriptors/commonizer/mergedtree/ir/Property.kt b/konan/commonizer/src/org/jetbrains/kotlin/descriptors/commonizer/mergedtree/ir/Property.kt
index ac35725258d..8e1e62e861f 100644
--- a/konan/commonizer/src/org/jetbrains/kotlin/descriptors/commonizer/mergedtree/ir/Property.kt
+++ b/konan/commonizer/src/org/jetbrains/kotlin/descriptors/commonizer/mergedtree/ir/Property.kt
@@ -32,7 +32,8 @@ data class CommonProperty(
override val isExternal: Boolean,
override val extensionReceiver: ExtensionReceiver?,
override val returnType: UnwrappedType,
- override val setter: Setter?
+ override val setter: Setter?,
+ override val typeParameters: List
) : CommonCallableMember(), Property {
override val isVar: Boolean get() = setter != null
override val lateInit: Boolean get() = false
diff --git a/konan/commonizer/src/org/jetbrains/kotlin/descriptors/commonizer/mergedtree/ir/TypeParameter.kt b/konan/commonizer/src/org/jetbrains/kotlin/descriptors/commonizer/mergedtree/ir/TypeParameter.kt
new file mode 100644
index 00000000000..bdab7d02701
--- /dev/null
+++ b/konan/commonizer/src/org/jetbrains/kotlin/descriptors/commonizer/mergedtree/ir/TypeParameter.kt
@@ -0,0 +1,41 @@
+/*
+ * Copyright 2010-2019 JetBrains s.r.o. and Kotlin Programming Language contributors.
+ * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
+ */
+
+package org.jetbrains.kotlin.descriptors.commonizer.mergedtree.ir
+
+import org.jetbrains.kotlin.descriptors.TypeParameterDescriptor
+import org.jetbrains.kotlin.descriptors.annotations.Annotations
+import org.jetbrains.kotlin.name.Name
+import org.jetbrains.kotlin.types.UnwrappedType
+import org.jetbrains.kotlin.types.Variance
+
+interface TypeParameter {
+ val annotations: Annotations
+ val name: Name
+ val isReified: Boolean
+ val variance: Variance
+ val upperBounds: List
+}
+
+interface DeclarationWithTypeParameters : Declaration {
+ val typeParameters: List
+}
+
+data class CommonTypeParameter(
+ override val name: Name,
+ override val isReified: Boolean,
+ override val variance: Variance,
+ override val upperBounds: List
+) : TypeParameter {
+ override val annotations: Annotations get() = Annotations.EMPTY
+}
+
+data class TargetTypeParameter(private val descriptor: TypeParameterDescriptor) : TypeParameter {
+ override val annotations: Annotations get() = descriptor.annotations
+ override val name: Name get() = descriptor.name
+ override val isReified: Boolean get() = descriptor.isReified
+ override val variance: Variance get() = descriptor.variance
+ override val upperBounds: List get() = descriptor.upperBounds.map { it.unwrap() }
+}
diff --git a/konan/commonizer/src/org/jetbrains/kotlin/descriptors/commonizer/mergedtree/packages.kt b/konan/commonizer/src/org/jetbrains/kotlin/descriptors/commonizer/mergedtree/packages.kt
index 90486ade731..0b48552d246 100644
--- a/konan/commonizer/src/org/jetbrains/kotlin/descriptors/commonizer/mergedtree/packages.kt
+++ b/konan/commonizer/src/org/jetbrains/kotlin/descriptors/commonizer/mergedtree/packages.kt
@@ -8,7 +8,7 @@ package org.jetbrains.kotlin.descriptors.commonizer.mergedtree
import org.jetbrains.kotlin.descriptors.PropertyDescriptor
import org.jetbrains.kotlin.descriptors.SimpleFunctionDescriptor
import org.jetbrains.kotlin.descriptors.commonizer.CommonizedGroupMap
-import org.jetbrains.kotlin.descriptors.commonizer.fqName
+import org.jetbrains.kotlin.descriptors.commonizer.fqNameWithTypeParameters
import org.jetbrains.kotlin.name.FqName
import org.jetbrains.kotlin.name.Name
import org.jetbrains.kotlin.resolve.scopes.DescriptorKindFilter
@@ -49,11 +49,11 @@ internal fun mergePackages(
internal data class PropertyKey(
val name: Name,
- val extensionReceiverParameterFqName: FqName?
+ val extensionReceiverParameter: String?
) {
constructor(property: PropertyDescriptor) : this(
property.name,
- property.extensionReceiverParameter?.type?.fqName
+ property.extensionReceiverParameter?.type?.fqNameWithTypeParameters
)
}
@@ -67,13 +67,13 @@ internal fun MemberScope.collectProperties(collector: (PropertyKey, PropertyDesc
internal data class FunctionKey(
val name: Name,
- val valueParameters: List>,
- val extensionReceiverParameterFqName: FqName?
+ val valueParameters: List>,
+ val extensionReceiverParameter: String?
) {
constructor(function: SimpleFunctionDescriptor) : this(
function.name,
- function.valueParameters.map { it.name to it.type.fqName },
- function.extensionReceiverParameter?.type?.fqName
+ function.valueParameters.map { it.name to it.type.fqNameWithTypeParameters },
+ function.extensionReceiverParameter?.type?.fqNameWithTypeParameters
)
}
diff --git a/konan/commonizer/src/org/jetbrains/kotlin/descriptors/commonizer/utils.kt b/konan/commonizer/src/org/jetbrains/kotlin/descriptors/commonizer/utils.kt
index 1792a57f432..9046b96f29e 100644
--- a/konan/commonizer/src/org/jetbrains/kotlin/descriptors/commonizer/utils.kt
+++ b/konan/commonizer/src/org/jetbrains/kotlin/descriptors/commonizer/utils.kt
@@ -8,6 +8,7 @@ package org.jetbrains.kotlin.descriptors.commonizer
import org.jetbrains.kotlin.name.FqName
import org.jetbrains.kotlin.resolve.descriptorUtil.fqNameSafe
import org.jetbrains.kotlin.types.KotlinType
+import org.jetbrains.kotlin.types.Variance
import org.jetbrains.kotlin.utils.addToStdlib.firstIsInstance
internal fun Sequence.toList(expectedCapacity: Int): List {
@@ -21,4 +22,30 @@ internal inline fun Iterable.firstNonNull() = firstIsInstance
internal val KotlinType.fqName: FqName
get() = constructor.declarationDescriptor!!.fqNameSafe
+internal val KotlinType.fqNameWithTypeParameters: String
+ get() = buildString { buildFqNameWithTypeParameters(this@fqNameWithTypeParameters) }
+
+private fun StringBuilder.buildFqNameWithTypeParameters(type: KotlinType) {
+ append(type.fqName)
+
+ val arguments = type.arguments
+ if (arguments.isNotEmpty()) {
+ append("<")
+ arguments.forEachIndexed { index, argument ->
+ if (index > 0)
+ append(",")
+
+ if (argument.isStarProjection)
+ append("*")
+ else {
+ val variance = argument.projectionKind
+ if (variance != Variance.INVARIANT)
+ append(variance).append(" ")
+ buildFqNameWithTypeParameters(argument.type)
+ }
+ }
+ append(">")
+ }
+}
+
internal fun Any?.isNull() = this == null
diff --git a/konan/commonizer/testData/callableMemberCommonization/extensionReceivers/commonized/common/package_root.kt b/konan/commonizer/testData/callableMemberCommonization/extensionReceivers/commonized/common/package_root.kt
index dfb3ae8a2a8..d24c2db01d7 100644
--- a/konan/commonizer/testData/callableMemberCommonization/extensionReceivers/commonized/common/package_root.kt
+++ b/konan/commonizer/testData/callableMemberCommonization/extensionReceivers/commonized/common/package_root.kt
@@ -13,3 +13,9 @@ expect fun Short.intFunction(): Int
expect fun Long.intFunction(): Int
expect fun String.intFunction(): Int
expect fun Planet.intFunction(): Int
+
+expect val T.propertyWithTypeParameter1: Int
+expect val T.propertyWithTypeParameter2: Int
+expect val T.propertyWithTypeParameter4: Int
+
+expect fun T.functionWithTypeParameter1()
diff --git a/konan/commonizer/testData/callableMemberCommonization/extensionReceivers/commonized/js/package_root.kt b/konan/commonizer/testData/callableMemberCommonization/extensionReceivers/commonized/js/package_root.kt
index c5873e4300a..67605009382 100644
--- a/konan/commonizer/testData/callableMemberCommonization/extensionReceivers/commonized/js/package_root.kt
+++ b/konan/commonizer/testData/callableMemberCommonization/extensionReceivers/commonized/js/package_root.kt
@@ -19,3 +19,18 @@ val mismatchedProperty2 get() = 42
fun String.mismatchedFunction1() = 42
fun mismatchedFunction2() = 42
+
+actual val T.propertyWithTypeParameter1 get() = 42
+actual val T.propertyWithTypeParameter2 get() = 42
+val T.propertyWithTypeParameter3 get() = 42
+actual val T.propertyWithTypeParameter4 get() = length
+val T.propertyWithTypeParameter5 get() = length
+val T.propertyWithTypeParameter6 get() = length
+val T.propertyWithTypeParameter7 get() = length
+val T.propertyWithTypeParameter8 get() = 42
+val T.propertyWithTypeParameter9 get() = 42
+
+actual fun T.functionWithTypeParameter1() {}
+fun T.functionWithTypeParameter2() {}
+fun T.functionWithTypeParameter3() {}
+fun T.functionWithTypeParameter4() {}
diff --git a/konan/commonizer/testData/callableMemberCommonization/extensionReceivers/commonized/jvm/package_root.kt b/konan/commonizer/testData/callableMemberCommonization/extensionReceivers/commonized/jvm/package_root.kt
index 22ff0baf6c2..bc36bd5a764 100644
--- a/konan/commonizer/testData/callableMemberCommonization/extensionReceivers/commonized/jvm/package_root.kt
+++ b/konan/commonizer/testData/callableMemberCommonization/extensionReceivers/commonized/jvm/package_root.kt
@@ -19,3 +19,18 @@ val Double.mismatchedProperty2 get() = 42
fun mismatchedFunction1() = 42
fun Double.mismatchedFunction2() = 42
+
+actual val T.propertyWithTypeParameter1 get() = 42
+actual val T.propertyWithTypeParameter2 get() = 42
+val T.propertyWithTypeParameter3 get() = 42
+actual val T.propertyWithTypeParameter4 get() = length
+val T.propertyWithTypeParameter5 get() = length
+val T.propertyWithTypeParameter6 get() = length
+val String.propertyWithTypeParameter7 get() = length
+val Q.propertyWithTypeParameter8 get() = 42
+val T.propertyWithTypeParameter9 get() = 42
+
+actual fun T.functionWithTypeParameter1() {}
+fun Q.functionWithTypeParameter2() {}
+fun T.functionWithTypeParameter3() {}
+fun Q.functionWithTypeParameter4() {}
diff --git a/konan/commonizer/testData/callableMemberCommonization/extensionReceivers/original/js/package_root.kt b/konan/commonizer/testData/callableMemberCommonization/extensionReceivers/original/js/package_root.kt
index 7cab8a200ea..2cf7c3b4436 100644
--- a/konan/commonizer/testData/callableMemberCommonization/extensionReceivers/original/js/package_root.kt
+++ b/konan/commonizer/testData/callableMemberCommonization/extensionReceivers/original/js/package_root.kt
@@ -19,3 +19,18 @@ val mismatchedProperty2 get() = 42
fun String.mismatchedFunction1() = 42
fun mismatchedFunction2() = 42
+
+val T.propertyWithTypeParameter1 get() = 42
+val T.propertyWithTypeParameter2 get() = 42
+val T.propertyWithTypeParameter3 get() = 42
+val T.propertyWithTypeParameter4 get() = length
+val T.propertyWithTypeParameter5 get() = length
+val T.propertyWithTypeParameter6 get() = length
+val T.propertyWithTypeParameter7 get() = length
+val T.propertyWithTypeParameter8 get() = 42
+val T.propertyWithTypeParameter9 get() = 42
+
+fun T.functionWithTypeParameter1() {}
+fun T.functionWithTypeParameter2() {}
+fun T.functionWithTypeParameter3() {}
+fun T.functionWithTypeParameter4() {}
diff --git a/konan/commonizer/testData/callableMemberCommonization/extensionReceivers/original/jvm/package_root.kt b/konan/commonizer/testData/callableMemberCommonization/extensionReceivers/original/jvm/package_root.kt
index daa1c272269..df3ce507794 100644
--- a/konan/commonizer/testData/callableMemberCommonization/extensionReceivers/original/jvm/package_root.kt
+++ b/konan/commonizer/testData/callableMemberCommonization/extensionReceivers/original/jvm/package_root.kt
@@ -19,3 +19,18 @@ val Double.mismatchedProperty2 get() = 42
fun mismatchedFunction1() = 42
fun Double.mismatchedFunction2() = 42
+
+val T.propertyWithTypeParameter1 get() = 42
+val T.propertyWithTypeParameter2 get() = 42
+val T.propertyWithTypeParameter3 get() = 42
+val T.propertyWithTypeParameter4 get() = length
+val T.propertyWithTypeParameter5 get() = length
+val T.propertyWithTypeParameter6 get() = length
+val String.propertyWithTypeParameter7 get() = length
+val Q.propertyWithTypeParameter8 get() = 42
+val T.propertyWithTypeParameter9 get() = 42
+
+fun T.functionWithTypeParameter1() {}
+fun Q.functionWithTypeParameter2() {}
+fun T.functionWithTypeParameter3() {}
+fun Q.functionWithTypeParameter4() {}
diff --git a/konan/commonizer/testData/callableMemberCommonization/returnTypes/commonized/common/package_root.kt b/konan/commonizer/testData/callableMemberCommonization/returnTypes/commonized/common/package_root.kt
index 1d0cae72063..a21faee290c 100644
--- a/konan/commonizer/testData/callableMemberCommonization/returnTypes/commonized/common/package_root.kt
+++ b/konan/commonizer/testData/callableMemberCommonization/returnTypes/commonized/common/package_root.kt
@@ -19,3 +19,19 @@ expect fun function2(): String
expect fun function3(): Planet
expect fun function6(): Planet
expect fun function7(): C
+
+class Box(val value: T)
+class Fox
+
+expect fun functionWithTypeParametersInReturnType1(): Array
+expect fun functionWithTypeParametersInReturnType3(): Array
+expect fun functionWithTypeParametersInReturnType4(): List
+expect fun functionWithTypeParametersInReturnType6(): List
+expect fun functionWithTypeParametersInReturnType7(): Box
+expect fun functionWithTypeParametersInReturnType9(): Box
+expect fun functionWithTypeParametersInReturnType10(): Box
+expect fun functionWithTypeParametersInReturnType12(): Box
+
+expect fun functionWithUnsubstitutedTypeParametersInReturnType1(): T
+expect fun functionWithUnsubstitutedTypeParametersInReturnType2(): T
+expect fun functionWithUnsubstitutedTypeParametersInReturnType8(): Box
diff --git a/konan/commonizer/testData/callableMemberCommonization/returnTypes/commonized/js/package_root.kt b/konan/commonizer/testData/callableMemberCommonization/returnTypes/commonized/js/package_root.kt
index a9e3e496f0c..dbfd9e282c7 100644
--- a/konan/commonizer/testData/callableMemberCommonization/returnTypes/commonized/js/package_root.kt
+++ b/konan/commonizer/testData/callableMemberCommonization/returnTypes/commonized/js/package_root.kt
@@ -36,3 +36,29 @@ fun functionWithMismatchedType2(): Int = 1
fun functionWithMismatchedType3(): Int = 1
fun functionWithMismatchedType4(): Int = 1
fun functionWithMismatchedType5(): Int = 1
+
+class Box(val value: T)
+class Fox
+
+actual fun functionWithTypeParametersInReturnType1() = arrayOf(1)
+fun functionWithTypeParametersInReturnType2() = arrayOf(1)
+actual fun functionWithTypeParametersInReturnType3() = arrayOf("hello")
+actual fun functionWithTypeParametersInReturnType4(): List = listOf(1)
+fun functionWithTypeParametersInReturnType5(): List = listOf(1)
+actual fun functionWithTypeParametersInReturnType6(): List = listOf("hello")
+actual fun functionWithTypeParametersInReturnType7() = Box(1)
+fun functionWithTypeParametersInReturnType8() = Box(1)
+actual fun functionWithTypeParametersInReturnType9() = Box("hello")
+actual fun functionWithTypeParametersInReturnType10() = Box(Planet("Earth", 12742))
+fun functionWithTypeParametersInReturnType11() = Box(Planet("Earth", 12742))
+actual fun functionWithTypeParametersInReturnType12() = Box(Fox())
+
+actual fun functionWithUnsubstitutedTypeParametersInReturnType1(): T = TODO()
+actual fun functionWithUnsubstitutedTypeParametersInReturnType2(): T = TODO()
+fun functionWithUnsubstitutedTypeParametersInReturnType3(): T = TODO()
+fun functionWithUnsubstitutedTypeParametersInReturnType4(): T = TODO()
+fun functionWithUnsubstitutedTypeParametersInReturnType5(): T = TODO()
+fun functionWithUnsubstitutedTypeParametersInReturnType6(): T = TODO()
+fun functionWithUnsubstitutedTypeParametersInReturnType7(): T = TODO()
+actual fun functionWithUnsubstitutedTypeParametersInReturnType8(): Box = TODO()
+fun functionWithUnsubstitutedTypeParametersInReturnType9(): Box = TODO()
diff --git a/konan/commonizer/testData/callableMemberCommonization/returnTypes/commonized/jvm/package_root.kt b/konan/commonizer/testData/callableMemberCommonization/returnTypes/commonized/jvm/package_root.kt
index 378a1be17ee..4dd157e6412 100644
--- a/konan/commonizer/testData/callableMemberCommonization/returnTypes/commonized/jvm/package_root.kt
+++ b/konan/commonizer/testData/callableMemberCommonization/returnTypes/commonized/jvm/package_root.kt
@@ -36,3 +36,29 @@ fun functionWithMismatchedType2(): Short = 1
fun functionWithMismatchedType3(): Number = 1
fun functionWithMismatchedType4(): Comparable = 1
fun functionWithMismatchedType5(): String = 1.toString()
+
+class Box(val value: T)
+class Fox
+
+actual fun functionWithTypeParametersInReturnType1() = arrayOf(1)
+fun functionWithTypeParametersInReturnType2() = arrayOf("hello")
+actual fun functionWithTypeParametersInReturnType3() = arrayOf("hello")
+actual fun functionWithTypeParametersInReturnType4(): List = listOf(1)
+fun functionWithTypeParametersInReturnType5(): List = listOf("hello")
+actual fun functionWithTypeParametersInReturnType6(): List = listOf("hello")
+actual fun functionWithTypeParametersInReturnType7() = Box(1)
+fun functionWithTypeParametersInReturnType8() = Box("hello")
+actual fun functionWithTypeParametersInReturnType9() = Box("hello")
+actual fun functionWithTypeParametersInReturnType10() = Box(Planet("Earth", 12742))
+fun functionWithTypeParametersInReturnType11() = Box(Fox())
+actual fun functionWithTypeParametersInReturnType12() = Box(Fox())
+
+actual fun functionWithUnsubstitutedTypeParametersInReturnType1(): T = TODO()
+actual fun functionWithUnsubstitutedTypeParametersInReturnType2(): T = TODO()
+fun functionWithUnsubstitutedTypeParametersInReturnType3(): T = TODO()
+fun functionWithUnsubstitutedTypeParametersInReturnType4(): Q = TODO()
+fun functionWithUnsubstitutedTypeParametersInReturnType5(): T = TODO()
+fun functionWithUnsubstitutedTypeParametersInReturnType6(): Q = TODO()
+fun functionWithUnsubstitutedTypeParametersInReturnType7(): String = TODO()
+actual fun functionWithUnsubstitutedTypeParametersInReturnType8(): Box = TODO()
+fun functionWithUnsubstitutedTypeParametersInReturnType9(): Box = TODO()
diff --git a/konan/commonizer/testData/callableMemberCommonization/returnTypes/original/js/package_root.kt b/konan/commonizer/testData/callableMemberCommonization/returnTypes/original/js/package_root.kt
index f7680053299..1d8883f6b4c 100644
--- a/konan/commonizer/testData/callableMemberCommonization/returnTypes/original/js/package_root.kt
+++ b/konan/commonizer/testData/callableMemberCommonization/returnTypes/original/js/package_root.kt
@@ -38,3 +38,29 @@ fun functionWithMismatchedType2(): Int = 1
fun functionWithMismatchedType3(): Int = 1
fun functionWithMismatchedType4(): Int = 1
fun functionWithMismatchedType5(): Int = 1
+
+class Box(val value: T)
+class Fox
+
+fun functionWithTypeParametersInReturnType1() = arrayOf(1)
+fun functionWithTypeParametersInReturnType2() = arrayOf(1)
+fun functionWithTypeParametersInReturnType3() = arrayOf("hello")
+fun functionWithTypeParametersInReturnType4(): List = listOf(1)
+fun functionWithTypeParametersInReturnType5(): List = listOf(1)
+fun functionWithTypeParametersInReturnType6(): List = listOf("hello")
+fun functionWithTypeParametersInReturnType7() = Box(1)
+fun functionWithTypeParametersInReturnType8() = Box(1)
+fun functionWithTypeParametersInReturnType9() = Box("hello")
+fun functionWithTypeParametersInReturnType10() = Box(Planet("Earth", 12742))
+fun functionWithTypeParametersInReturnType11() = Box(Planet("Earth", 12742))
+fun functionWithTypeParametersInReturnType12() = Box(Fox())
+
+fun functionWithUnsubstitutedTypeParametersInReturnType1(): T = TODO()
+fun functionWithUnsubstitutedTypeParametersInReturnType2(): T = TODO()
+fun functionWithUnsubstitutedTypeParametersInReturnType3(): T = TODO()
+fun functionWithUnsubstitutedTypeParametersInReturnType4(): T = TODO()
+fun functionWithUnsubstitutedTypeParametersInReturnType5(): T = TODO()
+fun functionWithUnsubstitutedTypeParametersInReturnType6(): T = TODO()
+fun functionWithUnsubstitutedTypeParametersInReturnType7(): T = TODO()
+fun functionWithUnsubstitutedTypeParametersInReturnType8(): Box = TODO()
+fun functionWithUnsubstitutedTypeParametersInReturnType9(): Box = TODO()
diff --git a/konan/commonizer/testData/callableMemberCommonization/returnTypes/original/jvm/package_root.kt b/konan/commonizer/testData/callableMemberCommonization/returnTypes/original/jvm/package_root.kt
index 31ebb440109..820bab8f1fb 100644
--- a/konan/commonizer/testData/callableMemberCommonization/returnTypes/original/jvm/package_root.kt
+++ b/konan/commonizer/testData/callableMemberCommonization/returnTypes/original/jvm/package_root.kt
@@ -38,3 +38,29 @@ fun functionWithMismatchedType2(): Short = 1
fun functionWithMismatchedType3(): Number = 1
fun functionWithMismatchedType4(): Comparable = 1
fun functionWithMismatchedType5(): String = 1.toString()
+
+class Box(val value: T)
+class Fox
+
+fun functionWithTypeParametersInReturnType1() = arrayOf(1)
+fun functionWithTypeParametersInReturnType2() = arrayOf("hello")
+fun functionWithTypeParametersInReturnType3() = arrayOf("hello")
+fun functionWithTypeParametersInReturnType4(): List = listOf(1)
+fun functionWithTypeParametersInReturnType5(): List = listOf("hello")
+fun functionWithTypeParametersInReturnType6(): List = listOf("hello")
+fun functionWithTypeParametersInReturnType7() = Box(1)
+fun functionWithTypeParametersInReturnType8() = Box("hello")
+fun functionWithTypeParametersInReturnType9() = Box("hello")
+fun functionWithTypeParametersInReturnType10() = Box(Planet("Earth", 12742))
+fun functionWithTypeParametersInReturnType11() = Box(Fox())
+fun functionWithTypeParametersInReturnType12() = Box(Fox())
+
+fun functionWithUnsubstitutedTypeParametersInReturnType1(): T = TODO()
+fun functionWithUnsubstitutedTypeParametersInReturnType2(): T = TODO()
+fun functionWithUnsubstitutedTypeParametersInReturnType3(): T = TODO()
+fun functionWithUnsubstitutedTypeParametersInReturnType4(): Q = TODO()
+fun functionWithUnsubstitutedTypeParametersInReturnType5(): T = TODO()
+fun functionWithUnsubstitutedTypeParametersInReturnType6(): Q = TODO()
+fun functionWithUnsubstitutedTypeParametersInReturnType7(): String = TODO()
+fun functionWithUnsubstitutedTypeParametersInReturnType8(): Box = TODO()
+fun functionWithUnsubstitutedTypeParametersInReturnType9(): Box = TODO()
diff --git a/konan/commonizer/testData/functionCommonization/valueParameters/commonized/common/package_root.kt b/konan/commonizer/testData/functionCommonization/valueParameters/commonized/common/package_root.kt
index 206bebb7cf3..9309949a571 100644
--- a/konan/commonizer/testData/functionCommonization/valueParameters/commonized/common/package_root.kt
+++ b/konan/commonizer/testData/functionCommonization/valueParameters/commonized/common/package_root.kt
@@ -11,3 +11,8 @@ expect inline fun inlineFunction5(noinline lazyMessage: () -> String)
expect fun functionWithVararg1(vararg numbers: Int)
expect fun functionWithVararg5(numbers: Array)
+expect fun functionWithVararg6(vararg names: String)
+expect fun functionWithVararg10(names: Array)
+
+expect fun functionWithTypeParameters1(p1: T, p2: String)
+expect fun functionWithTypeParameters4(p1: Q, p2: R)
diff --git a/konan/commonizer/testData/functionCommonization/valueParameters/commonized/js/package_root.kt b/konan/commonizer/testData/functionCommonization/valueParameters/commonized/js/package_root.kt
index 8ea15f08a7a..d943a6fd75a 100644
--- a/konan/commonizer/testData/functionCommonization/valueParameters/commonized/js/package_root.kt
+++ b/konan/commonizer/testData/functionCommonization/valueParameters/commonized/js/package_root.kt
@@ -24,5 +24,17 @@ actual inline fun inlineFunction5(noinline lazyMessage: () -> String) {}
actual fun functionWithVararg1(vararg numbers: Int) {}
fun functionWithVararg2(vararg numbers: Int) {}
fun functionWithVararg3(vararg numbers: Int) {}
-//fun functionWithVararg4(numbers: Array) {}
+fun functionWithVararg4(numbers: Array) {}
actual fun functionWithVararg5(numbers: Array) {}
+actual fun functionWithVararg6(vararg names: String) {}
+fun functionWithVararg7(vararg names: String) {}
+fun functionWithVararg8(vararg names: String) {}
+fun functionWithVararg9(names: Array) {}
+actual fun functionWithVararg10(names: Array) {}
+
+actual fun functionWithTypeParameters1(p1: T, p2: String) {}
+fun functionWithTypeParameters2(p1: T, p2: String) {}
+fun functionWithTypeParameters3(p1: T, p2: String) {}
+actual fun functionWithTypeParameters4(p1: Q, p2: R) {}
+fun functionWithTypeParameters5(p1: Q, p2: R) {}
+fun functionWithTypeParameters6(p1: Q, p2: R) {}
diff --git a/konan/commonizer/testData/functionCommonization/valueParameters/commonized/jvm/package_root.kt b/konan/commonizer/testData/functionCommonization/valueParameters/commonized/jvm/package_root.kt
index b96b4ef91ce..2c23a79c97d 100644
--- a/konan/commonizer/testData/functionCommonization/valueParameters/commonized/jvm/package_root.kt
+++ b/konan/commonizer/testData/functionCommonization/valueParameters/commonized/jvm/package_root.kt
@@ -24,5 +24,17 @@ actual inline fun inlineFunction5(noinline lazyMessage: () -> String) {}
actual fun functionWithVararg1(vararg numbers: Int) {}
fun functionWithVararg2(numbers: Array) {}
fun functionWithVararg3(numbers: Array) {}
-//fun functionWithVararg4(numbers: Array) {}
+fun functionWithVararg4(numbers: Array) {}
actual fun functionWithVararg5(numbers: Array) {}
+actual fun functionWithVararg6(vararg names: String) {}
+fun functionWithVararg7(names: Array) {}
+fun functionWithVararg8(names: Array) {}
+fun functionWithVararg9(names: Array) {}
+actual fun functionWithVararg10(names: Array) {}
+
+actual fun functionWithTypeParameters1(p1: T, p2: String) {}
+fun functionWithTypeParameters2(p1: String, p2: String) {}
+fun functionWithTypeParameters2(p1: String, p2: T) {}
+actual fun functionWithTypeParameters4(p1: Q, p2: R) {}
+fun functionWithTypeParameters5(p1: Q, p2: R) {}
+fun functionWithTypeParameters6(p1: R, p2: Q) {}
diff --git a/konan/commonizer/testData/functionCommonization/valueParameters/original/js/package_root.kt b/konan/commonizer/testData/functionCommonization/valueParameters/original/js/package_root.kt
index 13e6c537b73..bde3e547660 100644
--- a/konan/commonizer/testData/functionCommonization/valueParameters/original/js/package_root.kt
+++ b/konan/commonizer/testData/functionCommonization/valueParameters/original/js/package_root.kt
@@ -24,5 +24,17 @@ inline fun inlineFunction5(noinline lazyMessage: () -> String) {}
fun functionWithVararg1(vararg numbers: Int) {}
fun functionWithVararg2(vararg numbers: Int) {}
fun functionWithVararg3(vararg numbers: Int) {}
-//fun functionWithVararg4(numbers: Array) {}
+fun functionWithVararg4(numbers: Array) {}
fun functionWithVararg5(numbers: Array) {}
+fun functionWithVararg6(vararg names: String) {}
+fun functionWithVararg7(vararg names: String) {}
+fun functionWithVararg8(vararg names: String) {}
+fun functionWithVararg9(names: Array) {}
+fun functionWithVararg10(names: Array) {}
+
+fun functionWithTypeParameters1(p1: T, p2: String) {}
+fun functionWithTypeParameters2(p1: T, p2: String) {}
+fun functionWithTypeParameters3(p1: T, p2: String) {}
+fun functionWithTypeParameters4(p1: Q, p2: R) {}
+fun functionWithTypeParameters5(p1: Q, p2: R) {}
+fun functionWithTypeParameters6(p1: Q, p2: R) {}
diff --git a/konan/commonizer/testData/functionCommonization/valueParameters/original/jvm/package_root.kt b/konan/commonizer/testData/functionCommonization/valueParameters/original/jvm/package_root.kt
index f6ac65c9287..e358bb08b0a 100644
--- a/konan/commonizer/testData/functionCommonization/valueParameters/original/jvm/package_root.kt
+++ b/konan/commonizer/testData/functionCommonization/valueParameters/original/jvm/package_root.kt
@@ -24,5 +24,17 @@ inline fun inlineFunction5(noinline lazyMessage: () -> String) {}
fun functionWithVararg1(vararg numbers: Int) {}
fun functionWithVararg2(numbers: Array) {}
fun functionWithVararg3(numbers: Array) {}
-//fun functionWithVararg4(numbers: Array) {}
+fun functionWithVararg4(numbers: Array) {}
fun functionWithVararg5(numbers: Array) {}
+fun functionWithVararg6(vararg names: String) {}
+fun functionWithVararg7(names: Array) {}
+fun functionWithVararg8(names: Array) {}
+fun functionWithVararg9(names: Array) {}
+fun functionWithVararg10(names: Array) {}
+
+fun functionWithTypeParameters1(p1: T, p2: String) {}
+fun functionWithTypeParameters2(p1: String, p2: String) {}
+fun functionWithTypeParameters2(p1: String, p2: T) {}
+fun functionWithTypeParameters4(p1: Q, p2: R) {}
+fun functionWithTypeParameters5(p1: Q, p2: R) {}
+fun functionWithTypeParameters6(p1: R, p2: Q) {}
diff --git a/konan/commonizer/testData/generalCommonization/annotations/commonized/common/package_root.kt b/konan/commonizer/testData/generalCommonization/annotations/commonized/common/package_root.kt
index 5a1759bfba7..9a686afc15a 100644
--- a/konan/commonizer/testData/generalCommonization/annotations/commonized/common/package_root.kt
+++ b/konan/commonizer/testData/generalCommonization/annotations/commonized/common/package_root.kt
@@ -1,7 +1,7 @@
expect var propertyWithoutBackingField: Double
expect val propertyWithBackingField: Double
expect val propertyWithDelegateField: Int
-expect val String.propertyWithExtensionReceiver: Int
+expect val T.propertyWithExtensionReceiver: Int
expect fun function1(text: String): String
-expect fun String.function2(): String
+expect fun Q.function2(): Q
diff --git a/konan/commonizer/testData/generalCommonization/annotations/commonized/js/package_root.kt b/konan/commonizer/testData/generalCommonization/annotations/commonized/js/package_root.kt
index d505eede886..d35a86d583d 100644
--- a/konan/commonizer/testData/generalCommonization/annotations/commonized/js/package_root.kt
+++ b/konan/commonizer/testData/generalCommonization/annotations/commonized/js/package_root.kt
@@ -17,11 +17,11 @@ actual val propertyWithBackingField = 3.14
@delegate:Foo("field")
actual val propertyWithDelegateField: Int by lazy { 42 }
-actual val @receiver:Foo("receiver") String.propertyWithExtensionReceiver: Int
+actual val <@Foo("type-parameter") T : CharSequence> @receiver:Foo("receiver") T.propertyWithExtensionReceiver: Int
get() = length
@Foo("function")
actual fun function1(@Foo("parameter") text: String) = text
@Foo("function")
-actual fun @receiver:Foo("receiver") String.function2() = this
+actual fun <@Foo("type-parameter") Q : Number> @receiver:Foo("receiver") Q.function2() = this
diff --git a/konan/commonizer/testData/generalCommonization/annotations/commonized/jvm/package_root.kt b/konan/commonizer/testData/generalCommonization/annotations/commonized/jvm/package_root.kt
index 7f422677aad..ddd2d2717a9 100644
--- a/konan/commonizer/testData/generalCommonization/annotations/commonized/jvm/package_root.kt
+++ b/konan/commonizer/testData/generalCommonization/annotations/commonized/jvm/package_root.kt
@@ -14,11 +14,11 @@ actual val propertyWithBackingField = 3.14
@delegate:Bar("field")
actual val propertyWithDelegateField: Int by lazy { 42 }
-actual val @receiver:Bar("receiver") String.propertyWithExtensionReceiver: Int
+actual val <@Bar("type-parameter") T : CharSequence> @receiver:Bar("receiver") T.propertyWithExtensionReceiver: Int
get() = length
@Bar("function")
actual fun function1(@Bar("parameter") text: String) = text
@Bar("function")
-actual fun @receiver:Foo("receiver") String.function2() = this
+actual fun <@Bar("type-parameter") Q : Number> @receiver:Bar("receiver") Q.function2() = this
diff --git a/konan/commonizer/testData/generalCommonization/annotations/original/js/package_root.kt b/konan/commonizer/testData/generalCommonization/annotations/original/js/package_root.kt
index 48a4756e78a..fedae0e5d6e 100644
--- a/konan/commonizer/testData/generalCommonization/annotations/original/js/package_root.kt
+++ b/konan/commonizer/testData/generalCommonization/annotations/original/js/package_root.kt
@@ -1,6 +1,6 @@
import kotlin.annotation.AnnotationTarget.*
-@Target(PROPERTY, PROPERTY_GETTER, PROPERTY_SETTER, FIELD, VALUE_PARAMETER, FUNCTION)
+@Target(PROPERTY, PROPERTY_GETTER, PROPERTY_SETTER, FIELD, VALUE_PARAMETER, TYPE_PARAMETER, FUNCTION)
annotation class Foo(val text: String)
@Foo("property")
@@ -14,11 +14,11 @@ val propertyWithBackingField = 3.14
@delegate:Foo("field")
val propertyWithDelegateField: Int by lazy { 42 }
-val @receiver:Foo("receiver") String.propertyWithExtensionReceiver: Int
+val <@Foo("type-parameter") T : CharSequence> @receiver:Foo("receiver") T.propertyWithExtensionReceiver: Int
get() = length
@Foo("function")
fun function1(@Foo("parameter") text: String) = text
@Foo("function")
-fun @receiver:Foo("receiver") String.function2() = this
+fun <@Foo("type-parameter") Q : Number> @receiver:Foo("receiver") Q.function2() = this
diff --git a/konan/commonizer/testData/generalCommonization/annotations/original/jvm/package_root.kt b/konan/commonizer/testData/generalCommonization/annotations/original/jvm/package_root.kt
index c0668feb872..12f9416217d 100644
--- a/konan/commonizer/testData/generalCommonization/annotations/original/jvm/package_root.kt
+++ b/konan/commonizer/testData/generalCommonization/annotations/original/jvm/package_root.kt
@@ -14,11 +14,11 @@ val propertyWithBackingField = 3.14
@delegate:Bar("field")
val propertyWithDelegateField: Int by lazy { 42 }
-val @receiver:Bar("receiver") String.propertyWithExtensionReceiver: Int
+val <@Bar("type-parameter") T : CharSequence> @receiver:Bar("receiver") T.propertyWithExtensionReceiver: Int
get() = length
@Bar("function")
fun function1(@Bar("parameter") text: String) = text
@Bar("function")
-fun @receiver:Foo("receiver") String.function2() = this
+fun <@Bar("type-parameter") Q : Number> @receiver:Bar("receiver") Q.function2() = this
diff --git a/konan/commonizer/tests/org/jetbrains/kotlin/descriptors/commonizer/assertions.kt b/konan/commonizer/tests/org/jetbrains/kotlin/descriptors/commonizer/assertions.kt
index dc33134bc1d..e4ad46dd6f6 100644
--- a/konan/commonizer/tests/org/jetbrains/kotlin/descriptors/commonizer/assertions.kt
+++ b/konan/commonizer/tests/org/jetbrains/kotlin/descriptors/commonizer/assertions.kt
@@ -67,7 +67,7 @@ private class ComparingDeclarationsVisitor(
override fun visitModuleDeclaration(expected: ModuleDescriptor, context: Context) {
val actual = context.getActualAs()
- context.assertEquals(expected.name, actual.name, "module names")
+ context.assertFieldsEqual(expected::getName, actual::getName)
fun collectPackageMemberScopes(module: ModuleDescriptor): Map = mutableMapOf().also {
module.collectNonEmptyPackageMemberScopes { packageFqName, memberScope ->
@@ -79,7 +79,7 @@ private class ComparingDeclarationsVisitor(
val expectedPackageMemberScopes = collectPackageMemberScopes(expected)
val actualPackageMemberScopes = collectPackageMemberScopes(actual)
- context.assertEquals(expectedPackageMemberScopes.keys, actualPackageMemberScopes.keys, "sets of packages")
+ context.assertSetsEqual(expectedPackageMemberScopes.keys, actualPackageMemberScopes.keys, "sets of packages")
for (packageFqName in expectedPackageMemberScopes.keys) {
val expectedMemberScope = expectedPackageMemberScopes.getValue(packageFqName)
@@ -100,7 +100,7 @@ private class ComparingDeclarationsVisitor(
val expectedProperties = collectProperties(expected)
val actualProperties = collectProperties(actual)
- context.assertEquals(expectedProperties.keys, actualProperties.keys, "sets of properties")
+ context.assertSetsEqual(expectedProperties.keys, actualProperties.keys, "sets of properties")
expectedProperties.forEach { (propertyKey, expectedProperty) ->
val actualProperty = actualProperties.getValue(propertyKey)
@@ -117,7 +117,7 @@ private class ComparingDeclarationsVisitor(
val expectedFunctions = collectFunctions(expected)
val actualFunctions = collectFunctions(actual)
- context.assertEquals(expectedFunctions.keys, actualFunctions.keys, "sets of functions")
+ context.assertSetsEqual(expectedFunctions.keys, actualFunctions.keys, "sets of functions")
expectedFunctions.forEach { (functionKey, expectedFunction) ->
val actualFunction = actualFunctions.getValue(functionKey)
@@ -153,6 +153,8 @@ private class ComparingDeclarationsVisitor(
visitReceiverParameterDescriptor(expected.extensionReceiverParameter, context.nextLevel(actual.extensionReceiverParameter))
visitReceiverParameterDescriptor(expected.dispatchReceiverParameter, context.nextLevel(actual.dispatchReceiverParameter))
+
+ visitTypeParameters(expected.typeParameters, actual.typeParameters, context.nextLevel("Function type parameters"))
}
fun visitValueParameterDescriptorList(
@@ -172,17 +174,43 @@ private class ComparingDeclarationsVisitor(
val actual = context.getActualAs()
visitAnnotations(expected.annotations, actual.annotations, context.nextLevel("Value parameter annotations"))
- context.assertEquals(expected.name, actual.name, "Name")
- context.assertEquals(expected.index, actual.index, "Index")
- context.assertEquals(expected.declaresDefaultValue(), actual.declaresDefaultValue(), "Declares default value")
- context.assertEquals(expected.isCrossinline, actual.isCrossinline, "Crossinline")
- context.assertEquals(expected.isNoinline, actual.isNoinline, "Noinline")
+ context.assertFieldsEqual(expected::getName, actual::getName)
+ context.assertFieldsEqual(expected::index, actual::index)
+ context.assertFieldsEqual(expected::declaresDefaultValue, actual::declaresDefaultValue)
+ context.assertFieldsEqual(expected::isCrossinline, actual::isCrossinline)
+ context.assertFieldsEqual(expected::isNoinline, actual::isNoinline)
visitType(expected.type, actual.type, context.nextLevel("Value parameter type"))
visitType(expected.varargElementType, actual.varargElementType, context.nextLevel("Value parameter vararg element type"))
}
+ private fun visitTypeParameters(expected: List, actual: List, context: Context) {
+ context.assertEquals(expected.size, actual.size, "Type parameters list size")
+
+ expected.forEachIndexed { index, expectedParam ->
+ val actualParam = actual[index]
+ visitTypeParameterDescriptor(expectedParam, context.nextLevel(actualParam))
+ }
+ }
+
override fun visitTypeParameterDescriptor(expected: TypeParameterDescriptor, context: Context) {
- TODO("not implemented")
+ val actual = context.getActualAs()
+
+ visitAnnotations(expected.annotations, actual.annotations, context.nextLevel("Type parameter annotations"))
+ context.assertFieldsEqual(expected::getName, actual::getName)
+ context.assertFieldsEqual(expected::getIndex, actual::getIndex)
+ context.assertFieldsEqual(expected::isCapturedFromOuterDeclaration, actual::isCapturedFromOuterDeclaration)
+ context.assertFieldsEqual(expected::isReified, actual::isReified)
+ context.assertFieldsEqual(expected::getVariance, actual::getVariance)
+
+ val expectedUpperBounds = expected.upperBounds
+ val actualUpperBounds = actual.upperBounds
+
+ context.assertEquals(expectedUpperBounds.size, actualUpperBounds.size, "Size of upper bound types")
+
+ expectedUpperBounds.forEachIndexed { index, expectedType ->
+ val actualType = actualUpperBounds[index]
+ visitType(expectedType, actualType, context.nextLevel("Type parameter type"))
+ }
}
override fun visitClassDescriptor(expected: ClassDescriptor, context: Context) {
@@ -231,6 +259,8 @@ private class ComparingDeclarationsVisitor(
visitReceiverParameterDescriptor(expected.extensionReceiverParameter, context.nextLevel(actual.extensionReceiverParameter))
visitReceiverParameterDescriptor(expected.dispatchReceiverParameter, context.nextLevel(actual.dispatchReceiverParameter))
+
+ visitTypeParameters(expected.typeParameters, actual.typeParameters, context.nextLevel("Property type parameters"))
}
override fun visitPropertyGetterDescriptor(expected: PropertyGetterDescriptor?, context: Context) {
@@ -280,7 +310,7 @@ private class ComparingDeclarationsVisitor(
val expectedAnnotationFqNames = (expected ?: Annotations.EMPTY).map { it.fqName }.toSet()
val actualAnnotationFqNames = (actual ?: Annotations.EMPTY).map { it.fqName }.toSet()
- context.assertEquals(expectedAnnotationFqNames, actualAnnotationFqNames, "annotations")
+ context.assertSetsEqual(expectedAnnotationFqNames, actualAnnotationFqNames, "annotations")
}
private fun visitType(expected: KotlinType?, actual: KotlinType?, context: Context) {
@@ -297,6 +327,21 @@ private class ComparingDeclarationsVisitor(
val actualFqName = actualUnwrapped.fqName
context.assertEquals(expectedFqName, actualFqName, "type FQN")
+
+ val expectedArguments = expectedUnwrapped.arguments
+ val actualArguments = actualUnwrapped.arguments
+
+ context.assertEquals(expectedArguments.size, actualArguments.size, "size of type arguments list")
+
+ expectedArguments.forEachIndexed { index, expectedArgument ->
+ val actualArgument = actualArguments[index]
+
+ context.assertFieldsEqual(expectedArgument::isStarProjection, actualArgument::isStarProjection)
+ if (!expectedArgument.isStarProjection) {
+ context.assertFieldsEqual(expectedArgument::getProjectionKind, actualArgument::getProjectionKind)
+ visitType(expectedArgument.type, actualArgument.type, context.nextLevel("Type argument type"))
+ }
+ }
}
private fun Context.assertEquals(expected: T?, actual: T?, subject: String) {
@@ -317,6 +362,24 @@ private class ComparingDeclarationsVisitor(
assertEquals(expectedValue, actualValue, "fields \"$expected\"")
}
+ private fun Context.assertSetsEqual(expected: Set, actual: Set, subject: String) {
+ val expectedMinusActual = expected.subtract(actual)
+ val actualMinusExpected = actual.subtract(expected)
+
+ if (expectedMinusActual.isNotEmpty() || actualMinusExpected.isNotEmpty())
+ fail(
+ buildString {
+ append("Comparing $subject:\n")
+ append("$expected is not equal to $actual\n")
+ append("Expected size: ${expected.size}\n")
+ append("Actual size: ${actual.size}\n")
+ append("Expected minus actual: $expectedMinusActual\n")
+ append("Actual minus expected: $actualMinusExpected\n")
+ append(this@assertSetsEqual.toString())
+ }
+ )
+ }
+
override fun visitPackageViewDescriptor(expected: PackageViewDescriptor, context: Context) =
fail("Comparison of package views not supported")
diff --git a/konan/commonizer/tests/org/jetbrains/kotlin/descriptors/commonizer/core/DefaultTypeParameterCommonizerTest.kt b/konan/commonizer/tests/org/jetbrains/kotlin/descriptors/commonizer/core/DefaultTypeParameterCommonizerTest.kt
new file mode 100644
index 00000000000..f5a0306eb7a
--- /dev/null
+++ b/konan/commonizer/tests/org/jetbrains/kotlin/descriptors/commonizer/core/DefaultTypeParameterCommonizerTest.kt
@@ -0,0 +1,110 @@
+/*
+ * Copyright 2010-2019 JetBrains s.r.o. and Kotlin Programming Language contributors.
+ * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
+ */
+
+package org.jetbrains.kotlin.descriptors.commonizer.core
+
+import org.jetbrains.kotlin.descriptors.TypeParameterDescriptor
+import org.jetbrains.kotlin.descriptors.commonizer.mergedtree.ir.CommonTypeParameter
+import org.jetbrains.kotlin.descriptors.commonizer.mergedtree.ir.TypeParameter
+import org.jetbrains.kotlin.descriptors.commonizer.mockClassType
+import org.jetbrains.kotlin.descriptors.commonizer.mockTypeParameter
+import org.jetbrains.kotlin.name.Name
+import org.jetbrains.kotlin.types.Variance
+import org.jetbrains.kotlin.types.refinement.TypeRefinement
+import org.junit.Test
+
+@TypeRefinement
+class DefaultTypeParameterCommonizerTest : AbstractCommonizerTest