From bd085fbf43a57d1a9ea93feb2bb95a908410b19b Mon Sep 17 00:00:00 2001 From: Vladimir Dolzhenko Date: Mon, 26 Sep 2022 16:34:20 +0200 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 --- .../lazy/descriptors/LazyJavaClassDescriptor.kt | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-) diff --git a/core/descriptors.jvm/src/org/jetbrains/kotlin/load/java/lazy/descriptors/LazyJavaClassDescriptor.kt b/core/descriptors.jvm/src/org/jetbrains/kotlin/load/java/lazy/descriptors/LazyJavaClassDescriptor.kt index 65ce2e3216f..66069fa93b7 100644 --- a/core/descriptors.jvm/src/org/jetbrains/kotlin/load/java/lazy/descriptors/LazyJavaClassDescriptor.kt +++ b/core/descriptors.jvm/src/org/jetbrains/kotlin/load/java/lazy/descriptors/LazyJavaClassDescriptor.kt @@ -163,7 +163,6 @@ class LazyJavaClassDescriptor( override fun isDefinitelyNotSamInterface(): Boolean { if (kind != 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 @@ -171,7 +170,17 @@ class LazyJavaClassDescriptor( // 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