Generate local delegated properties in interface in jvm-default all modes

This commit is contained in:
Mikhael Bogdanov
2021-02-25 09:24:39 +01:00
parent c25a694b6b
commit 49aa36b70d
17 changed files with 318 additions and 18 deletions
@@ -660,7 +660,8 @@ public abstract class MemberCodegen<T extends KtPureElement/* TODO: & KtDeclarat
List<VariableDescriptorWithAccessors> delegatedProperties = bindingContext.get(CodegenBinding.DELEGATED_PROPERTIES_WITH_METADATA, thisAsmType);
if (delegatedProperties == null || delegatedProperties.isEmpty()) return;
v.newField(NO_ORIGIN, ACC_STATIC | ACC_FINAL | ACC_SYNTHETIC, JvmAbi.DELEGATED_PROPERTIES_ARRAY_NAME,
int additionalFlags = context.getContextKind() != OwnerKind.DEFAULT_IMPLS && isInterface(context.getContextDescriptor()) ? ACC_PUBLIC : 0;
v.newField(NO_ORIGIN, ACC_STATIC | ACC_FINAL | ACC_SYNTHETIC | additionalFlags, JvmAbi.DELEGATED_PROPERTIES_ARRAY_NAME,
"[" + K_PROPERTY_TYPE, null, null);
if (!state.getClassBuilderMode().generateBodies) return;
@@ -24,6 +24,7 @@ import org.jetbrains.kotlin.codegen.coroutines.CoroutineCodegenUtilKt;
import org.jetbrains.kotlin.codegen.state.GenerationState;
import org.jetbrains.kotlin.codegen.when.SwitchCodegenProvider;
import org.jetbrains.kotlin.codegen.when.WhenByEnumsMapping;
import org.jetbrains.kotlin.config.JvmDefaultMode;
import org.jetbrains.kotlin.config.LanguageFeature;
import org.jetbrains.kotlin.config.LanguageVersionSettings;
import org.jetbrains.kotlin.coroutines.CoroutineUtilKt;
@@ -87,6 +88,7 @@ class CodegenAnnotatingVisitor extends KtVisitorVoid {
private final LanguageVersionSettings languageVersionSettings;
private final ClassBuilderMode classBuilderMode;
private final DelegatedPropertiesCodegenHelper delegatedPropertiesCodegenHelper;
private final JvmDefaultMode jvmDefaultMode;
public CodegenAnnotatingVisitor(@NotNull GenerationState state) {
this.bindingTrace = state.getBindingTrace();
@@ -97,6 +99,7 @@ class CodegenAnnotatingVisitor extends KtVisitorVoid {
this.languageVersionSettings = state.getLanguageVersionSettings();
this.classBuilderMode = state.getClassBuilderMode();
this.delegatedPropertiesCodegenHelper = new DelegatedPropertiesCodegenHelper(state);
jvmDefaultMode = state.getJvmDefaultMode();
}
@NotNull
@@ -585,7 +588,7 @@ class CodegenAnnotatingVisitor extends KtVisitorVoid {
}
return AsmUtil.asmTypeByClassId(
DescriptorUtils.isInterface(descriptor)
DescriptorUtils.isInterface(descriptor) && !jvmDefaultMode.getForAllMethodsWithBody()
? classId.createNestedClassId(Name.identifier(JvmAbi.DEFAULT_IMPLS_CLASS_NAME))
: classId
);
@@ -91,7 +91,7 @@ class JvmSerializerExtension @JvmOverloads constructor(
}
//TODO: support local delegated properties in new defaults scheme
val containerAsmType =
if (isInterface(descriptor)) typeMapper.mapDefaultImpls(descriptor) else typeMapper.mapClass(descriptor)
if (isInterface(descriptor) && !jvmDefaultMode.forAllMethodsWithBody) typeMapper.mapDefaultImpls(descriptor) else typeMapper.mapClass(descriptor)
writeLocalProperties(proto, containerAsmType, JvmProtoBuf.classLocalVariable)
writeVersionRequirementForJvmDefaultIfNeeded(descriptor, proto, versionRequirementTable)
@@ -21996,6 +21996,12 @@ public class FirBlackBoxCodegenTestGenerated extends AbstractFirBlackBoxCodegenT
runTest("compiler/testData/codegen/box/jvm8/defaults/allCompatibility/kt42674.kt");
}
@Test
@TestMetadata("localDelegatedProperties.kt")
public void testLocalDelegatedProperties() throws Exception {
runTest("compiler/testData/codegen/box/jvm8/defaults/allCompatibility/localDelegatedProperties.kt");
}
@Test
@TestMetadata("privateFunInInterface.kt")
public void testPrivateFunInInterface() throws Exception {
@@ -22330,6 +22336,18 @@ public class FirBlackBoxCodegenTestGenerated extends AbstractFirBlackBoxCodegenT
runTest("compiler/testData/codegen/box/jvm8/defaults/noDefaultImpls/kt42674.kt");
}
@Test
@TestMetadata("localDelegatedProperties.kt")
public void testLocalDelegatedProperties() throws Exception {
runTest("compiler/testData/codegen/box/jvm8/defaults/noDefaultImpls/localDelegatedProperties.kt");
}
@Test
@TestMetadata("localDelegatedProperties2.kt")
public void testLocalDelegatedProperties2() throws Exception {
runTest("compiler/testData/codegen/box/jvm8/defaults/noDefaultImpls/localDelegatedProperties2.kt");
}
@Test
@TestMetadata("privateFunInInterface.kt")
public void testPrivateFunInInterface() throws Exception {
@@ -44,9 +44,12 @@ class DescriptorMetadataSerializer(
if (localDelegatedProperties != null && localDelegatedProperties.isNotEmpty()) {
context.state.bindingTrace.record(
CodegenBinding.DELEGATED_PROPERTIES_WITH_METADATA,
// When serializing metadata for interfaces, `JvmSerializerExtension.serializeClass`
// looks at `$DefaultImpls` for some reason that's probably related to the old backend.
if (irClass.isInterface) context.typeMapper.mapClass(context.cachedDeclarations.getDefaultImplsClass(irClass)) else type,
// key for local delegated properties metadata in interfaces depends on jvmDefaultMode
if (irClass.isInterface && !context.state.jvmDefaultMode.forAllMethodsWithBody) context.typeMapper.mapClass(
context.cachedDeclarations.getDefaultImplsClass(
irClass
)
) else type,
localDelegatedProperties.mapNotNull { (it.owner.metadata as? DescriptorMetadataSource.LocalDelegatedProperty)?.descriptor }
)
}
@@ -161,7 +161,9 @@ internal class InterfaceLowering(val context: JvmBackendContext) : IrElementTran
// Move $$delegatedProperties array and $assertionsDisabled field
for (field in irClass.declarations.filterIsInstance<IrField>()) {
if (field.origin != JvmLoweredDeclarationOrigin.GENERATED_PROPERTY_REFERENCE && field.origin != JvmLoweredDeclarationOrigin.GENERATED_ASSERTION_ENABLED_FIELD)
if ((jvmDefaultMode.forAllMethodsWithBody || field.origin != JvmLoweredDeclarationOrigin.GENERATED_PROPERTY_REFERENCE) &&
field.origin != JvmLoweredDeclarationOrigin.GENERATED_ASSERTION_ENABLED_FIELD
)
continue
irClass.declarations.remove(field)
@@ -24,6 +24,7 @@ import org.jetbrains.kotlin.backend.jvm.lower.inlineclasses.InlineClassAbi
import org.jetbrains.kotlin.backend.jvm.lower.inlineclasses.isInlineClassFieldGetter
import org.jetbrains.kotlin.descriptors.DescriptorVisibilities
import org.jetbrains.kotlin.descriptors.Modality
import org.jetbrains.kotlin.descriptors.Visibilities
import org.jetbrains.kotlin.ir.IrStatement
import org.jetbrains.kotlin.ir.UNDEFINED_OFFSET
import org.jetbrains.kotlin.ir.builders.*
@@ -41,6 +42,7 @@ import org.jetbrains.kotlin.ir.types.typeWith
import org.jetbrains.kotlin.ir.util.*
import org.jetbrains.kotlin.load.java.JavaDescriptorVisibilities
import org.jetbrains.kotlin.load.java.JvmAbi
import org.jetbrains.kotlin.metadata.ProtoBuf
import org.jetbrains.kotlin.name.Name
import org.jetbrains.kotlin.name.SpecialNames
import org.jetbrains.kotlin.types.Variance
@@ -191,7 +193,8 @@ private class PropertyReferenceLowering(val context: JvmBackendContext) : IrElem
origin = JvmLoweredDeclarationOrigin.GENERATED_PROPERTY_REFERENCE
isFinal = true
isStatic = true
visibility = JavaDescriptorVisibilities.PACKAGE_VISIBILITY
visibility =
if (irClass.isInterface && context.state.jvmDefaultMode.forAllMethodsWithBody) DescriptorVisibilities.PUBLIC else JavaDescriptorVisibilities.PACKAGE_VISIBILITY
}
val localProperties = mutableListOf<IrLocalDelegatedPropertySymbol>()
@@ -0,0 +1,26 @@
// CHECK_BYTECODE_LISTING
// !JVM_DEFAULT_MODE: all-compatibility
// TARGET_BACKEND: JVM
// JVM_TARGET: 1.8
// WITH_RUNTIME
// WITH_REFLECT
import kotlin.reflect.KProperty
class Delegate {
operator fun getValue(t: Any?, p: KProperty<*>): String {
return p.returnType.toString()
}
}
interface Foo {
fun test(): String {
val OK by Delegate()
return OK
}
}
fun box(): String {
return if (object : Foo {}.test() != "kotlin.String") "fail" else "OK"
}
@@ -0,0 +1,38 @@
@kotlin.Metadata
public final class Delegate {
// source: 'localDelegatedProperties.kt'
public method <init>(): void
public final @org.jetbrains.annotations.NotNull method getValue(@org.jetbrains.annotations.Nullable p0: java.lang.Object, @org.jetbrains.annotations.NotNull p1: kotlin.reflect.KProperty): java.lang.String
}
@kotlin.Metadata
public final class Foo$DefaultImpls {
// source: 'localDelegatedProperties.kt'
public deprecated static @java.lang.Deprecated @org.jetbrains.annotations.NotNull method test(@org.jetbrains.annotations.NotNull p0: Foo): java.lang.String
public final inner class Foo$DefaultImpls
}
@kotlin.Metadata
public interface Foo {
// source: 'localDelegatedProperties.kt'
public synthetic final static field $$delegatedProperties: kotlin.reflect.KProperty[]
static method <clinit>(): void
public synthetic static method access$test$jd(p0: Foo): java.lang.String
public @org.jetbrains.annotations.NotNull method test(): java.lang.String
public final inner class Foo$DefaultImpls
}
@kotlin.Metadata
public final class LocalDelegatedPropertiesKt$box$1 {
// source: 'localDelegatedProperties.kt'
enclosing method LocalDelegatedPropertiesKt.box()Ljava/lang/String;
inner (anonymous) class LocalDelegatedPropertiesKt$box$1
method <init>(): void
}
@kotlin.Metadata
public final class LocalDelegatedPropertiesKt {
// source: 'localDelegatedProperties.kt'
inner (anonymous) class LocalDelegatedPropertiesKt$box$1
public final static @org.jetbrains.annotations.NotNull method box(): java.lang.String
}
@@ -0,0 +1,41 @@
@kotlin.Metadata
public final class Delegate {
// source: 'localDelegatedProperties.kt'
public method <init>(): void
public final @org.jetbrains.annotations.NotNull method getValue(@org.jetbrains.annotations.Nullable p0: java.lang.Object, @org.jetbrains.annotations.NotNull p1: kotlin.reflect.KProperty): java.lang.String
}
@kotlin.Metadata
public final class Foo$DefaultImpls {
// source: 'localDelegatedProperties.kt'
private deprecated static @java.lang.Deprecated method test$lambda-0(p0: Delegate): java.lang.String
public deprecated static @java.lang.Deprecated @org.jetbrains.annotations.NotNull method test(@org.jetbrains.annotations.NotNull p0: Foo): java.lang.String
public final inner class Foo$DefaultImpls
}
@kotlin.Metadata
public interface Foo {
// source: 'localDelegatedProperties.kt'
public synthetic final static field $$delegatedProperties: kotlin.reflect.KProperty[]
static method <clinit>(): void
public synthetic static method access$test$jd(p0: Foo): java.lang.String
public synthetic static method access$test$lambda-0(p0: Delegate): java.lang.String
private static method test$lambda-0(p0: Delegate): java.lang.String
public @org.jetbrains.annotations.NotNull method test(): java.lang.String
public final inner class Foo$DefaultImpls
}
@kotlin.Metadata
public final class LocalDelegatedPropertiesKt$box$1 {
// source: 'localDelegatedProperties.kt'
enclosing method LocalDelegatedPropertiesKt.box()Ljava/lang/String;
inner (anonymous) class LocalDelegatedPropertiesKt$box$1
method <init>(): void
}
@kotlin.Metadata
public final class LocalDelegatedPropertiesKt {
// source: 'localDelegatedProperties.kt'
inner (anonymous) class LocalDelegatedPropertiesKt$box$1
public final static @org.jetbrains.annotations.NotNull method box(): java.lang.String
}
@@ -0,0 +1,26 @@
// CHECK_BYTECODE_LISTING
// !JVM_DEFAULT_MODE: all
// TARGET_BACKEND: JVM
// JVM_TARGET: 1.8
// WITH_REFLECT
import kotlin.reflect.KProperty
class Delegate {
operator fun getValue(t: Any?, p: KProperty<*>): String {
return p.returnType.toString()
}
}
interface Foo {
fun test(): String {
val OK by Delegate()
return OK
}
}
fun box(): String {
return if (object : Foo {}.test() != "kotlin.String") "fail" else "OK"
}
@@ -0,0 +1,29 @@
@kotlin.Metadata
public final class Delegate {
// source: 'localDelegatedProperties.kt'
public method <init>(): void
public final @org.jetbrains.annotations.NotNull method getValue(@org.jetbrains.annotations.Nullable p0: java.lang.Object, @org.jetbrains.annotations.NotNull p1: kotlin.reflect.KProperty): java.lang.String
}
@kotlin.Metadata
public interface Foo {
// source: 'localDelegatedProperties.kt'
public synthetic final static field $$delegatedProperties: kotlin.reflect.KProperty[]
static method <clinit>(): void
public @org.jetbrains.annotations.NotNull method test(): java.lang.String
}
@kotlin.Metadata
public final class LocalDelegatedPropertiesKt$box$1 {
// source: 'localDelegatedProperties.kt'
enclosing method LocalDelegatedPropertiesKt.box()Ljava/lang/String;
inner (anonymous) class LocalDelegatedPropertiesKt$box$1
method <init>(): void
}
@kotlin.Metadata
public final class LocalDelegatedPropertiesKt {
// source: 'localDelegatedProperties.kt'
inner (anonymous) class LocalDelegatedPropertiesKt$box$1
public final static @org.jetbrains.annotations.NotNull method box(): java.lang.String
}
@@ -0,0 +1,29 @@
// !JVM_DEFAULT_MODE: all
// TARGET_BACKEND: JVM
// JVM_TARGET: 1.8
import kotlin.reflect.KProperty
class Delegate {
operator fun getValue(t: Any?, p: KProperty<*>): String = p.name
}
interface Foo {
fun test(): String {
val O by Delegate()
return O
}
}
interface Foo2: Foo {
override fun test(): String {
val K by Delegate()
return super.test() + K
}
}
fun box(): String {
return object : Foo2 {}.test()
}
@@ -0,0 +1,30 @@
@kotlin.Metadata
public final class Delegate {
// source: 'localDelegatedProperties.kt'
public method <init>(): void
public final @org.jetbrains.annotations.NotNull method getValue(@org.jetbrains.annotations.Nullable p0: java.lang.Object, @org.jetbrains.annotations.NotNull p1: kotlin.reflect.KProperty): java.lang.String
}
@kotlin.Metadata
public interface Foo {
// source: 'localDelegatedProperties.kt'
public synthetic final static field $$delegatedProperties: kotlin.reflect.KProperty[]
static method <clinit>(): void
private static method test$lambda-0(p0: Delegate): java.lang.String
public @org.jetbrains.annotations.NotNull method test(): java.lang.String
}
@kotlin.Metadata
public final class LocalDelegatedPropertiesKt$box$1 {
// source: 'localDelegatedProperties.kt'
enclosing method LocalDelegatedPropertiesKt.box()Ljava/lang/String;
inner (anonymous) class LocalDelegatedPropertiesKt$box$1
method <init>(): void
}
@kotlin.Metadata
public final class LocalDelegatedPropertiesKt {
// source: 'localDelegatedProperties.kt'
inner (anonymous) class LocalDelegatedPropertiesKt$box$1
public final static @org.jetbrains.annotations.NotNull method box(): java.lang.String
}
@@ -21996,6 +21996,12 @@ public class BlackBoxCodegenTestGenerated extends AbstractBlackBoxCodegenTest {
runTest("compiler/testData/codegen/box/jvm8/defaults/allCompatibility/kt42674.kt");
}
@Test
@TestMetadata("localDelegatedProperties.kt")
public void testLocalDelegatedProperties() throws Exception {
runTest("compiler/testData/codegen/box/jvm8/defaults/allCompatibility/localDelegatedProperties.kt");
}
@Test
@TestMetadata("privateFunInInterface.kt")
public void testPrivateFunInInterface() throws Exception {
@@ -22330,6 +22336,18 @@ public class BlackBoxCodegenTestGenerated extends AbstractBlackBoxCodegenTest {
runTest("compiler/testData/codegen/box/jvm8/defaults/noDefaultImpls/kt42674.kt");
}
@Test
@TestMetadata("localDelegatedProperties.kt")
public void testLocalDelegatedProperties() throws Exception {
runTest("compiler/testData/codegen/box/jvm8/defaults/noDefaultImpls/localDelegatedProperties.kt");
}
@Test
@TestMetadata("localDelegatedProperties2.kt")
public void testLocalDelegatedProperties2() throws Exception {
runTest("compiler/testData/codegen/box/jvm8/defaults/noDefaultImpls/localDelegatedProperties2.kt");
}
@Test
@TestMetadata("privateFunInInterface.kt")
public void testPrivateFunInInterface() throws Exception {
@@ -21996,6 +21996,12 @@ public class IrBlackBoxCodegenTestGenerated extends AbstractIrBlackBoxCodegenTes
runTest("compiler/testData/codegen/box/jvm8/defaults/allCompatibility/kt42674.kt");
}
@Test
@TestMetadata("localDelegatedProperties.kt")
public void testLocalDelegatedProperties() throws Exception {
runTest("compiler/testData/codegen/box/jvm8/defaults/allCompatibility/localDelegatedProperties.kt");
}
@Test
@TestMetadata("privateFunInInterface.kt")
public void testPrivateFunInInterface() throws Exception {
@@ -22330,6 +22336,18 @@ public class IrBlackBoxCodegenTestGenerated extends AbstractIrBlackBoxCodegenTes
runTest("compiler/testData/codegen/box/jvm8/defaults/noDefaultImpls/kt42674.kt");
}
@Test
@TestMetadata("localDelegatedProperties.kt")
public void testLocalDelegatedProperties() throws Exception {
runTest("compiler/testData/codegen/box/jvm8/defaults/noDefaultImpls/localDelegatedProperties.kt");
}
@Test
@TestMetadata("localDelegatedProperties2.kt")
public void testLocalDelegatedProperties2() throws Exception {
runTest("compiler/testData/codegen/box/jvm8/defaults/noDefaultImpls/localDelegatedProperties2.kt");
}
@Test
@TestMetadata("privateFunInInterface.kt")
public void testPrivateFunInInterface() throws Exception {
@@ -7522,11 +7522,6 @@ public class LightAnalysisModeTestGenerated extends AbstractLightAnalysisModeTes
runTest("compiler/testData/codegen/box/coroutines/featureIntersection/funInterface.kt");
}
@TestMetadata("jvmDefault.kt")
public void ignoreJvmDefault() throws Exception {
runTest("compiler/testData/codegen/box/coroutines/featureIntersection/jvmDefault.kt");
}
private void runTest(String testDataFilePath) throws Exception {
KotlinTestUtils.runTest(this::doTest, TargetBackend.JVM, testDataFilePath);
}
@@ -7570,6 +7565,11 @@ public class LightAnalysisModeTestGenerated extends AbstractLightAnalysisModeTes
runTest("compiler/testData/codegen/box/coroutines/featureIntersection/interfaceMethodWithBodyGeneric.kt");
}
@TestMetadata("jvmDefault.kt")
public void testJvmDefault() throws Exception {
runTest("compiler/testData/codegen/box/coroutines/featureIntersection/jvmDefault.kt");
}
@TestMetadata("overrideInInlineClass.kt")
public void testOverrideInInlineClass() throws Exception {
runTest("compiler/testData/codegen/box/coroutines/featureIntersection/overrideInInlineClass.kt");
@@ -18378,6 +18378,11 @@ public class LightAnalysisModeTestGenerated extends AbstractLightAnalysisModeTes
@TestDataPath("$PROJECT_ROOT")
@RunWith(JUnit3RunnerWithInners.class)
public static class AllCompatibility extends AbstractLightAnalysisModeTest {
@TestMetadata("privateSuspend.kt")
public void ignorePrivateSuspend() throws Exception {
runTest("compiler/testData/codegen/box/jvm8/defaults/allCompatibility/privateSuspend.kt");
}
@TestMetadata("suspendFunction.kt")
public void ignoreSuspendFunction() throws Exception {
runTest("compiler/testData/codegen/box/jvm8/defaults/allCompatibility/suspendFunction.kt");
@@ -18516,16 +18521,16 @@ public class LightAnalysisModeTestGenerated extends AbstractLightAnalysisModeTes
runTest("compiler/testData/codegen/box/jvm8/defaults/allCompatibility/kt42674.kt");
}
@TestMetadata("localDelegatedProperties.kt")
public void testLocalDelegatedProperties() throws Exception {
runTest("compiler/testData/codegen/box/jvm8/defaults/allCompatibility/localDelegatedProperties.kt");
}
@TestMetadata("privateFunInInterface.kt")
public void testPrivateFunInInterface() throws Exception {
runTest("compiler/testData/codegen/box/jvm8/defaults/allCompatibility/privateFunInInterface.kt");
}
@TestMetadata("privateSuspend.kt")
public void testPrivateSuspend() throws Exception {
runTest("compiler/testData/codegen/box/jvm8/defaults/allCompatibility/privateSuspend.kt");
}
@TestMetadata("propertyAnnotation.kt")
public void testPropertyAnnotation() throws Exception {
runTest("compiler/testData/codegen/box/jvm8/defaults/allCompatibility/propertyAnnotation.kt");
@@ -18808,6 +18813,16 @@ public class LightAnalysisModeTestGenerated extends AbstractLightAnalysisModeTes
runTest("compiler/testData/codegen/box/jvm8/defaults/noDefaultImpls/kt42674.kt");
}
@TestMetadata("localDelegatedProperties.kt")
public void testLocalDelegatedProperties() throws Exception {
runTest("compiler/testData/codegen/box/jvm8/defaults/noDefaultImpls/localDelegatedProperties.kt");
}
@TestMetadata("localDelegatedProperties2.kt")
public void testLocalDelegatedProperties2() throws Exception {
runTest("compiler/testData/codegen/box/jvm8/defaults/noDefaultImpls/localDelegatedProperties2.kt");
}
@TestMetadata("privateFunInInterface.kt")
public void testPrivateFunInInterface() throws Exception {
runTest("compiler/testData/codegen/box/jvm8/defaults/noDefaultImpls/privateFunInInterface.kt");