From a5a422fc4d8e93a2b70d7df14cc150508379fdbd Mon Sep 17 00:00:00 2001 From: Alexander Udalov Date: Wed, 19 Oct 2016 11:44:50 +0300 Subject: [PATCH] Use TypeConstructor equality instead of ClassDescriptor in CollectionStubMethodGenerator Equals/hashCode are meaningful for TypeConstructor instances (see AbstractClassTypeConstructor.java) in contrast to ClassDescriptor where equality is referential --- .../codegen/CollectionStubMethodGenerator.kt | 58 +++++++++---------- 1 file changed, 29 insertions(+), 29 deletions(-) diff --git a/compiler/backend/src/org/jetbrains/kotlin/codegen/CollectionStubMethodGenerator.kt b/compiler/backend/src/org/jetbrains/kotlin/codegen/CollectionStubMethodGenerator.kt index b12ce34ce58..34202455858 100644 --- a/compiler/backend/src/org/jetbrains/kotlin/codegen/CollectionStubMethodGenerator.kt +++ b/compiler/backend/src/org/jetbrains/kotlin/codegen/CollectionStubMethodGenerator.kt @@ -93,7 +93,7 @@ class CollectionStubMethodGenerator( // to construct the needed MutableCollection type. Since getAllSupertypes() may return several types which correspond to the // Collection class descriptor, we find the most specific one (which is guaranteed to exist by front-end) val readOnlyCollectionType = TypeUtils.getAllSupertypes(parentType).findMostSpecificTypeForClass(readOnlyClass) - val mutableCollectionType = newType(mutableClass, readOnlyCollectionType.arguments) + val mutableCollectionType = newType(mutableClass.declarationDescriptor as ClassDescriptor, readOnlyCollectionType.arguments) child.addSupertype(parentType) child.addSupertype(mutableCollectionType) @@ -105,7 +105,7 @@ class CollectionStubMethodGenerator( if (method.modality == Modality.ABSTRACT || isDefaultInJdk(method)) { // If the fake override is abstract and it's _declared_ as abstract in the class, skip it because the method is already // present in the bytecode (abstract) and we don't want a duplicate signature error - if (method.findOverriddenFromDirectSuperClass(descriptor)?.kind == DECLARATION) continue + if (method.findOverriddenFromDirectSuperClass(descriptor.typeConstructor)?.kind == DECLARATION) continue // If the substituted signature differs from the original one in MutableCollection, we should also generate a stub with // the original (erased) signature. It doesn't really matter if this is a bridge method delegating to the first stub or @@ -195,53 +195,52 @@ class CollectionStubMethodGenerator( } private data class CollectionClassPair( - val readOnlyClass: ClassDescriptor, - val mutableClass: ClassDescriptor + val readOnlyClass: TypeConstructor, + val mutableClass: TypeConstructor ) private fun findRelevantSuperCollectionClasses(): Collection { - fun pair(readOnlyClass: ClassDescriptor, mutableClass: ClassDescriptor) = CollectionClassPair(readOnlyClass, mutableClass) + fun pair(readOnlyClass: TypeConstructor, mutableClass: TypeConstructor) = CollectionClassPair(readOnlyClass, mutableClass) val collectionClasses = with(descriptor.builtIns) { listOf( - pair(collection, mutableCollection), - pair(set, mutableSet), - pair(list, mutableList), - pair(map, mutableMap), - pair(mapEntry, mutableMapEntry), - pair(iterable, mutableIterable), - pair(iterator, mutableIterator), - pair(listIterator, mutableListIterator) - ) + collection to mutableCollection, + set to mutableSet, + list to mutableList, + map to mutableMap, + mapEntry to mutableMapEntry, + iterable to mutableIterable, + iterator to mutableIterator, + listIterator to mutableListIterator + ).map { (readOnly, mutable) -> + pair(readOnly.typeConstructor, mutable.typeConstructor) + } } - val allSuperClasses = TypeUtils.getAllSupertypes(descriptor.defaultType).classes().toHashSet() + val allSuperClasses = TypeUtils.getAllSupertypes(descriptor.defaultType).mapTo(HashSet(), KotlinType::constructor) val ourSuperCollectionClasses = collectionClasses.filter { (readOnlyClass, mutableClass) -> readOnlyClass in allSuperClasses && mutableClass !in allSuperClasses } - if (ourSuperCollectionClasses.isEmpty()) return listOf() + if (ourSuperCollectionClasses.isEmpty()) return emptySet() // Filter out built-in classes which are overridden by other built-in classes in the list, to avoid duplicating methods. - val redundantClasses = ourSuperCollectionClasses.flatMapTo(HashSet()) { (readOnlyClass) -> - readOnlyClass.typeConstructor.supertypes.classes() + val redundantClasses = ourSuperCollectionClasses.flatMapTo(HashSet()) { (readOnlyClass) -> + readOnlyClass.supertypes.map(KotlinType::constructor) } return ourSuperCollectionClasses.filter { (readOnlyClass) -> readOnlyClass !in redundantClasses } } - private fun Collection.classes(): Collection = - this.map { it.constructor.declarationDescriptor as ClassDescriptor } - private fun findFakeOverridesForMethodsFromMutableCollection( klass: ClassDescriptor, - mutableCollectionClass: ClassDescriptor + mutableCollectionTypeConstructor: TypeConstructor ): List { val result = ArrayList() generateOverridesInAClass(klass, object : NonReportingOverrideStrategy() { override fun addFakeOverride(fakeOverride: CallableMemberDescriptor) { if (fakeOverride !is FunctionDescriptor) return - val foundOverriddenFromDirectSuperClass = fakeOverride.findOverriddenFromDirectSuperClass(mutableCollectionClass) ?: return + val foundOverriddenFromDirectSuperClass = fakeOverride.findOverriddenFromDirectSuperClass(mutableCollectionTypeConstructor) ?: return if (foundOverriddenFromDirectSuperClass.kind == DECLARATION) { // For regular classes there should no be fake overrides having return types incompatible with return types of their // overridden, while here it's possible to create declaration like `fun remove(e: E): ImmutableCollection` @@ -284,9 +283,9 @@ class CollectionStubMethodGenerator( return result } - private fun Collection.findMostSpecificTypeForClass(klass: ClassDescriptor): KotlinType { - val types = this.filter { it.constructor.declarationDescriptor == klass } - if (types.isEmpty()) error("No supertype of $klass in $this") + private fun Collection.findMostSpecificTypeForClass(typeConstructor: TypeConstructor): KotlinType { + val types = this.filter { it.constructor == typeConstructor } + if (types.isEmpty()) error("No supertype of $typeConstructor in $this") if (types.size == 1) return types.first() // Find the first type in the list such that it's a subtype of every other type in that list return types.first { type -> @@ -320,9 +319,10 @@ class CollectionStubMethodGenerator( return Pair(child, newTypeParameters) } - private fun FunctionDescriptor.findOverriddenFromDirectSuperClass(classDescriptor: ClassDescriptor): FunctionDescriptor? { - return this.overriddenDescriptors.firstOrNull { it.containingDeclaration == classDescriptor } - } + private fun FunctionDescriptor.findOverriddenFromDirectSuperClass(typeConstructor: TypeConstructor): FunctionDescriptor? = + this.overriddenDescriptors.firstOrNull { + (it.containingDeclaration as? ClassDescriptor)?.typeConstructor == typeConstructor + } private fun newType(classDescriptor: ClassDescriptor, typeArguments: List): KotlinType { return KotlinTypeFactory.simpleNotNullType(Annotations.EMPTY, classDescriptor, typeArguments)