Optimize and improve AbstractClassTypeConstructor.equals
Instead of computing and comparing FQ names, compare simple names of classes and theirs containers. This code was responsible for creation of about 10% of FqNameUnsafe instances during compilation of "core" modules. Also make the check more strict: previously, a class "c" declared in package "a.b" would be considered equal to a class "c" declared in class "b" in package "a". Because JVM type descriptors of such classes are different, this behavior was suspicious and might have lead to error at runtime. Now, we require the number of containing classes of the given two classes also to be the same
This commit is contained in:
@@ -18,9 +18,7 @@ package org.jetbrains.kotlin.types;
|
||||
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.kotlin.builtins.KotlinBuiltIns;
|
||||
import org.jetbrains.kotlin.descriptors.ClassDescriptor;
|
||||
import org.jetbrains.kotlin.descriptors.ClassifierDescriptor;
|
||||
import org.jetbrains.kotlin.descriptors.DeclarationDescriptor;
|
||||
import org.jetbrains.kotlin.descriptors.*;
|
||||
import org.jetbrains.kotlin.name.FqNameUnsafe;
|
||||
import org.jetbrains.kotlin.resolve.DescriptorUtils;
|
||||
import org.jetbrains.kotlin.resolve.descriptorUtil.DescriptorUtilsKt;
|
||||
@@ -63,7 +61,7 @@ public abstract class AbstractClassTypeConstructor extends AbstractTypeConstruct
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object other) {
|
||||
public final boolean equals(Object other) {
|
||||
if (!(other instanceof TypeConstructor)) return false;
|
||||
|
||||
// performance optimization: getFqName is slow method
|
||||
@@ -86,14 +84,35 @@ public abstract class AbstractClassTypeConstructor extends AbstractTypeConstruct
|
||||
}
|
||||
|
||||
if (myDescriptor instanceof ClassDescriptor && otherDescriptor instanceof ClassDescriptor) {
|
||||
FqNameUnsafe otherFqName = DescriptorUtils.getFqName(otherDescriptor);
|
||||
FqNameUnsafe myFqName = DescriptorUtils.getFqName(myDescriptor);
|
||||
return myFqName.equals(otherFqName);
|
||||
return areFqNamesEqual(((ClassDescriptor) myDescriptor), ((ClassDescriptor) otherDescriptor));
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
private static boolean areFqNamesEqual(ClassDescriptor first, ClassDescriptor second) {
|
||||
if (!first.getName().equals(second.getName())) return false;
|
||||
|
||||
DeclarationDescriptor a = first.getContainingDeclaration();
|
||||
DeclarationDescriptor b = second.getContainingDeclaration();
|
||||
while (a != null && b != null) {
|
||||
if (a instanceof ModuleDescriptor) return b instanceof ModuleDescriptor;
|
||||
if (b instanceof ModuleDescriptor) return false;
|
||||
|
||||
if (a instanceof PackageFragmentDescriptor) {
|
||||
return b instanceof PackageFragmentDescriptor &&
|
||||
((PackageFragmentDescriptor) a).getFqName().equals(((PackageFragmentDescriptor) b).getFqName());
|
||||
}
|
||||
if (b instanceof PackageFragmentDescriptor) return false;
|
||||
|
||||
if (!a.getName().equals(b.getName())) return false;
|
||||
|
||||
a = a.getContainingDeclaration();
|
||||
b = b.getContainingDeclaration();
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
private static boolean hasMeaningfulFqName(@NotNull ClassifierDescriptor descriptor) {
|
||||
return !ErrorUtils.isError(descriptor) &&
|
||||
!DescriptorUtils.isLocal(descriptor);
|
||||
|
||||
Reference in New Issue
Block a user