FIR2IR don't generate delegates for default interface members
This commit is contained in:
committed by
TeamCityServer
parent
261482904c
commit
88f41d006a
+35
-2
@@ -5,9 +5,11 @@
|
||||
|
||||
package org.jetbrains.kotlin.fir.backend.generators
|
||||
|
||||
import org.jetbrains.kotlin.descriptors.Modality
|
||||
import org.jetbrains.kotlin.fir.*
|
||||
import org.jetbrains.kotlin.fir.backend.*
|
||||
import org.jetbrains.kotlin.fir.declarations.*
|
||||
import org.jetbrains.kotlin.fir.isJavaDefault
|
||||
import org.jetbrains.kotlin.fir.declarations.utils.modality
|
||||
import org.jetbrains.kotlin.fir.scopes.impl.delegatedWrapperData
|
||||
import org.jetbrains.kotlin.fir.scopes.processAllFunctions
|
||||
import org.jetbrains.kotlin.fir.scopes.processAllProperties
|
||||
@@ -25,6 +27,9 @@ import org.jetbrains.kotlin.ir.expressions.impl.IrReturnImpl
|
||||
import org.jetbrains.kotlin.ir.types.classifierOrNull
|
||||
import org.jetbrains.kotlin.ir.types.isNothing
|
||||
import org.jetbrains.kotlin.ir.types.isUnit
|
||||
import org.jetbrains.kotlin.name.ClassId
|
||||
import org.jetbrains.kotlin.name.FqName
|
||||
import org.jetbrains.kotlin.name.JvmNames.JVM_DEFAULT_CLASS_ID
|
||||
|
||||
/**
|
||||
* A generator for delegated members from implementation by delegation.
|
||||
@@ -37,6 +42,10 @@ class DelegatedMemberGenerator(
|
||||
private val components: Fir2IrComponents
|
||||
) : Fir2IrComponents by components {
|
||||
|
||||
companion object {
|
||||
private val PLATFORM_DEPENDENT_CLASS_ID = ClassId.topLevel(FqName("kotlin.internal.PlatformDependent"))
|
||||
}
|
||||
|
||||
private val baseFunctionSymbols = mutableMapOf<IrFunction, List<FirNamedFunctionSymbol>>()
|
||||
private val basePropertySymbols = mutableMapOf<IrProperty, List<FirPropertySymbol>>()
|
||||
|
||||
@@ -55,7 +64,7 @@ class DelegatedMemberGenerator(
|
||||
declarationStorage.getIrFunctionSymbol(unwrapped.symbol).owner as? IrSimpleFunction
|
||||
?: return@processAllFunctions
|
||||
|
||||
if (unwrapped.isJavaDefault) {
|
||||
if (shouldSkipDelegationFor(unwrapped)) {
|
||||
return@processAllFunctions
|
||||
}
|
||||
|
||||
@@ -78,6 +87,10 @@ class DelegatedMemberGenerator(
|
||||
val member = declarationStorage.getIrPropertySymbol(unwrapped.symbol).owner as? IrProperty
|
||||
?: return@processAllProperties
|
||||
|
||||
if (shouldSkipDelegationFor(unwrapped)) {
|
||||
return@processAllProperties
|
||||
}
|
||||
|
||||
val irSubProperty = generateDelegatedProperty(
|
||||
subClass, firSubClass, irField, member, propertySymbol.fir
|
||||
)
|
||||
@@ -87,6 +100,26 @@ class DelegatedMemberGenerator(
|
||||
}
|
||||
}
|
||||
|
||||
private fun shouldSkipDelegationFor(unwrapped: FirCallableDeclaration): Boolean {
|
||||
// See org.jetbrains.kotlin.resolve.jvm.JvmDelegationFilter
|
||||
return (unwrapped is FirSimpleFunction && unwrapped.isDefaultJavaMethod()) ||
|
||||
unwrapped.hasAnnotation(JVM_DEFAULT_CLASS_ID) ||
|
||||
unwrapped.hasAnnotation(PLATFORM_DEPENDENT_CLASS_ID)
|
||||
}
|
||||
|
||||
private fun FirSimpleFunction.isDefaultJavaMethod(): Boolean =
|
||||
when {
|
||||
isIntersectionOverride ->
|
||||
baseForIntersectionOverride!!.isDefaultJavaMethod()
|
||||
isSubstitutionOverride ->
|
||||
originalForSubstitutionOverride!!.isDefaultJavaMethod()
|
||||
else -> {
|
||||
// Check that we have a non-abstract method from Java interface
|
||||
origin == FirDeclarationOrigin.Enhancement && modality == Modality.OPEN
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
fun bindDelegatedMembersOverriddenSymbols(irClass: IrClass) {
|
||||
val superClasses by lazy(LazyThreadSafetyMode.NONE) {
|
||||
irClass.superTypes.mapNotNullTo(mutableSetOf()) { it.classifierOrNull?.owner as? IrClass }
|
||||
|
||||
+6
@@ -25090,6 +25090,12 @@ public class FirBlackBoxCodegenTestGenerated extends AbstractFirBlackBoxCodegenT
|
||||
KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("compiler/testData/codegen/box/jvm8/defaults/delegationBy"), Pattern.compile("^(.+)\\.kt$"), null, TargetBackend.JVM_IR, true);
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("javaDefaultMethod.kt")
|
||||
public void testJavaDefaultMethod() throws Exception {
|
||||
runTest("compiler/testData/codegen/box/jvm8/defaults/delegationBy/javaDefaultMethod.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("simple.kt")
|
||||
public void testSimple() throws Exception {
|
||||
|
||||
@@ -59,12 +59,6 @@ inline val <reified D : FirCallableDeclaration> D.baseForIntersectionOverride: D
|
||||
inline val <reified S : FirCallableSymbol<*>> S.baseForIntersectionOverride: S?
|
||||
get() = fir.baseForIntersectionOverride?.symbol as S?
|
||||
|
||||
val FirSimpleFunction.isJavaDefault: Boolean
|
||||
get() {
|
||||
if (isIntersectionOverride) return baseForIntersectionOverride!!.isJavaDefault
|
||||
return origin == FirDeclarationOrigin.Enhancement && modality == Modality.OPEN
|
||||
}
|
||||
|
||||
inline fun <reified D : FirCallableDeclaration> D.originalIfFakeOverride(): D? =
|
||||
originalForSubstitutionOverride ?: baseForIntersectionOverride
|
||||
|
||||
|
||||
-2
@@ -1,6 +1,4 @@
|
||||
// !JVM_DEFAULT_MODE: all-compatibility
|
||||
// IGNORE_BACKEND_FIR: JVM_IR
|
||||
// FIR status: FailK
|
||||
// TARGET_BACKEND: JVM
|
||||
// JVM_TARGET: 1.8
|
||||
// WITH_STDLIB
|
||||
|
||||
-2
@@ -1,6 +1,4 @@
|
||||
// !JVM_DEFAULT_MODE: all-compatibility
|
||||
// IGNORE_BACKEND_FIR: JVM_IR
|
||||
// FIR status: failK
|
||||
// TARGET_BACKEND: JVM
|
||||
// JVM_TARGET: 1.8
|
||||
// WITH_STDLIB
|
||||
|
||||
@@ -1,5 +1,12 @@
|
||||
// IGNORE_BACKEND_FIR: JVM_IR
|
||||
// FIR status: Shouldn't be executed in 'remove'
|
||||
// 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
|
||||
@@ -25,3 +32,4 @@ fun box(): String {
|
||||
|
||||
return test.getOrDefault("absent", "OK")
|
||||
}
|
||||
|
||||
|
||||
-2
@@ -1,6 +1,4 @@
|
||||
// !JVM_DEFAULT_MODE: all-compatibility
|
||||
// IGNORE_BACKEND_FIR: JVM_IR
|
||||
// FIR status: failK
|
||||
// TARGET_BACKEND: JVM
|
||||
// JVM_TARGET: 1.8
|
||||
// WITH_STDLIB
|
||||
|
||||
Vendored
-2
@@ -1,6 +1,4 @@
|
||||
// !JVM_DEFAULT_MODE: all-compatibility
|
||||
// IGNORE_BACKEND_FIR: JVM_IR
|
||||
// FIR status: failK
|
||||
// TARGET_BACKEND: JVM
|
||||
// JVM_TARGET: 1.8
|
||||
// WITH_STDLIB
|
||||
|
||||
+24
@@ -0,0 +1,24 @@
|
||||
// TARGET_BACKEND: JVM
|
||||
// JVM_TARGET: 1.8
|
||||
// WITH_STDLIB
|
||||
|
||||
// FILE: javaDefaultMethod.kt
|
||||
|
||||
class JImpl : J {
|
||||
override fun getO() = "fail"
|
||||
override fun getK() = "K"
|
||||
}
|
||||
|
||||
class Test : J by JImpl()
|
||||
|
||||
fun box() =
|
||||
Test().getO() + Test().getK()
|
||||
|
||||
// FILE: J.java
|
||||
public interface J {
|
||||
default String getO() {
|
||||
return "O";
|
||||
}
|
||||
|
||||
String getK();
|
||||
}
|
||||
@@ -1,6 +1,4 @@
|
||||
// !JVM_DEFAULT_MODE: enable
|
||||
// IGNORE_BACKEND_FIR: JVM_IR
|
||||
// FIR status: failK
|
||||
// TARGET_BACKEND: JVM
|
||||
// JVM_TARGET: 1.8
|
||||
// WITH_STDLIB
|
||||
|
||||
@@ -1,6 +1,4 @@
|
||||
// !JVM_DEFAULT_MODE: enable
|
||||
// IGNORE_BACKEND_FIR: JVM_IR
|
||||
// FIR status: failK
|
||||
// TARGET_BACKEND: JVM
|
||||
// JVM_TARGET: 1.8
|
||||
// WITH_STDLIB
|
||||
|
||||
-2
@@ -1,6 +1,4 @@
|
||||
// !JVM_DEFAULT_MODE: all
|
||||
// IGNORE_BACKEND_FIR: JVM_IR
|
||||
// FIR status: failK
|
||||
// TARGET_BACKEND: JVM
|
||||
// JVM_TARGET: 1.8
|
||||
// WITH_STDLIB
|
||||
|
||||
-2
@@ -1,6 +1,4 @@
|
||||
// !JVM_DEFAULT_MODE: all
|
||||
// IGNORE_BACKEND_FIR: JVM_IR
|
||||
// FIR status: failK
|
||||
// TARGET_BACKEND: JVM
|
||||
// JVM_TARGET: 1.8
|
||||
// WITH_STDLIB
|
||||
|
||||
@@ -41,22 +41,6 @@ FILE fqName:<root> fileName:/kt43342.kt
|
||||
$this: GET_FIELD 'FIELD DELEGATE name:<$$delegate_0> type:kotlin.collections.Map<K of <root>.ControlFlowInfo, V of <root>.ControlFlowInfo> visibility:local [final]' type=kotlin.collections.Map<K of <root>.ControlFlowInfo, V of <root>.ControlFlowInfo> origin=null
|
||||
receiver: GET_VAR '<this>: <root>.ControlFlowInfo<K of <root>.ControlFlowInfo, V of <root>.ControlFlowInfo> declared in <root>.ControlFlowInfo.get' type=<root>.ControlFlowInfo<K of <root>.ControlFlowInfo, V of <root>.ControlFlowInfo> origin=null
|
||||
key: GET_VAR 'key: K of <root>.ControlFlowInfo declared in <root>.ControlFlowInfo.get' type=K of <root>.ControlFlowInfo origin=null
|
||||
FUN DELEGATED_MEMBER 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
|
||||
annotations:
|
||||
SinceKotlin(version = '1.1')
|
||||
PlatformDependent
|
||||
overridden:
|
||||
public open fun getOrDefault (key: K of kotlin.collections.Map, defaultValue: V of kotlin.collections.Map): V of kotlin.collections.Map declared in kotlin.collections.Map
|
||||
$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
|
||||
BLOCK_BODY
|
||||
RETURN type=kotlin.Nothing from='public open fun getOrDefault (key: K of <root>.ControlFlowInfo, defaultValue: V of <root>.ControlFlowInfo): V of <root>.ControlFlowInfo declared in <root>.ControlFlowInfo'
|
||||
CALL 'public open fun getOrDefault (key: K of kotlin.collections.Map, defaultValue: V of kotlin.collections.Map): V of kotlin.collections.Map declared in kotlin.collections.Map' type=V of <root>.ControlFlowInfo origin=null
|
||||
$this: GET_FIELD 'FIELD DELEGATE name:<$$delegate_0> type:kotlin.collections.Map<K of <root>.ControlFlowInfo, V of <root>.ControlFlowInfo> visibility:local [final]' type=kotlin.collections.Map<K of <root>.ControlFlowInfo, V of <root>.ControlFlowInfo> origin=null
|
||||
receiver: GET_VAR '<this>: <root>.ControlFlowInfo<K of <root>.ControlFlowInfo, V of <root>.ControlFlowInfo> declared in <root>.ControlFlowInfo.getOrDefault' type=<root>.ControlFlowInfo<K of <root>.ControlFlowInfo, V of <root>.ControlFlowInfo> origin=null
|
||||
key: GET_VAR 'key: K of <root>.ControlFlowInfo declared in <root>.ControlFlowInfo.getOrDefault' type=K of <root>.ControlFlowInfo origin=null
|
||||
defaultValue: GET_VAR 'defaultValue: V of <root>.ControlFlowInfo declared in <root>.ControlFlowInfo.getOrDefault' type=V of <root>.ControlFlowInfo origin=null
|
||||
FUN DELEGATED_MEMBER name:isEmpty visibility:public modality:OPEN <> ($this:<root>.ControlFlowInfo<K of <root>.ControlFlowInfo, V of <root>.ControlFlowInfo>) returnType:kotlin.Boolean
|
||||
overridden:
|
||||
public abstract fun isEmpty (): kotlin.Boolean declared in kotlin.collections.Map
|
||||
|
||||
@@ -17,12 +17,6 @@ open class ControlFlowInfo<K : Any?, V : Any?> : Map<K, V> {
|
||||
return <this>.#<$$delegate_0>.get(key = key)
|
||||
}
|
||||
|
||||
@SinceKotlin(version = "1.1")
|
||||
@PlatformDependent
|
||||
override fun getOrDefault(key: K, defaultValue: V): V {
|
||||
return <this>.#<$$delegate_0>.getOrDefault(key = key, defaultValue = defaultValue)
|
||||
}
|
||||
|
||||
override fun isEmpty(): Boolean {
|
||||
return <this>.#<$$delegate_0>.isEmpty()
|
||||
}
|
||||
|
||||
+6
@@ -24928,6 +24928,12 @@ public class BlackBoxCodegenTestGenerated extends AbstractBlackBoxCodegenTest {
|
||||
KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("compiler/testData/codegen/box/jvm8/defaults/delegationBy"), Pattern.compile("^(.+)\\.kt$"), null, TargetBackend.JVM, true);
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("javaDefaultMethod.kt")
|
||||
public void testJavaDefaultMethod() throws Exception {
|
||||
runTest("compiler/testData/codegen/box/jvm8/defaults/delegationBy/javaDefaultMethod.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("simple.kt")
|
||||
public void testSimple() throws Exception {
|
||||
|
||||
+6
@@ -25090,6 +25090,12 @@ public class IrBlackBoxCodegenTestGenerated extends AbstractIrBlackBoxCodegenTes
|
||||
KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("compiler/testData/codegen/box/jvm8/defaults/delegationBy"), Pattern.compile("^(.+)\\.kt$"), null, TargetBackend.JVM_IR, true);
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("javaDefaultMethod.kt")
|
||||
public void testJavaDefaultMethod() throws Exception {
|
||||
runTest("compiler/testData/codegen/box/jvm8/defaults/delegationBy/javaDefaultMethod.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("simple.kt")
|
||||
public void testSimple() throws Exception {
|
||||
|
||||
+5
@@ -20986,6 +20986,11 @@ public class LightAnalysisModeTestGenerated extends AbstractLightAnalysisModeTes
|
||||
KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("compiler/testData/codegen/box/jvm8/defaults/delegationBy"), Pattern.compile("^(.+)\\.kt$"), null, TargetBackend.JVM, true);
|
||||
}
|
||||
|
||||
@TestMetadata("javaDefaultMethod.kt")
|
||||
public void testJavaDefaultMethod() throws Exception {
|
||||
runTest("compiler/testData/codegen/box/jvm8/defaults/delegationBy/javaDefaultMethod.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("simple.kt")
|
||||
public void testSimple() throws Exception {
|
||||
runTest("compiler/testData/codegen/box/jvm8/defaults/delegationBy/simple.kt");
|
||||
|
||||
+6
@@ -25391,6 +25391,12 @@ public class NativeExtBlackBoxTestGenerated extends AbstractNativeBlackBoxTest {
|
||||
KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("compiler/testData/codegen/box/jvm8/defaults/delegationBy"), Pattern.compile("^(.+)\\.kt$"), null, true);
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("javaDefaultMethod.kt")
|
||||
public void testJavaDefaultMethod() throws Exception {
|
||||
runTest("compiler/testData/codegen/box/jvm8/defaults/delegationBy/javaDefaultMethod.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("simple.kt")
|
||||
public void testSimple() throws Exception {
|
||||
|
||||
Reference in New Issue
Block a user