Extract some logic from AbstractTypeConstructor to reuse it later
In FE10-binding I would like to re-use equal and hashCode mechanics that was implemented in AbstractTypeConstructor, but I don't need the supertype implementation, because it already there in FIR
This commit is contained in:
@@ -24,13 +24,9 @@ import org.jetbrains.kotlin.types.checker.KotlinTypeRefiner
|
|||||||
import org.jetbrains.kotlin.types.checker.refineTypes
|
import org.jetbrains.kotlin.types.checker.refineTypes
|
||||||
import org.jetbrains.kotlin.types.refinement.TypeRefinement
|
import org.jetbrains.kotlin.types.refinement.TypeRefinement
|
||||||
|
|
||||||
abstract class AbstractTypeConstructor(storageManager: StorageManager) : TypeConstructor {
|
abstract class AbstractTypeConstructor(storageManager: StorageManager) : ClassifierBasedTypeConstructor() {
|
||||||
private var hashCode = 0
|
|
||||||
|
|
||||||
override fun getSupertypes() = supertypes().supertypesWithoutCycles
|
override fun getSupertypes() = supertypes().supertypesWithoutCycles
|
||||||
|
|
||||||
abstract override fun getDeclarationDescriptor(): ClassifierDescriptor
|
|
||||||
|
|
||||||
@TypeRefinement
|
@TypeRefinement
|
||||||
override fun refine(kotlinTypeRefiner: KotlinTypeRefiner): TypeConstructor = ModuleViewTypeConstructor(kotlinTypeRefiner)
|
override fun refine(kotlinTypeRefiner: KotlinTypeRefiner): TypeConstructor = ModuleViewTypeConstructor(kotlinTypeRefiner)
|
||||||
|
|
||||||
@@ -134,65 +130,4 @@ abstract class AbstractTypeConstructor(storageManager: StorageManager) : TypeCon
|
|||||||
// Only for debugging
|
// Only for debugging
|
||||||
fun renderAdditionalDebugInformation(): String = "supertypes=${supertypes.renderDebugInformation()}"
|
fun renderAdditionalDebugInformation(): String = "supertypes=${supertypes.renderDebugInformation()}"
|
||||||
|
|
||||||
override fun hashCode(): Int {
|
|
||||||
val cachedHashCode = hashCode
|
|
||||||
if (cachedHashCode != 0) return cachedHashCode
|
|
||||||
|
|
||||||
val descriptor = declarationDescriptor
|
|
||||||
val computedHashCode = if (hasMeaningfulFqName(descriptor)) {
|
|
||||||
DescriptorUtils.getFqName(descriptor).hashCode()
|
|
||||||
} else {
|
|
||||||
System.identityHashCode(this)
|
|
||||||
}
|
|
||||||
|
|
||||||
return computedHashCode.also { hashCode = it }
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun equals(other: Any?): Boolean {
|
|
||||||
if (this === other) return true
|
|
||||||
if (other !is TypeConstructor) return false
|
|
||||||
|
|
||||||
// performance optimization: getFqName is slow method
|
|
||||||
// Cast to Any is needed as a workaround for KT-45008.
|
|
||||||
if ((other as Any).hashCode() != hashCode()) return false
|
|
||||||
|
|
||||||
// Sometimes we can get two classes from different modules with different counts of type parameters.
|
|
||||||
// To avoid problems in type checker we suppose that it is different type constructors.
|
|
||||||
if (other.parameters.size != parameters.size) return false
|
|
||||||
|
|
||||||
val myDescriptor = declarationDescriptor
|
|
||||||
val otherDescriptor = other.declarationDescriptor ?: return false
|
|
||||||
if (!hasMeaningfulFqName(myDescriptor) || !hasMeaningfulFqName(otherDescriptor)) {
|
|
||||||
// All error types and local classes have the same descriptor,
|
|
||||||
// but we've already checked identity equality in the beginning of the method
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
|
|
||||||
return isSameClassifier(otherDescriptor)
|
|
||||||
}
|
|
||||||
|
|
||||||
protected abstract fun isSameClassifier(classifier: ClassifierDescriptor): Boolean
|
|
||||||
|
|
||||||
protected fun areFqNamesEqual(first: ClassifierDescriptor, second: ClassifierDescriptor): Boolean {
|
|
||||||
if (first.name != second.name) return false
|
|
||||||
var a: DeclarationDescriptor? = first.containingDeclaration
|
|
||||||
var b: DeclarationDescriptor? = second.containingDeclaration
|
|
||||||
while (a != null && b != null) {
|
|
||||||
when {
|
|
||||||
a is ModuleDescriptor -> return b is ModuleDescriptor
|
|
||||||
b is ModuleDescriptor -> return false
|
|
||||||
a is PackageFragmentDescriptor -> return b is PackageFragmentDescriptor && a.fqName == b.fqName
|
|
||||||
b is PackageFragmentDescriptor -> return false
|
|
||||||
a.name != b.name -> return false
|
|
||||||
else -> {
|
|
||||||
a = a.containingDeclaration
|
|
||||||
b = b.containingDeclaration
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun hasMeaningfulFqName(descriptor: ClassifierDescriptor): Boolean =
|
|
||||||
!ErrorUtils.isError(descriptor) && !DescriptorUtils.isLocal(descriptor)
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,80 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2010-2021 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.types
|
||||||
|
|
||||||
|
import org.jetbrains.kotlin.descriptors.ClassifierDescriptor
|
||||||
|
import org.jetbrains.kotlin.descriptors.DeclarationDescriptor
|
||||||
|
import org.jetbrains.kotlin.descriptors.ModuleDescriptor
|
||||||
|
import org.jetbrains.kotlin.descriptors.PackageFragmentDescriptor
|
||||||
|
import org.jetbrains.kotlin.resolve.DescriptorUtils
|
||||||
|
|
||||||
|
abstract class ClassifierBasedTypeConstructor : TypeConstructor {
|
||||||
|
private var hashCode = 0
|
||||||
|
|
||||||
|
abstract override fun getDeclarationDescriptor(): ClassifierDescriptor
|
||||||
|
|
||||||
|
override fun hashCode(): Int {
|
||||||
|
val cachedHashCode = hashCode
|
||||||
|
if (cachedHashCode != 0) return cachedHashCode
|
||||||
|
|
||||||
|
val descriptor = declarationDescriptor
|
||||||
|
val computedHashCode = if (hasMeaningfulFqName(descriptor)) {
|
||||||
|
DescriptorUtils.getFqName(descriptor).hashCode()
|
||||||
|
} else {
|
||||||
|
System.identityHashCode(this)
|
||||||
|
}
|
||||||
|
|
||||||
|
return computedHashCode.also { hashCode = it }
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun equals(other: Any?): Boolean {
|
||||||
|
if (this === other) return true
|
||||||
|
if (other !is TypeConstructor) return false
|
||||||
|
|
||||||
|
// performance optimization: getFqName is slow method
|
||||||
|
// Cast to Any is needed as a workaround for KT-45008.
|
||||||
|
if ((other as Any).hashCode() != hashCode()) return false
|
||||||
|
|
||||||
|
// Sometimes we can get two classes from different modules with different counts of type parameters.
|
||||||
|
// To avoid problems in type checker we suppose that it is different type constructors.
|
||||||
|
if (other.parameters.size != parameters.size) return false
|
||||||
|
|
||||||
|
val myDescriptor = declarationDescriptor
|
||||||
|
val otherDescriptor = other.declarationDescriptor ?: return false
|
||||||
|
if (!hasMeaningfulFqName(myDescriptor) || !hasMeaningfulFqName(otherDescriptor)) {
|
||||||
|
// All error types and local classes have the same descriptor,
|
||||||
|
// but we've already checked identity equality in the beginning of the method
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
return isSameClassifier(otherDescriptor)
|
||||||
|
}
|
||||||
|
|
||||||
|
protected abstract fun isSameClassifier(classifier: ClassifierDescriptor): Boolean
|
||||||
|
|
||||||
|
protected fun areFqNamesEqual(first: ClassifierDescriptor, second: ClassifierDescriptor): Boolean {
|
||||||
|
if (first.name != second.name) return false
|
||||||
|
var a: DeclarationDescriptor? = first.containingDeclaration
|
||||||
|
var b: DeclarationDescriptor? = second.containingDeclaration
|
||||||
|
while (a != null && b != null) {
|
||||||
|
when {
|
||||||
|
a is ModuleDescriptor -> return b is ModuleDescriptor
|
||||||
|
b is ModuleDescriptor -> return false
|
||||||
|
a is PackageFragmentDescriptor -> return b is PackageFragmentDescriptor && a.fqName == b.fqName
|
||||||
|
b is PackageFragmentDescriptor -> return false
|
||||||
|
a.name != b.name -> return false
|
||||||
|
else -> {
|
||||||
|
a = a.containingDeclaration
|
||||||
|
b = b.containingDeclaration
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun hasMeaningfulFqName(descriptor: ClassifierDescriptor): Boolean =
|
||||||
|
!ErrorUtils.isError(descriptor) && !DescriptorUtils.isLocal(descriptor)
|
||||||
|
}
|
||||||
@@ -610,7 +610,7 @@ interface ClassicTypeSystemContext : TypeSystemInferenceExtensionContext, TypeSy
|
|||||||
}
|
}
|
||||||
|
|
||||||
override fun TypeConstructorMarker.isTypeParameterTypeConstructor(): Boolean {
|
override fun TypeConstructorMarker.isTypeParameterTypeConstructor(): Boolean {
|
||||||
return this is AbstractTypeConstructor && this.declarationDescriptor is AbstractTypeParameterDescriptor
|
return this is ClassifierBasedTypeConstructor && this.declarationDescriptor is AbstractTypeParameterDescriptor
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun arrayType(componentType: KotlinTypeMarker): SimpleTypeMarker {
|
override fun arrayType(componentType: KotlinTypeMarker): SimpleTypeMarker {
|
||||||
|
|||||||
Reference in New Issue
Block a user