~~ DO NOT MERGE: Refactoring of the processFunctionsByName
diff --git a/compiler/fir/java/src/org/jetbrains/kotlin/fir/java/scopes/JavaClassUseSiteMemberScope.kt b/compiler/fir/java/src/org/jetbrains/kotlin/fir/java/scopes/JavaClassUseSiteMemberScope.kt
index e2fe00a..6e4bd24 100644
--- a/compiler/fir/java/src/org/jetbrains/kotlin/fir/java/scopes/JavaClassUseSiteMemberScope.kt
+++ b/compiler/fir/java/src/org/jetbrains/kotlin/fir/java/scopes/JavaClassUseSiteMemberScope.kt
@@ -346,11 +346,9 @@
     private fun FirNamedFunctionSymbol.doesOverrideRenamedBuiltins(): Boolean {
         // e.g. 'removeAt' or 'toInt'
         val builtinName = SpecialGenericSignatures.getBuiltinFunctionNamesByJvmName(name) ?: return false
-        val builtinSpecialFromSuperTypes = supertypeScopeContext.collectFunctions(builtinName)
-            .flatMap { result ->
-                result.overriddenMembers.filter { (symbol, scope) ->
-                    symbol.doesOverrideBuiltinWithDifferentJvmName(scope, session)
-                }.map { it.member }
+        val builtinSpecialFromSuperTypes = supertypeScopeContext.collectMembersGroupedByScope(builtinName, FirScope::processFunctionsByName)
+            .flatMap { (scope, symbols) ->
+                symbols.filter { it.doesOverrideBuiltinWithDifferentJvmName(scope, session) }
             }
         if (builtinSpecialFromSuperTypes.isEmpty()) return false
 
@@ -388,7 +386,7 @@
      */
     private fun FirNamedFunctionSymbol.shouldBeVisibleAsOverrideOfBuiltInWithErasedValueParameters(): Boolean {
         if (!name.sameAsBuiltinMethodWithErasedValueParameters) return false
-        val candidatesToOverride = supertypeScopeContext.collectFunctions(name)
+        val candidatesToOverride = supertypeScopeContext.collectIntersectionResultsForCallables(name, FirScope::processFunctionsByName)
             .flatMap { it.overriddenMembers }
             .filterNot { (member, _) ->
                 member.valueParameterSymbols.all { it.resolvedReturnType.lowerBoundIfFlexible().isAny }
@@ -432,7 +430,7 @@
         collectDeclaredFunctions(name, result)
         val explicitlyDeclaredFunctions = result.toSet()
 
-        val functionsWithScopeFromSupertypes = supertypeScopeContext.collectFunctions(name).map { it.overriddenMembers.first().baseScope to listOf(it.chosenSymbol) }
+        val functionsWithScopeFromSupertypes = supertypeScopeContext.collectMembersGroupedByScope(name, FirScope::processFunctionsByName)
 
         if (
             !name.sameAsRenamedInJvmBuiltin &&
diff --git a/compiler/fir/java/src/org/jetbrains/kotlin/fir/scopes/jvm/JvmMappedScope.kt b/compiler/fir/java/src/org/jetbrains/kotlin/fir/scopes/jvm/JvmMappedScope.kt
index a193e25..ed1df87 100644
--- a/compiler/fir/java/src/org/jetbrains/kotlin/fir/scopes/jvm/JvmMappedScope.kt
+++ b/compiler/fir/java/src/org/jetbrains/kotlin/fir/scopes/jvm/JvmMappedScope.kt
@@ -116,79 +116,81 @@
         }
     }
 
-    override fun collectFunctionsByName(name: Name): List<FirNamedFunctionSymbol> {
+    override fun collectFunctionsByName(name: Name): List<FirNamedFunctionSymbol>  {
         val result = mutableListOf<FirNamedFunctionSymbol>()
-
-        // Collect declared functions
-        val declared = declaredMemberScope.collectFunctionsByName(name).filter { symbol ->
-            !filterOutJvmPlatformDeclarations || FirJvmPlatformDeclarationFilter.isFunctionAvailable(
-                symbol.fir,
-                javaMappedClassUseSiteScope,
-                session
-            )
+        val declared = mutableListOf<FirNamedFunctionSymbol>()
+        declaredMemberScope.processFunctionsByName(name) { symbol ->
+            if (!filterOutJvmPlatformDeclarations || FirJvmPlatformDeclarationFilter.isFunctionAvailable(
+                    symbol.fir,
+                    javaMappedClassUseSiteScope,
+                    session
+                )
+            ) {
+                declared += symbol
+                result.add(symbol)
+            }
         }
-        result.addAll(declared)
 
-        // Collect declared signatures
-        val declaredSignatures = buildSet {
-            declared.mapTo(this) { it.fir.computeJvmDescriptor() }
-            declaredScopeOfMutableVersion?.collectFunctionsByName(name)?.forEach {
-                add(it.fir.computeJvmDescriptor())
+        val declaredSignatures: Set<String> by lazy {
+            buildSet {
+                declared.mapTo(this) { it.fir.computeJvmDescriptor() }
+                declaredScopeOfMutableVersion?.processFunctionsByName(name) {
+                    add(it.fir.computeJvmDescriptor())
+                }
             }
         }
 
         var needsHiddenFake = isList && (name == GET_FIRST_NAME || name == GET_LAST_NAME)
 
-        // Process Java mapped functions
-        javaMappedClassUseSiteScope.collectFunctionsByName(name)
-            .filter { symbol ->
-                symbol.isDeclaredInMappedJavaClass() && 
-                (symbol.fir.status as FirResolvedDeclarationStatus).visibility.isPublicAPI
-            }
-            .forEach { symbol ->
-                val jvmDescriptor = symbol.fir.computeJvmDescriptor()
-
-                // Skip if already declared or special cases
-                if (jvmDescriptor in declaredSignatures ||
-                    isRenamedJdkMethod(jvmDescriptor) ||
-                    symbol.isOverrideOfKotlinBuiltinPropertyGetter() ||
-                    isOverrideOfKotlinDeclaredFunction(symbol) ||
-                    isMutabilityViolation(symbol, jvmDescriptor)
-                ) {
-                    return@forEach
-                }
-
-                val jdkMemberStatus = getJdkMethodStatus(jvmDescriptor)
-
-                // Skip based on JDK member status
-                if (jdkMemberStatus == JDKMemberStatus.DROP ||
-                    ((jdkMemberStatus == JDKMemberStatus.HIDDEN || jdkMemberStatus == JDKMemberStatus.HIDDEN_IN_DECLARING_CLASS_ONLY) && firKotlinClass.isFinal)
-                ) {
-                    return@forEach
-                }
-
-                val newSymbol = mappedSymbolCache.mappedFunctions.getValue(symbol, this to jdkMemberStatus)
-
-                if (needsHiddenFake &&
-                    allJavaMappedSuperClassIds.any {
-                        SignatureBuildingComponents.signature(it, jvmDescriptor) in JvmBuiltInsSignatures.DEPRECATED_LIST_METHODS
-                    }
-                ) {
-                    needsHiddenFake = false
-                }
-
-                result.add(newSymbol)
+        javaMappedClassUseSiteScope.processFunctionsByName(name) processor@{ symbol ->
+            if (!symbol.isDeclaredInMappedJavaClass() || !(symbol.fir.status as FirResolvedDeclarationStatus).visibility.isPublicAPI) {
+                return@processor
             }
 
-        if (needsHiddenFake) {
-            // Add hidden fake function for List methods in JDK < 21
-            result.add(mappedSymbolCache.hiddenFakeFunctions.getValue(name, this))
+            val jvmDescriptor = symbol.fir.computeJvmDescriptor()
+            // We don't need adding what is already declared
+            if (jvmDescriptor in declaredSignatures) return@processor
+
+            // That condition means that the member is already declared in the built-in class, but has a non-trivially mapped JVM descriptor
+            if (isRenamedJdkMethod(jvmDescriptor) || symbol.isOverrideOfKotlinBuiltinPropertyGetter()) return@processor
+
+            // If it's java.lang.List.contains(Object) it being loaded as contains(E) and treated as an override
+            // of kotlin.collections.Collection.contains(E), thus we're not loading it as an additional JDK member
+            if (isOverrideOfKotlinDeclaredFunction(symbol)) return@processor
+
+            if (isMutabilityViolation(symbol, jvmDescriptor)) return@processor
+
+            val jdkMemberStatus = getJdkMethodStatus(jvmDescriptor)
+
+            if (jdkMemberStatus == JDKMemberStatus.DROP) return@processor
+            // hidden methods in final class can't be overridden or called with 'super'
+            if ((jdkMemberStatus == JDKMemberStatus.HIDDEN || jdkMemberStatus == JDKMemberStatus.HIDDEN_IN_DECLARING_CLASS_ONLY) && firKotlinClass.isFinal) return@processor
+
+            val newSymbol = mappedSymbolCache.mappedFunctions.getValue(symbol, this to jdkMemberStatus)
+
+            if (needsHiddenFake &&
+                allJavaMappedSuperClassIds.any {
+                    SignatureBuildingComponents.signature(it, jvmDescriptor) in JvmBuiltInsSignatures.DEPRECATED_LIST_METHODS
+                }
+            ) {
+                needsHiddenFake = false
+            }
+
+            result.add(newSymbol)
         }
 
+        if (needsHiddenFake) {
+            // We're in JDK < 21, i.e., getFirst/getLast don't exist in the List interface yet.
+            // We create a fake version of them for the sole purpose of reporting deprecations on to-become-overrides like in LinkedList.
+            // This is because we want to rename these two methods in the future,
+            // and we want to warn users of older JDKs of a potential breaking change caused by upgrading to JDK >= 21.
+            // See KT-65440.
+            val fakeSymbol = mappedSymbolCache.hiddenFakeFunctions.getValue(name, this)
+            result.add(fakeSymbol)
+        }
         return result
     }
 
-
     private fun createHiddenFakeFunction(name: Name): FirNamedFunctionSymbol {
         return buildSimpleFunction {
             moduleData = firKotlinClass.moduleData
diff --git a/compiler/fir/providers/src/org/jetbrains/kotlin/fir/resolve/calls/Synthetics.kt b/compiler/fir/providers/src/org/jetbrains/kotlin/fir/resolve/calls/Synthetics.kt
index 9911ae1..5d4f341 100644
--- a/compiler/fir/providers/src/org/jetbrains/kotlin/fir/resolve/calls/Synthetics.kt
+++ b/compiler/fir/providers/src/org/jetbrains/kotlin/fir/resolve/calls/Synthetics.kt
@@ -74,13 +74,13 @@
         val getterNames = syntheticNamesProvider.possibleGetterNamesByPropertyName(name)
         var getterFound = false
         for (getterName in getterNames) {
-            baseScope.collectFunctionsByName(getterName).forEach {
+            baseScope.processFunctionsByName(getterName) {
                 checkGetAndCreateSynthetic(name, getterName, it, needCheckForSetter = true, processor)
                 getterFound = true
             }
         }
         if (!getterFound && shouldSearchForJavaRecordComponents()) {
-            baseScope.collectFunctionsByName(name).forEach {
+            baseScope.processFunctionsByName(name) {
                 if (it.fir.isJavaRecordComponent == true) {
                     checkGetAndCreateSynthetic(name, name, it, needCheckForSetter = false, processor)
                 }
@@ -136,16 +136,17 @@
         var matchingSetter: FirSimpleFunction? = null
         if (needCheckForSetter && getterReturnType != null) {
             val setterName = syntheticNamesProvider.setterNameByGetterName(getterName)
-            baseScope.collectFunctionsByName(setterName).forEach { setterSymbol ->
-                if (matchingSetter != null) return@forEach
+            baseScope.processFunctionsByName(setterName, fun(setterSymbol: FirNamedFunctionSymbol) {
+                if (matchingSetter != null) return
 
                 val setter = setterSymbol.fir
-                if (setter.typeParameters.isNotEmpty() || setter.isStatic) return@forEach
-                val parameter = setter.valueParameters.singleOrNull() ?: return@forEach
-                val parameterType = (parameter.returnTypeRef as? FirResolvedTypeRef)?.coneType ?: return@forEach
-                if (!setterTypeIsConsistentWithGetterType(propertyName, getterSymbol, setterSymbol, parameterType)) return@forEach
+                if (setter.typeParameters.isNotEmpty() || setter.isStatic) return
+                val parameter = setter.valueParameters.singleOrNull() ?: return
+                if (parameter.isVararg) return
+                val parameterType = (parameter.returnTypeRef as? FirResolvedTypeRef)?.coneType ?: return
+                if (!setterTypeIsConsistentWithGetterType(propertyName, getterSymbol, setterSymbol, parameterType)) return
                 matchingSetter = setterSymbol.fir
-            }
+            })
         }
 
         val property = buildSyntheticProperty(propertyName, getter, matchingSetter, getterCompatibility, deprecatedOverrideOfHidden)
@@ -404,3 +405,4 @@
 
 val FirSimpleSyntheticPropertySymbol.deprecatedOverrideOfHidden: Boolean
     get() = (fir as FirSyntheticProperty).deprecatedOverrideOfHidden == true
+
diff --git a/compiler/fir/providers/src/org/jetbrains/kotlin/fir/scopes/impl/FirAbstractImportingScope.kt b/compiler/fir/providers/src/org/jetbrains/kotlin/fir/scopes/impl/FirAbstractImportingScope.kt
index ecc0ee5..4c02a4a 100644
--- a/compiler/fir/providers/src/org/jetbrains/kotlin/fir/scopes/impl/FirAbstractImportingScope.kt
+++ b/compiler/fir/providers/src/org/jetbrains/kotlin/fir/scopes/impl/FirAbstractImportingScope.kt
@@ -115,10 +115,6 @@
         )
     }
 
-    protected fun processFunctionsByName(name: Name?, imports: List<FirResolvedImport>, processor: (FirNamedFunctionSymbol) -> Unit) {
-        collectFunctionsByName(name, imports).forEach(processor)
-    }
-
     protected fun processPropertiesByName(name: Name?, imports: List<FirResolvedImport>, processor: (FirVariableSymbol<*>) -> Unit) {
         processCallablesFromImportsByName(
             name,
diff --git a/compiler/fir/providers/src/org/jetbrains/kotlin/fir/scopes/impl/FirActualizingScope.kt b/compiler/fir/providers/src/org/jetbrains/kotlin/fir/scopes/impl/FirActualizingScope.kt
index 3a9f382..0b49664 100644
--- a/compiler/fir/providers/src/org/jetbrains/kotlin/fir/scopes/impl/FirActualizingScope.kt
+++ b/compiler/fir/providers/src/org/jetbrains/kotlin/fir/scopes/impl/FirActualizingScope.kt
@@ -50,13 +50,13 @@
     @Suppress("UNCHECKED_CAST")
     private fun <S : FirCallableSymbol<*>> collectCallableSymbols(
         name: Name,
-        collect: () -> List<S>
+        collect: (Name) -> List<S>
     ): List<S> {
         val filteredSymbols = mutableSetOf<S>()
         // All matched `expect` callables should be preserved to make it possible to filter them out later if corresponding actuals are found
         val ignoredExpectSymbols = mutableSetOf<FirBasedSymbol<*>>()
 
-        collect().forEach { symbol ->
+        collect(name).forEach { symbol ->
             if (symbol.isActual) {
                 val matchedExpectSymbol = symbol.getSingleMatchedExpectForActualOrNull()
                 if (matchedExpectSymbol != null) {
diff --git a/compiler/fir/providers/src/org/jetbrains/kotlin/fir/scopes/impl/FirTypeIntersectionScope.kt b/compiler/fir/providers/src/org/jetbrains/kotlin/fir/scopes/impl/FirTypeIntersectionScope.kt
index 8399aba..2af112d 100644
--- a/compiler/fir/providers/src/org/jetbrains/kotlin/fir/scopes/impl/FirTypeIntersectionScope.kt
+++ b/compiler/fir/providers/src/org/jetbrains/kotlin/fir/scopes/impl/FirTypeIntersectionScope.kt
@@ -35,24 +35,27 @@
     override fun collectFunctionsByName(name: Name): List<FirNamedFunctionSymbol> {
         // Important optimization: avoid creating cache keys for names that are definitely absent
         if (name !in getCallableNames()) return emptyList()
-
-        val callablesWithOverridden = intersectionContext.collectFunctions(name)
-
-        return callablesWithOverridden.map { resultOfIntersection ->
-            val symbol = resultOfIntersection.chosenSymbol
-            overriddenSymbols[symbol] = resultOfIntersection.overriddenMembers
-            symbol
+        return buildList {
+            processCallablesByName(name, processor = {
+                this.add(it)
+            }, processCallables = { name, proc ->
+                collectFunctionsByName(name).forEach(proc)
+            })
         }
     }
 
     override fun processPropertiesByName(name: Name, processor: (FirVariableSymbol<*>) -> Unit) {
         // Important optimization: avoid creating cache keys for names that are definitely absent
         if (name !in getCallableNames()) return
+        processCallablesByName(name, processor, FirScope::processPropertiesByName)
+    }
 
-        val callablesWithOverridden = intersectionContext.collectIntersectionResultsForCallables(
-            name,
-            FirScope::processPropertiesByName
-        )
+    private inline fun <D : FirCallableSymbol<*>> processCallablesByName(
+        name: Name,
+        noinline processor: (D) -> Unit,
+        processCallables: FirScope.(Name, (D) -> Unit) -> Unit
+    ) {
+        val callablesWithOverridden = intersectionContext.collectIntersectionResultsForCallables(name, processCallables)
 
         for (resultOfIntersection in callablesWithOverridden) {
             val symbol = resultOfIntersection.chosenSymbol
diff --git a/compiler/fir/providers/src/org/jetbrains/kotlin/fir/scopes/impl/FirTypeIntersectionScopeContext.kt b/compiler/fir/providers/src/org/jetbrains/kotlin/fir/scopes/impl/FirTypeIntersectionScopeContext.kt
index 0c148b5..0a1ffe9 100644
--- a/compiler/fir/providers/src/org/jetbrains/kotlin/fir/scopes/impl/FirTypeIntersectionScopeContext.kt
+++ b/compiler/fir/providers/src/org/jetbrains/kotlin/fir/scopes/impl/FirTypeIntersectionScopeContext.kt
@@ -103,11 +103,9 @@
     }
 
     fun collectFunctions(name: Name): List<ResultOfIntersection<FirNamedFunctionSymbol>> {
-        val membersByScope = scopes.mapNotNull { scope ->
-            val members = scope.collectFunctionsByName(name)
-            if (members.isNotEmpty()) scope to members else null
-        }
-        return convertGroupedCallablesToIntersectionResults(membersByScope)
+        return collectIntersectionResultsForCallables(name, processCallables = { name, proc ->
+            collectFunctionsByName(name).forEach(proc)
+        })
     }
 
     inline fun <D : FirCallableSymbol<*>> collectMembersGroupedByScope(
diff --git a/compiler/fir/tree/src/org/jetbrains/kotlin/fir/scopes/FirScope.kt b/compiler/fir/tree/src/org/jetbrains/kotlin/fir/scopes/FirScope.kt
index 1b46064..0e9bde6 100644
--- a/compiler/fir/tree/src/org/jetbrains/kotlin/fir/scopes/FirScope.kt
+++ b/compiler/fir/tree/src/org/jetbrains/kotlin/fir/scopes/FirScope.kt
@@ -22,7 +22,7 @@
     }
 
 
-    @Deprecated("Obsolete API, please use collectFunctionsByName instead", ReplaceWith("collectFunctionsByName()"), DeprecationLevel.ERROR)
+    //@Deprecated("Obsolete API, please use collectFunctionsByName instead", ReplaceWith("collectFunctionsByName()"), DeprecationLevel.ERROR)
     final fun processFunctionsByName(
         name: Name,
         processor: (FirNamedFunctionSymbol) -> Unit