From db3f70cfe966c52fda0bdf85edb600a2b7a292e0 Mon Sep 17 00:00:00 2001 From: Alexander Udalov Date: Thu, 20 Apr 2017 15:33:45 +0300 Subject: [PATCH] Drop unneeded hack relating to matching header class to impl typealias This is not needed anymore because we use a special TypeCheckerContext which correctly matches header class to impl typealias. Also fix 'platformModule' in areCompatibleClassifiers: it's not b's module (b is already the expansion of a typealias), but the module of "other", original 'impl' classifier --- .../checkers/HeaderImplDeclarationChecker.kt | 37 ++++++------------- 1 file changed, 12 insertions(+), 25 deletions(-) diff --git a/compiler/frontend/src/org/jetbrains/kotlin/resolve/checkers/HeaderImplDeclarationChecker.kt b/compiler/frontend/src/org/jetbrains/kotlin/resolve/checkers/HeaderImplDeclarationChecker.kt index 32cdb617387..d887eaf147f 100644 --- a/compiler/frontend/src/org/jetbrains/kotlin/resolve/checkers/HeaderImplDeclarationChecker.kt +++ b/compiler/frontend/src/org/jetbrains/kotlin/resolve/checkers/HeaderImplDeclarationChecker.kt @@ -276,6 +276,7 @@ object HeaderImplDeclarationChecker : DeclarationChecker { a: CallableMemberDescriptor, b: CallableMemberDescriptor, checkImpl: Boolean, + platformModule: ModuleDescriptor = b.module, parentSubstitutor: Substitutor? = null ): Compatibility { assert(a.name == b.name) { "This function should be invoked only for declarations with the same name: $a, $b" } @@ -295,7 +296,6 @@ object HeaderImplDeclarationChecker : DeclarationChecker { val bTypeParams = b.typeParameters if (aTypeParams.size != bTypeParams.size) return Incompatible.TypeParameterCount - val platformModule = b.module val substitutor = Substitutor(aTypeParams, bTypeParams, parentSubstitutor) if (!areCompatibleTypeLists(aParams.map { substitutor(it.type) }, bParams.map { it.type }, platformModule) || @@ -406,23 +406,12 @@ object HeaderImplDeclarationChecker : DeclarationChecker { private fun areCompatibleClassifiers(a: ClassDescriptor, other: ClassifierDescriptor, checkImpl: Boolean): Compatibility { assert(a.fqNameUnsafe == other.fqNameUnsafe) { "This function should be invoked only for declarations with the same name: $a, $other" } - var parentSubstitutor: Substitutor? = null var implTypealias = false - val b = when (other) { is ClassDescriptor -> other is TypeAliasDescriptor -> { - val classDescriptor = other.classDescriptor ?: return Compatible // do not report extra error on erroneous typealias implTypealias = true - // If a header class test.C is implemented by a typealias test.C = test.CImpl, we must now state that any occurrence - // of the type "test.C" in the header class scope should be replaced with "test.CImpl". - // Otherwise the types would not be equal and e.g. test.C's constructor is not going to be found in test.CImpl's scope. - // For this, we construct an additional substitutor with a single mapping test.C -> test.CImpl - // TODO: this looks like a dirty hack - parentSubstitutor = Substitutor(null, TypeSubstitutor.create(TypeConstructorSubstitution.createByConstructorsMap( - mapOf(a.typeConstructor to classDescriptor.defaultType.asTypeProjection()) - ))) - classDescriptor + other.classDescriptor ?: return Compatible // do not report extra error on erroneous typealias } else -> throw AssertionError("Incorrect impl classifier for $a: $other") } @@ -439,8 +428,8 @@ object HeaderImplDeclarationChecker : DeclarationChecker { if (a.visibility != b.visibility) return Incompatible.Visibility - val platformModule = b.module - val substitutor = Substitutor(aTypeParams, bTypeParams, parentSubstitutor) + val platformModule = other.module + val substitutor = Substitutor(aTypeParams, bTypeParams) areCompatibleTypeParameters(aTypeParams, bTypeParams, platformModule, substitutor).let { if (it != Compatible) return it } // Subtract kotlin.Any from supertypes because it's implicitly added if no explicit supertype is specified, @@ -451,7 +440,7 @@ object HeaderImplDeclarationChecker : DeclarationChecker { bSupertypes.none { bSupertype -> areCompatibleTypes(aSupertype, bSupertype, platformModule) } }) return Incompatible.Supertypes - areCompatibleClassScopes(a, b, checkImpl && !implTypealias, substitutor).let { if (it != Compatible) return it } + areCompatibleClassScopes(a, b, checkImpl && !implTypealias, platformModule, substitutor).let { if (it != Compatible) return it } if (checkImpl && !b.isImpl && !implTypealias) return Incompatible.NoImpl @@ -462,6 +451,7 @@ object HeaderImplDeclarationChecker : DeclarationChecker { a: ClassDescriptor, b: ClassDescriptor, checkImpl: Boolean, + platformModule: ModuleDescriptor, substitutor: Substitutor ): Compatibility { val unimplemented = arrayListOf>>>() @@ -472,7 +462,7 @@ object HeaderImplDeclarationChecker : DeclarationChecker { if (!aMember.kind.isReal) continue val mapping = bMembersByName[aMember.name].orEmpty().keysToMap { bMember -> - areCompatibleCallables(aMember, bMember, checkImpl, substitutor) + areCompatibleCallables(aMember, bMember, checkImpl, platformModule, substitutor) } if (mapping.values.any { it == Compatible }) continue @@ -522,18 +512,15 @@ object HeaderImplDeclarationChecker : DeclarationChecker { // This substitutor takes the type from A's signature and returns the type that should be in that place in B's signature private class Substitutor( - private val parent: Substitutor?, - private val typeSubstitutor: TypeSubstitutor + aTypeParams: List, + bTypeParams: List, + private val parent: Substitutor? = null ) : (KotlinType?) -> KotlinType? { - constructor( - aTypeParams: List, - bTypeParams: List, - parent: Substitutor? = null - ) : this(parent, TypeSubstitutor.create( + private val typeSubstitutor = TypeSubstitutor.create( TypeConstructorSubstitution.createByParametersMap(aTypeParams.keysToMap { bTypeParams[it.index].defaultType.asTypeProjection() }) - )) + ) override fun invoke(type: KotlinType?): KotlinType? = (parent?.invoke(type) ?: type)?.asTypeProjection()?.let(typeSubstitutor::substitute)?.type