K2: introduce platform-dependent filtering for non-JVM platforms
This commit fixes a false negative in testData/cli/metadata/getOrDefault Related to KT-57268
This commit is contained in:
committed by
Space Team
parent
7599ff0ef1
commit
ed246d372b
+2
-10
@@ -5,20 +5,14 @@
|
||||
|
||||
package org.jetbrains.kotlin.fir.scopes.jvm
|
||||
|
||||
import org.jetbrains.kotlin.builtins.StandardNames
|
||||
import org.jetbrains.kotlin.fir.FirSession
|
||||
import org.jetbrains.kotlin.fir.declarations.FirSimpleFunction
|
||||
import org.jetbrains.kotlin.fir.declarations.hasAnnotation
|
||||
import org.jetbrains.kotlin.fir.scopes.FirPlatformDeclarationFilter
|
||||
import org.jetbrains.kotlin.fir.scopes.FirTypeScope
|
||||
import org.jetbrains.kotlin.name.Name
|
||||
|
||||
internal object FirJvmPlatformDeclarationFilter {
|
||||
fun isFunctionAvailable(function: FirSimpleFunction, javaClassScope: FirTypeScope, session: FirSession): Boolean {
|
||||
// Optimization: only run the below logic for functions named "getOrDefault" and "remove", since only two functions with these names
|
||||
// in kotlin.collections.Map are currently annotated with @PlatformDependent.
|
||||
if (function.name !in namesToCheck) return true
|
||||
|
||||
if (!function.hasAnnotation(StandardNames.FqNames.platformDependentClassId, session)) return true
|
||||
if (FirPlatformDeclarationFilter.isFunctionAvailable(function, session)) return true
|
||||
|
||||
var isFunctionPresentInJavaAnalogue = false
|
||||
val jvmDescriptorOfKotlinFunction = function.computeJvmDescriptor()
|
||||
@@ -29,6 +23,4 @@ internal object FirJvmPlatformDeclarationFilter {
|
||||
}
|
||||
return isFunctionPresentInJavaAnalogue
|
||||
}
|
||||
|
||||
private val namesToCheck = listOf("getOrDefault", "remove").map(Name::identifier)
|
||||
}
|
||||
|
||||
+55
-1
@@ -5,6 +5,7 @@
|
||||
|
||||
package org.jetbrains.kotlin.fir.scopes
|
||||
|
||||
import org.jetbrains.kotlin.builtins.StandardNames
|
||||
import org.jetbrains.kotlin.descriptors.ClassKind
|
||||
import org.jetbrains.kotlin.fir.FirSession
|
||||
import org.jetbrains.kotlin.fir.FirSessionComponent
|
||||
@@ -12,6 +13,8 @@ import org.jetbrains.kotlin.fir.declarations.FirClass
|
||||
import org.jetbrains.kotlin.fir.declarations.FirDeclarationOrigin
|
||||
import org.jetbrains.kotlin.fir.declarations.FirRegularClass
|
||||
import org.jetbrains.kotlin.fir.declarations.FirResolvePhase
|
||||
import org.jetbrains.kotlin.fir.declarations.FirSimpleFunction
|
||||
import org.jetbrains.kotlin.fir.declarations.hasAnnotation
|
||||
import org.jetbrains.kotlin.fir.declarations.utils.delegateFields
|
||||
import org.jetbrains.kotlin.fir.declarations.utils.isData
|
||||
import org.jetbrains.kotlin.fir.declarations.utils.isExpect
|
||||
@@ -23,9 +26,14 @@ import org.jetbrains.kotlin.fir.resolve.substitution.substitutorByMap
|
||||
import org.jetbrains.kotlin.fir.scopes.impl.*
|
||||
import org.jetbrains.kotlin.fir.symbols.ConeClassLikeLookupTag
|
||||
import org.jetbrains.kotlin.fir.symbols.impl.FirClassSymbol
|
||||
import org.jetbrains.kotlin.fir.symbols.impl.FirClassifierSymbol
|
||||
import org.jetbrains.kotlin.fir.symbols.impl.FirConstructorSymbol
|
||||
import org.jetbrains.kotlin.fir.symbols.impl.FirNamedFunctionSymbol
|
||||
import org.jetbrains.kotlin.fir.symbols.impl.FirRegularClassSymbol
|
||||
import org.jetbrains.kotlin.fir.symbols.impl.FirVariableSymbol
|
||||
import org.jetbrains.kotlin.fir.symbols.lazyResolveToPhaseWithCallableMembers
|
||||
import org.jetbrains.kotlin.fir.types.*
|
||||
import org.jetbrains.kotlin.name.Name
|
||||
|
||||
class FirKotlinScopeProvider(
|
||||
val declaredMemberScopeDecorator: (
|
||||
@@ -34,7 +42,9 @@ class FirKotlinScopeProvider(
|
||||
useSiteSession: FirSession,
|
||||
scopeSession: ScopeSession,
|
||||
memberRequiredPhase: FirResolvePhase?,
|
||||
) -> FirContainingNamesAwareScope = { _, declaredMemberScope, _, _, _ -> declaredMemberScope }
|
||||
) -> FirContainingNamesAwareScope = { _, declaredMemberScope, session, _, _ ->
|
||||
PlatformDependentFilteringScope(declaredMemberScope, session)
|
||||
}
|
||||
) : FirScopeProvider(), FirSessionComponent {
|
||||
override fun getUseSiteMemberScope(
|
||||
klass: FirClass,
|
||||
@@ -109,8 +119,52 @@ class FirKotlinScopeProvider(
|
||||
): FirContainingNamesAwareScope? {
|
||||
return useSiteSession.nestedClassifierScope(klass)
|
||||
}
|
||||
|
||||
class PlatformDependentFilteringScope(
|
||||
val declaredMemberScope: FirContainingNamesAwareScope,
|
||||
val session: FirSession,
|
||||
) : FirContainingNamesAwareScope() {
|
||||
override fun getCallableNames(): Set<Name> = declaredMemberScope.getCallableNames()
|
||||
|
||||
override fun getClassifierNames(): Set<Name> = declaredMemberScope.getClassifierNames()
|
||||
|
||||
override fun processPropertiesByName(name: Name, processor: (FirVariableSymbol<*>) -> Unit) {
|
||||
declaredMemberScope.processPropertiesByName(name, processor)
|
||||
}
|
||||
|
||||
override fun processClassifiersByNameWithSubstitution(name: Name, processor: (FirClassifierSymbol<*>, ConeSubstitutor) -> Unit) {
|
||||
declaredMemberScope.processClassifiersByNameWithSubstitution(name, processor)
|
||||
}
|
||||
|
||||
override fun processDeclaredConstructors(processor: (FirConstructorSymbol) -> Unit) {
|
||||
declaredMemberScope.processDeclaredConstructors(processor)
|
||||
}
|
||||
|
||||
override fun processFunctionsByName(name: Name, processor: (FirNamedFunctionSymbol) -> Unit) {
|
||||
declaredMemberScope.processFunctionsByName(name) {
|
||||
if (FirPlatformDeclarationFilter.isFunctionAvailable(it.fir, session)) {
|
||||
processor(it)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
override fun mayContainName(name: Name): Boolean = declaredMemberScope.mayContainName(name)
|
||||
|
||||
override val scopeOwnerLookupNames: List<String>
|
||||
get() = declaredMemberScope.scopeOwnerLookupNames
|
||||
}
|
||||
}
|
||||
|
||||
object FirPlatformDeclarationFilter {
|
||||
fun isFunctionAvailable(function: FirSimpleFunction, session: FirSession): Boolean {
|
||||
// Optimization: only check the annotations for functions named "getOrDefault" and "remove",
|
||||
// since only two functions with these names in kotlin.collections.Map are currently annotated with @PlatformDependent.
|
||||
// This also allows to optimize more heavyweight FirJvmPlatformDeclarationFilter as it uses this function
|
||||
return function.name !in namesToCheck || !function.hasAnnotation(StandardNames.FqNames.platformDependentClassId, session)
|
||||
}
|
||||
|
||||
private val namesToCheck = listOf("getOrDefault", "remove").map(Name::identifier)
|
||||
}
|
||||
|
||||
data class ConeSubstitutionScopeKey(
|
||||
val lookupTag: ConeClassLikeLookupTag,
|
||||
|
||||
+4
-1
@@ -1 +1,4 @@
|
||||
OK
|
||||
compiler/testData/cli/metadata/getOrDefault.kt:2:38: error: unresolved reference 'getOrDefault'.
|
||||
fun foo(map: Map<String, Int>) = map.getOrDefault("", 0)
|
||||
^
|
||||
COMPILATION_ERROR
|
||||
|
||||
+1
-1
@@ -12,4 +12,4 @@ public expect abstract class AbstractMutableMap<K, V> : MutableMap<K, V> {
|
||||
|
||||
import java.util.AbstractMap
|
||||
|
||||
public actual abstract class <!NO_ACTUAL_CLASS_MEMBER_FOR_EXPECTED_CLASS, NO_ACTUAL_CLASS_MEMBER_FOR_EXPECTED_CLASS!>AbstractMutableMap<!><K, V>() : MutableMap<K, V>, AbstractMap<K, V>()
|
||||
public actual abstract class <!NO_ACTUAL_CLASS_MEMBER_FOR_EXPECTED_CLASS!>AbstractMutableMap<!><K, V>() : MutableMap<K, V>, AbstractMap<K, V>()
|
||||
|
||||
Reference in New Issue
Block a user