Use 'DefaultImpls' as owner for interface local delegated properties

#KT-19690 Fixed
This commit is contained in:
Mikhael Bogdanov
2017-08-16 16:35:31 +02:00
parent 905b8cc4e9
commit 97d46e76f5
7 changed files with 59 additions and 11 deletions
@@ -22,20 +22,14 @@ import org.jetbrains.kotlin.backend.common.bridges.firstSuperMethodFromKotlin
import org.jetbrains.kotlin.codegen.context.ClassContext
import org.jetbrains.kotlin.codegen.state.GenerationState
import org.jetbrains.kotlin.descriptors.*
import org.jetbrains.kotlin.descriptors.impl.ClassDescriptorImpl
import org.jetbrains.kotlin.load.java.JvmAbi
import org.jetbrains.kotlin.load.java.descriptors.JavaMethodDescriptor
import org.jetbrains.kotlin.name.Name
import org.jetbrains.kotlin.psi.KtPureClassOrObject
import org.jetbrains.kotlin.resolve.DescriptorToSourceUtils
import org.jetbrains.kotlin.resolve.DescriptorUtils
import org.jetbrains.kotlin.resolve.jvm.diagnostics.JvmDeclarationOrigin
import org.jetbrains.kotlin.resolve.jvm.diagnostics.JvmDeclarationOriginKind
import org.jetbrains.kotlin.resolve.jvm.jvmSignature.JvmMethodSignature
import org.jetbrains.kotlin.resolve.scopes.MemberScope
import org.jetbrains.org.objectweb.asm.MethodVisitor
import org.jetbrains.org.objectweb.asm.Opcodes.*
import java.util.*
class InterfaceImplBodyCodegen(
aClass: KtPureClassOrObject,
@@ -47,12 +41,14 @@ class InterfaceImplBodyCodegen(
private var isAnythingGenerated: Boolean = false
get() = (v as InterfaceImplClassBuilder).isAnythingGenerated
private val defaultImplType = typeMapper.mapDefaultImpls(descriptor)
override fun generateDeclaration() {
val codegenFlags = ACC_PUBLIC or ACC_FINAL or ACC_SUPER
val flags = if (state.classBuilderMode == ClassBuilderMode.LIGHT_CLASSES) codegenFlags or ACC_STATIC else codegenFlags
v.defineClass(
myClass.psiOrParent, state.classFileVersion, flags,
typeMapper.mapDefaultImpls(descriptor).internalName,
defaultImplType.internalName,
null, "java/lang/Object", ArrayUtil.EMPTY_STRING_ARRAY
)
v.visitSource(myClass.containingKtFile.name, null)
@@ -154,7 +150,7 @@ class InterfaceImplBodyCodegen(
override fun done() {
super.done()
if (!isAnythingGenerated) {
state.factory.removeClasses(setOf(typeMapper.mapDefaultImpls(descriptor).internalName))
state.factory.removeClasses(setOf(defaultImplType.internalName))
}
}
@@ -183,4 +179,8 @@ class InterfaceImplBodyCodegen(
return super.newMethod(origin, access, name, desc, signature, exceptions)
}
}
override fun generateSyntheticPartsBeforeBody() {
generatePropertyMetadataArrayFieldIfNeeded(defaultImplType)
}
}
@@ -38,6 +38,7 @@ import org.jetbrains.kotlin.descriptors.annotations.Annotations;
import org.jetbrains.kotlin.descriptors.impl.LocalVariableDescriptor;
import org.jetbrains.kotlin.fileClasses.FileClasses;
import org.jetbrains.kotlin.fileClasses.JvmFileClassesProvider;
import org.jetbrains.kotlin.load.java.JvmAbi;
import org.jetbrains.kotlin.load.java.sam.SamConstructorDescriptor;
import org.jetbrains.kotlin.load.kotlin.TypeMappingConfiguration;
import org.jetbrains.kotlin.name.ClassId;
@@ -440,9 +441,15 @@ class CodegenAnnotatingVisitor extends KtVisitorVoid {
// The first "real" containing class (not a synthetic class for lambda) is the owner of the delegated property metadata
if (!(descriptor instanceof SyntheticClassDescriptorForLambda)) {
ClassId classId = DescriptorUtilsKt.getClassId(descriptor);
return classId != null
? AsmUtil.asmTypeByClassId(classId)
: CodegenBinding.getAsmType(bindingContext, descriptor);
if (classId == null) {
return CodegenBinding.getAsmType(bindingContext, descriptor);
}
return AsmUtil.asmTypeByClassId(
DescriptorUtils.isInterface(descriptor)
? classId.createNestedClassId(Name.identifier(JvmAbi.DEFAULT_IMPLS_CLASS_NAME))
: classId
);
}
}
@@ -0,0 +1,17 @@
//WITH_REFLECT
import kotlin.properties.Delegates
interface MyInterface {
fun something(): String {
var foo: String by Delegates.notNull();
foo = "OK"
return foo
}
}
fun box(): String {
return object : MyInterface {
}.something()
}
@@ -7012,6 +7012,12 @@ public class IrBlackBoxCodegenTestGenerated extends AbstractIrBlackBoxCodegenTes
doTest(fileName);
}
@TestMetadata("kt19690.kt")
public void testKt19690() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/delegatedProperty/local/kt19690.kt");
doTest(fileName);
}
@TestMetadata("localVal.kt")
public void testLocalVal() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/delegatedProperty/local/localVal.kt");
@@ -7012,6 +7012,12 @@ public class BlackBoxCodegenTestGenerated extends AbstractBlackBoxCodegenTest {
doTest(fileName);
}
@TestMetadata("kt19690.kt")
public void testKt19690() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/delegatedProperty/local/kt19690.kt");
doTest(fileName);
}
@TestMetadata("localVal.kt")
public void testLocalVal() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/delegatedProperty/local/localVal.kt");
@@ -7012,6 +7012,12 @@ public class LightAnalysisModeTestGenerated extends AbstractLightAnalysisModeTes
doTest(fileName);
}
@TestMetadata("kt19690.kt")
public void testKt19690() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/delegatedProperty/local/kt19690.kt");
doTest(fileName);
}
@TestMetadata("localVal.kt")
public void testLocalVal() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/delegatedProperty/local/localVal.kt");
@@ -7798,6 +7798,12 @@ public class JsCodegenBoxTestGenerated extends AbstractJsCodegenBoxTest {
doTest(fileName);
}
@TestMetadata("kt19690.kt")
public void testKt19690() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/delegatedProperty/local/kt19690.kt");
doTest(fileName);
}
@TestMetadata("localVal.kt")
public void testLocalVal() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/delegatedProperty/local/localVal.kt");