From d6e587171e5086776cbcb1a6314174143fe6909b Mon Sep 17 00:00:00 2001 From: Vladimir Dolzhenko Date: Tue, 3 Jan 2023 14:08:18 +0100 Subject: [PATCH] Optimize isDefinitelyNotSamInterface Do not generate intermediate garbage and no reason to iterate over all non-SAM candidates when more than one found #KTIJ-23032 --- .../descriptors/SyntheticJavaClassDescriptor.kt | 14 ++++++++++++-- 1 file changed, 12 insertions(+), 2 deletions(-) diff --git a/core/descriptors.jvm/src/org/jetbrains/kotlin/load/java/lazy/descriptors/SyntheticJavaClassDescriptor.kt b/core/descriptors.jvm/src/org/jetbrains/kotlin/load/java/lazy/descriptors/SyntheticJavaClassDescriptor.kt index 875d91ada14..22a65668086 100644 --- a/core/descriptors.jvm/src/org/jetbrains/kotlin/load/java/lazy/descriptors/SyntheticJavaClassDescriptor.kt +++ b/core/descriptors.jvm/src/org/jetbrains/kotlin/load/java/lazy/descriptors/SyntheticJavaClassDescriptor.kt @@ -105,7 +105,6 @@ class SyntheticJavaClassDescriptor( override fun isDefinitelyNotSamInterface(): Boolean { if (classKind != ClassKind.INTERFACE) return true - val candidates = jClass.methods.filter { it.isAbstract && it.typeParameters.isEmpty() } // From the definition of function interfaces in the Java specification (pt. 9.8): // "methods that are members of I that do not have the same signature as any public instance method of the class Object" // It means that if an interface declares `int hashCode()` then the method won't be taken into account when @@ -113,7 +112,18 @@ class SyntheticJavaClassDescriptor( // We make here a conservative check just filtering out methods by name. // If we ignore a method with wrong signature (different from one in Object) it's not very bad, // we'll just say that the interface MAY BE a SAM when it's not and then more detailed check will be applied. - if (candidates.count { it.name.identifier !in PUBLIC_METHOD_NAMES_IN_OBJECT } > 1) return true + var foundSamMethod = false + for (method in jClass.methods) { + if (method.isAbstract && method.typeParameters.isEmpty() && + method.name.identifier !in PUBLIC_METHOD_NAMES_IN_OBJECT + ) { + // found 2nd method candidate + if (foundSamMethod) { + return true + } + foundSamMethod = true + } + } // If we have default methods the interface could be a SAM even while a super interface has more than one abstract method if (jClass.methods.any { !it.isAbstract && it.typeParameters.isEmpty() }) return false