[FIR] Don't generate delegated members for java methods with default implementation
^KT-62334 Fixed
This commit is contained in:
committed by
Space Team
parent
5857e6cc5d
commit
61ec143b74
@@ -54,6 +54,7 @@ import org.jetbrains.kotlin.fir.scopes.FirOverrideService
|
||||
import org.jetbrains.kotlin.fir.scopes.FirPlatformClassMapper
|
||||
import org.jetbrains.kotlin.fir.scopes.PlatformSpecificOverridabilityRules
|
||||
import org.jetbrains.kotlin.fir.scopes.impl.*
|
||||
import org.jetbrains.kotlin.fir.scopes.jvm.FirJvmDelegatedMembersFilter
|
||||
import org.jetbrains.kotlin.fir.scopes.jvm.JvmMappedScope.FirMappedSymbolStorage
|
||||
import org.jetbrains.kotlin.fir.serialization.FirProvidedDeclarationsForMetadataService
|
||||
import org.jetbrains.kotlin.fir.symbols.FirLazyDeclarationResolver
|
||||
@@ -159,6 +160,7 @@ fun FirSession.registerJavaComponents(
|
||||
register(FirOverridesBackwardCompatibilityHelper::class, FirJvmOverridesBackwardCompatibilityHelper)
|
||||
register(FirInlineCheckerPlatformSpecificComponent::class, FirJvmInlineCheckerComponent())
|
||||
register(FirGenericArrayClassLiteralSupport::class, FirGenericArrayClassLiteralSupport.Enabled)
|
||||
register(FirDelegatedMembersFilter::class, FirJvmDelegatedMembersFilter(this))
|
||||
}
|
||||
|
||||
// -------------------------- Resolve components --------------------------
|
||||
|
||||
+2
@@ -15,6 +15,7 @@ import org.jetbrains.kotlin.fir.extensions.FirExtensionService
|
||||
import org.jetbrains.kotlin.fir.java.FirProjectSessionProvider
|
||||
import org.jetbrains.kotlin.fir.resolve.calls.ConeCallConflictResolverFactory
|
||||
import org.jetbrains.kotlin.fir.scopes.FirPlatformClassMapper
|
||||
import org.jetbrains.kotlin.fir.scopes.impl.FirDelegatedMembersFilter
|
||||
import org.jetbrains.kotlin.fir.session.environment.AbstractProjectEnvironment
|
||||
import org.jetbrains.kotlin.fir.session.environment.AbstractProjectFileSearchScope
|
||||
import org.jetbrains.kotlin.incremental.components.EnumWhenTracker
|
||||
@@ -138,5 +139,6 @@ object FirSessionFactoryHelper {
|
||||
register(ConeCallConflictResolverFactory::class, DefaultCallConflictResolverFactory)
|
||||
register(FirPlatformClassMapper::class, FirPlatformClassMapper.Default)
|
||||
register(FirOverridesBackwardCompatibilityHelper::class, FirDefaultOverridesBackwardCompatibilityHelper)
|
||||
register(FirDelegatedMembersFilter::class, FirDelegatedMembersFilter.Default)
|
||||
}
|
||||
}
|
||||
|
||||
+47
@@ -0,0 +1,47 @@
|
||||
/*
|
||||
* Copyright 2010-2023 JetBrains s.r.o. and Kotlin Programming Language contributors.
|
||||
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
|
||||
*/
|
||||
|
||||
package org.jetbrains.kotlin.fir.scopes.jvm
|
||||
|
||||
import org.jetbrains.kotlin.descriptors.Modality
|
||||
import org.jetbrains.kotlin.fir.FirSession
|
||||
import org.jetbrains.kotlin.fir.declarations.FirDeclarationOrigin
|
||||
import org.jetbrains.kotlin.fir.declarations.hasAnnotation
|
||||
import org.jetbrains.kotlin.fir.declarations.utils.modality
|
||||
import org.jetbrains.kotlin.fir.scopes.impl.FirDelegatedMembersFilter
|
||||
import org.jetbrains.kotlin.fir.symbols.impl.FirCallableSymbol
|
||||
import org.jetbrains.kotlin.fir.unwrapFakeOverrides
|
||||
import org.jetbrains.kotlin.name.ClassId
|
||||
import org.jetbrains.kotlin.name.FqName
|
||||
import org.jetbrains.kotlin.name.JvmStandardClassIds
|
||||
|
||||
/*
|
||||
* KT-18324: If original is java method with default then delegated function should not be generated
|
||||
* See org.jetbrains.kotlin.resolve.jvm.JvmDelegationFilter for K1 implementation
|
||||
*/
|
||||
class FirJvmDelegatedMembersFilter(private val session: FirSession) : FirDelegatedMembersFilter() {
|
||||
companion object {
|
||||
private val PLATFORM_DEPENDENT_ANNOTATION_CLASS_ID = ClassId.topLevel(FqName("kotlin.internal.PlatformDependent"))
|
||||
}
|
||||
|
||||
override fun shouldNotGenerateDelegatedMember(memberSymbolFromSuperInterface: FirCallableSymbol<*>): Boolean {
|
||||
val original = memberSymbolFromSuperInterface.unwrapFakeOverrides()
|
||||
return original.isNonAbstractJavaMethod() || original.hasJvmDefaultAnnotation() || original.isBuiltInMemberMappedToJavaDefault()
|
||||
}
|
||||
|
||||
// If java interface method is not abstract, then it's a default method.
|
||||
private fun FirCallableSymbol<*>.isNonAbstractJavaMethod(): Boolean {
|
||||
return origin == FirDeclarationOrigin.Enhancement && modality != Modality.ABSTRACT
|
||||
}
|
||||
|
||||
private fun FirCallableSymbol<*>.hasJvmDefaultAnnotation(): Boolean {
|
||||
return annotations.hasAnnotation(JvmStandardClassIds.JVM_DEFAULT_CLASS_ID, session)
|
||||
}
|
||||
|
||||
private fun FirCallableSymbol<*>.isBuiltInMemberMappedToJavaDefault(): Boolean {
|
||||
return modality != Modality.ABSTRACT &&
|
||||
annotations.hasAnnotation(PLATFORM_DEPENDENT_ANNOTATION_CLASS_ID, session)
|
||||
}
|
||||
}
|
||||
+22
@@ -9,6 +9,7 @@ import org.jetbrains.kotlin.descriptors.Modality
|
||||
import org.jetbrains.kotlin.descriptors.Visibilities
|
||||
import org.jetbrains.kotlin.fir.DelegatedWrapperData
|
||||
import org.jetbrains.kotlin.fir.FirSession
|
||||
import org.jetbrains.kotlin.fir.FirSessionComponent
|
||||
import org.jetbrains.kotlin.fir.declarations.*
|
||||
import org.jetbrains.kotlin.fir.declarations.utils.classId
|
||||
import org.jetbrains.kotlin.fir.declarations.utils.modality
|
||||
@@ -39,6 +40,7 @@ class FirDelegatedMemberScope(
|
||||
) : FirContainingNamesAwareScope() {
|
||||
private val dispatchReceiverType = containingClass.defaultType()
|
||||
private val overrideChecker = session.firOverrideChecker
|
||||
private val delegatedMembersFilter = session.delegatedMembersFilter
|
||||
|
||||
override fun processFunctionsByName(name: Name, processor: (FirNamedFunctionSymbol) -> Unit) {
|
||||
declaredMemberScope.processFunctionsByName(name, processor)
|
||||
@@ -80,6 +82,10 @@ class FirDelegatedMemberScope(
|
||||
return@processor
|
||||
}
|
||||
|
||||
if (delegatedMembersFilter.shouldNotGenerateDelegatedMember(original.symbol)) {
|
||||
return@processor
|
||||
}
|
||||
|
||||
if (declaredMemberScope.getFunctions(name).any { overrideChecker.isOverriddenFunction(it.fir, original) }) {
|
||||
return@processor
|
||||
}
|
||||
@@ -143,6 +149,10 @@ class FirDelegatedMemberScope(
|
||||
return@processor
|
||||
}
|
||||
|
||||
if (delegatedMembersFilter.shouldNotGenerateDelegatedMember(propertySymbol)) {
|
||||
return@processor
|
||||
}
|
||||
|
||||
val original = propertySymbol.fir
|
||||
var isOverriddenProperty = false
|
||||
declaredMemberScope.processPropertiesByName(name) {
|
||||
@@ -240,3 +250,15 @@ fun FirValueParameter.hasTypeOf(classId: ClassId, allowNullable: Boolean): Boole
|
||||
}
|
||||
|
||||
private val PUBLIC_METHOD_NAMES_IN_ANY = setOf("equals", "hashCode", "toString")
|
||||
|
||||
abstract class FirDelegatedMembersFilter : FirSessionComponent {
|
||||
abstract fun shouldNotGenerateDelegatedMember(memberSymbolFromSuperInterface: FirCallableSymbol<*>): Boolean
|
||||
|
||||
object Default : FirDelegatedMembersFilter() {
|
||||
override fun shouldNotGenerateDelegatedMember(memberSymbolFromSuperInterface: FirCallableSymbol<*>): Boolean {
|
||||
return false
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private val FirSession.delegatedMembersFilter: FirDelegatedMembersFilter by FirSession.sessionComponentAccessor()
|
||||
|
||||
@@ -2,8 +2,6 @@
|
||||
// IGNORE_CODEGEN_WITH_IR_FAKE_OVERRIDE_GENERATION: KT-61370
|
||||
// WITH_STDLIB
|
||||
// FULL_JDK
|
||||
// IGNORE_BACKEND_K2: ANY
|
||||
// Ignore reason: KT-62334
|
||||
|
||||
abstract class AMap1<K1, V1>(private val m: Map<K1, V1>) : Map<K1, V1> by m
|
||||
|
||||
|
||||
@@ -1,7 +1,5 @@
|
||||
// TARGET_BACKEND: JVM
|
||||
// JVM_TARGET: 1.8
|
||||
// IGNORE_BACKEND_K2: ANY
|
||||
// Ignore reason: KT-62334
|
||||
// FILE: Base.java
|
||||
|
||||
public interface Base {
|
||||
|
||||
@@ -1,12 +1,3 @@
|
||||
// IGNORE_BACKEND_K2: JVM_IR, JS_IR
|
||||
// FIR status: NSME: Test.remove(Ljava/lang/String;Ljava/lang/String;)Z
|
||||
// FIR + JVM_IR:
|
||||
// INVOKEVIRTUAL Test.remove (Ljava/lang/String;Ljava/lang/String;)Z
|
||||
// => java.lang.NoSuchMethodError: Test.remove(Ljava/lang/String;Ljava/lang/String;)Z
|
||||
// FE1.0 + JVM_IR:
|
||||
// INVOKEVIRTUAL Test.remove (Ljava/lang/Object;Ljava/lang/Object;)Z
|
||||
// => default method in java.util.Map (as expected)
|
||||
|
||||
// SKIP_JDK6
|
||||
// TARGET_BACKEND: JVM
|
||||
// FULL_JDK
|
||||
|
||||
@@ -1,7 +1,5 @@
|
||||
// TARGET_BACKEND: JVM
|
||||
// JVM_TARGET: 1.8
|
||||
// IGNORE_BACKEND_K2: ANY
|
||||
// Ignore reason: KT-62334
|
||||
// FILE: Base.java
|
||||
|
||||
public interface Base {
|
||||
|
||||
@@ -1,7 +1,5 @@
|
||||
// TARGET_BACKEND: JVM
|
||||
// JVM_TARGET: 1.8
|
||||
// IGNORE_BACKEND_K2: ANY
|
||||
// Ignore reason: KT-62334
|
||||
// FILE: Base.java
|
||||
|
||||
public interface Base {
|
||||
|
||||
@@ -1,7 +1,5 @@
|
||||
// TARGET_BACKEND: JVM
|
||||
// JVM_TARGET: 1.8
|
||||
// IGNORE_BACKEND_K2: ANY
|
||||
// Ignore reason: KT-62334
|
||||
// FILE: Base.java
|
||||
|
||||
public interface Base extends KBase {
|
||||
|
||||
@@ -1,7 +1,5 @@
|
||||
// TARGET_BACKEND: JVM
|
||||
// JVM_TARGET: 1.8
|
||||
// IGNORE_BACKEND_K2: ANY
|
||||
// Ignore reason: KT-62334
|
||||
// FILE: Base.java
|
||||
|
||||
public interface Base {
|
||||
|
||||
-2
@@ -1,7 +1,5 @@
|
||||
// TARGET_BACKEND: JVM_IR
|
||||
// JVM_TARGET: 1.8
|
||||
// IGNORE_BACKEND_K2: ANY
|
||||
// Ignore reason: KT-62334
|
||||
// FILE: A.java
|
||||
|
||||
public interface A {
|
||||
|
||||
-2
@@ -1,7 +1,5 @@
|
||||
// TARGET_BACKEND: JVM_IR
|
||||
// JVM_TARGET: 1.8
|
||||
// IGNORE_BACKEND_K2: ANY
|
||||
// Ignore reason: KT-62334
|
||||
// FILE: A.java
|
||||
|
||||
public interface A {
|
||||
|
||||
+1
-3
@@ -1,8 +1,6 @@
|
||||
// TARGET_BACKEND: JVM
|
||||
// JVM_TARGET: 1.8
|
||||
// WITH_STDLIB
|
||||
// IGNORE_BACKEND_K2: ANY
|
||||
// Ignore reason: KT-62334
|
||||
|
||||
// FILE: javaDefaultMethod.kt
|
||||
|
||||
@@ -23,4 +21,4 @@ public interface J {
|
||||
}
|
||||
|
||||
String getK();
|
||||
}
|
||||
}
|
||||
@@ -1,7 +1,5 @@
|
||||
// TARGET_BACKEND: JVM
|
||||
// JVM_TARGET: 1.8
|
||||
// IGNORE_BACKEND_K2: ANY
|
||||
// Ignore reason: KT-62334
|
||||
|
||||
// MODULE: lib
|
||||
// FILE: A.java
|
||||
|
||||
@@ -126,6 +126,10 @@ FILE fqName:<root> fileName:/kt43342.kt
|
||||
overridden:
|
||||
public open fun toString (): kotlin.String declared in kotlin.collections.Map
|
||||
$this: VALUE_PARAMETER name:<this> type:kotlin.Any
|
||||
FUN name:getOrDefault visibility:public modality:OPEN <> ($this:<root>.ControlFlowInfo<K of <root>.ControlFlowInfo, V of <root>.ControlFlowInfo>, key:K of <root>.ControlFlowInfo, defaultValue:V of <root>.ControlFlowInfo) returnType:V of <root>.ControlFlowInfo
|
||||
$this: VALUE_PARAMETER name:<this> type:<root>.ControlFlowInfo<K of <root>.ControlFlowInfo, V of <root>.ControlFlowInfo>
|
||||
VALUE_PARAMETER name:key index:0 type:K of <root>.ControlFlowInfo
|
||||
VALUE_PARAMETER name:defaultValue index:1 type:V of <root>.ControlFlowInfo
|
||||
CLASS CLASS name:StringFlowInfo modality:FINAL visibility:public superTypes:[<root>.ControlFlowInfo<kotlin.String, kotlin.String>]
|
||||
$this: VALUE_PARAMETER INSTANCE_RECEIVER name:<this> type:<root>.StringFlowInfo
|
||||
CONSTRUCTOR visibility:public <> (map:kotlin.collections.Map<kotlin.String, kotlin.String>) returnType:<root>.StringFlowInfo [primary]
|
||||
|
||||
Reference in New Issue
Block a user