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
This commit is contained in:
Alexander Udalov
2016-10-19 11:44:50 +03:00
parent 08398178e0
commit a5a422fc4d
@@ -93,7 +93,7 @@ class CollectionStubMethodGenerator(
// to construct the needed MutableCollection type. Since getAllSupertypes() may return several types which correspond to the // 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) // 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 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(parentType)
child.addSupertype(mutableCollectionType) child.addSupertype(mutableCollectionType)
@@ -105,7 +105,7 @@ class CollectionStubMethodGenerator(
if (method.modality == Modality.ABSTRACT || isDefaultInJdk(method)) { 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 // 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 // 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 // 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 // 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( private data class CollectionClassPair(
val readOnlyClass: ClassDescriptor, val readOnlyClass: TypeConstructor,
val mutableClass: ClassDescriptor val mutableClass: TypeConstructor
) )
private fun findRelevantSuperCollectionClasses(): Collection<CollectionClassPair> { private fun findRelevantSuperCollectionClasses(): Collection<CollectionClassPair> {
fun pair(readOnlyClass: ClassDescriptor, mutableClass: ClassDescriptor) = CollectionClassPair(readOnlyClass, mutableClass) fun pair(readOnlyClass: TypeConstructor, mutableClass: TypeConstructor) = CollectionClassPair(readOnlyClass, mutableClass)
val collectionClasses = with(descriptor.builtIns) { val collectionClasses = with(descriptor.builtIns) {
listOf( listOf(
pair(collection, mutableCollection), collection to mutableCollection,
pair(set, mutableSet), set to mutableSet,
pair(list, mutableList), list to mutableList,
pair(map, mutableMap), map to mutableMap,
pair(mapEntry, mutableMapEntry), mapEntry to mutableMapEntry,
pair(iterable, mutableIterable), iterable to mutableIterable,
pair(iterator, mutableIterator), iterator to mutableIterator,
pair(listIterator, mutableListIterator) 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) -> val ourSuperCollectionClasses = collectionClasses.filter { (readOnlyClass, mutableClass) ->
readOnlyClass in allSuperClasses && mutableClass !in allSuperClasses 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. // 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<ClassDescriptor>()) { (readOnlyClass) -> val redundantClasses = ourSuperCollectionClasses.flatMapTo(HashSet()) { (readOnlyClass) ->
readOnlyClass.typeConstructor.supertypes.classes() readOnlyClass.supertypes.map(KotlinType::constructor)
} }
return ourSuperCollectionClasses.filter { (readOnlyClass) -> readOnlyClass !in redundantClasses } return ourSuperCollectionClasses.filter { (readOnlyClass) -> readOnlyClass !in redundantClasses }
} }
private fun Collection<KotlinType>.classes(): Collection<ClassDescriptor> =
this.map { it.constructor.declarationDescriptor as ClassDescriptor }
private fun findFakeOverridesForMethodsFromMutableCollection( private fun findFakeOverridesForMethodsFromMutableCollection(
klass: ClassDescriptor, klass: ClassDescriptor,
mutableCollectionClass: ClassDescriptor mutableCollectionTypeConstructor: TypeConstructor
): List<FunctionDescriptor> { ): List<FunctionDescriptor> {
val result = ArrayList<FunctionDescriptor>() val result = ArrayList<FunctionDescriptor>()
generateOverridesInAClass(klass, object : NonReportingOverrideStrategy() { generateOverridesInAClass(klass, object : NonReportingOverrideStrategy() {
override fun addFakeOverride(fakeOverride: CallableMemberDescriptor) { override fun addFakeOverride(fakeOverride: CallableMemberDescriptor) {
if (fakeOverride !is FunctionDescriptor) return if (fakeOverride !is FunctionDescriptor) return
val foundOverriddenFromDirectSuperClass = fakeOverride.findOverriddenFromDirectSuperClass(mutableCollectionClass) ?: return val foundOverriddenFromDirectSuperClass = fakeOverride.findOverriddenFromDirectSuperClass(mutableCollectionTypeConstructor) ?: return
if (foundOverriddenFromDirectSuperClass.kind == DECLARATION) { if (foundOverriddenFromDirectSuperClass.kind == DECLARATION) {
// For regular classes there should no be fake overrides having return types incompatible with return types of their // 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<E>` // overridden, while here it's possible to create declaration like `fun remove(e: E): ImmutableCollection<E>`
@@ -284,9 +283,9 @@ class CollectionStubMethodGenerator(
return result return result
} }
private fun Collection<KotlinType>.findMostSpecificTypeForClass(klass: ClassDescriptor): KotlinType { private fun Collection<KotlinType>.findMostSpecificTypeForClass(typeConstructor: TypeConstructor): KotlinType {
val types = this.filter { it.constructor.declarationDescriptor == klass } val types = this.filter { it.constructor == typeConstructor }
if (types.isEmpty()) error("No supertype of $klass in $this") if (types.isEmpty()) error("No supertype of $typeConstructor in $this")
if (types.size == 1) return types.first() 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 // Find the first type in the list such that it's a subtype of every other type in that list
return types.first { type -> return types.first { type ->
@@ -320,9 +319,10 @@ class CollectionStubMethodGenerator(
return Pair(child, newTypeParameters) return Pair(child, newTypeParameters)
} }
private fun FunctionDescriptor.findOverriddenFromDirectSuperClass(classDescriptor: ClassDescriptor): FunctionDescriptor? { private fun FunctionDescriptor.findOverriddenFromDirectSuperClass(typeConstructor: TypeConstructor): FunctionDescriptor? =
return this.overriddenDescriptors.firstOrNull { it.containingDeclaration == classDescriptor } this.overriddenDescriptors.firstOrNull {
} (it.containingDeclaration as? ClassDescriptor)?.typeConstructor == typeConstructor
}
private fun newType(classDescriptor: ClassDescriptor, typeArguments: List<TypeProjection>): KotlinType { private fun newType(classDescriptor: ClassDescriptor, typeArguments: List<TypeProjection>): KotlinType {
return KotlinTypeFactory.simpleNotNullType(Annotations.EMPTY, classDescriptor, typeArguments) return KotlinTypeFactory.simpleNotNullType(Annotations.EMPTY, classDescriptor, typeArguments)