Use isJvmInterface in JVM back-end instead of isInterface
To support const vals and proper initialization order for companions of annotations (since 1.3+) as well as interfaces #KT-16962 Fixed
This commit is contained in:
@@ -781,7 +781,7 @@ public class AsmUtil {
|
||||
public static boolean isPropertyWithBackingFieldCopyInOuterClass(@NotNull PropertyDescriptor propertyDescriptor) {
|
||||
DeclarationDescriptor propertyContainer = propertyDescriptor.getContainingDeclaration();
|
||||
return propertyDescriptor.isConst()
|
||||
&& isCompanionObject(propertyContainer) && isInterface(propertyContainer.getContainingDeclaration())
|
||||
&& isCompanionObject(propertyContainer) && isJvmInterface(propertyContainer.getContainingDeclaration())
|
||||
&& getVisibilityForBackingField(propertyDescriptor, false) == ACC_PUBLIC;
|
||||
}
|
||||
|
||||
|
||||
@@ -52,7 +52,8 @@ import org.jetbrains.kotlin.resolve.DelegationResolver;
|
||||
import org.jetbrains.kotlin.resolve.DescriptorToSourceUtils;
|
||||
import org.jetbrains.kotlin.resolve.DescriptorUtils;
|
||||
import org.jetbrains.kotlin.resolve.calls.callUtil.CallUtilKt;
|
||||
import org.jetbrains.kotlin.resolve.calls.model.*;
|
||||
import org.jetbrains.kotlin.resolve.calls.model.ResolvedCall;
|
||||
import org.jetbrains.kotlin.resolve.calls.model.VariableAsFunctionResolvedCall;
|
||||
import org.jetbrains.kotlin.resolve.descriptorUtil.DescriptorUtilsKt;
|
||||
import org.jetbrains.kotlin.resolve.jvm.diagnostics.JvmDeclarationOrigin;
|
||||
import org.jetbrains.kotlin.resolve.jvm.diagnostics.JvmDeclarationOriginKt;
|
||||
@@ -64,7 +65,10 @@ import org.jetbrains.kotlin.resolve.scopes.receivers.ExtensionReceiver;
|
||||
import org.jetbrains.kotlin.resolve.scopes.receivers.ImplicitReceiver;
|
||||
import org.jetbrains.kotlin.resolve.scopes.receivers.ReceiverValue;
|
||||
import org.jetbrains.kotlin.types.KotlinType;
|
||||
import org.jetbrains.org.objectweb.asm.*;
|
||||
import org.jetbrains.org.objectweb.asm.FieldVisitor;
|
||||
import org.jetbrains.org.objectweb.asm.Label;
|
||||
import org.jetbrains.org.objectweb.asm.MethodVisitor;
|
||||
import org.jetbrains.org.objectweb.asm.Type;
|
||||
import org.jetbrains.org.objectweb.asm.commons.InstructionAdapter;
|
||||
import org.jetbrains.org.objectweb.asm.commons.Method;
|
||||
|
||||
@@ -974,7 +978,7 @@ public class ImplementationBodyCodegen extends ClassBodyCodegen {
|
||||
}
|
||||
|
||||
private void generatePrimaryConstructor(DelegationFieldsInfo delegationFieldsInfo) {
|
||||
if (isInterface(descriptor) || isAnnotationClass(descriptor)) return;
|
||||
if (isJvmInterface(descriptor)) return;
|
||||
|
||||
ClassConstructorDescriptor constructorDescriptor = descriptor.getUnsubstitutedPrimaryConstructor();
|
||||
if (constructorDescriptor == null) return;
|
||||
|
||||
@@ -31,6 +31,7 @@ import org.jetbrains.kotlin.codegen.state.GenerationState;
|
||||
import org.jetbrains.kotlin.codegen.state.KotlinTypeMapper;
|
||||
import org.jetbrains.kotlin.descriptors.*;
|
||||
import org.jetbrains.kotlin.descriptors.impl.LocalVariableDescriptor;
|
||||
import org.jetbrains.kotlin.load.java.JvmAbi;
|
||||
import org.jetbrains.kotlin.load.java.descriptors.JavaCallableMemberDescriptor;
|
||||
import org.jetbrains.kotlin.load.java.descriptors.JavaPropertyDescriptor;
|
||||
import org.jetbrains.kotlin.load.kotlin.*;
|
||||
@@ -57,6 +58,7 @@ import static org.jetbrains.kotlin.descriptors.ClassKind.INTERFACE;
|
||||
import static org.jetbrains.kotlin.descriptors.Modality.ABSTRACT;
|
||||
import static org.jetbrains.kotlin.descriptors.Modality.FINAL;
|
||||
import static org.jetbrains.kotlin.resolve.BindingContext.DELEGATED_PROPERTY_CALL;
|
||||
import static org.jetbrains.kotlin.resolve.DescriptorUtils.isCompanionObject;
|
||||
import static org.jetbrains.kotlin.resolve.jvm.annotations.AnnotationUtilKt.hasJvmFieldAnnotation;
|
||||
|
||||
public class JvmCodegenUtil {
|
||||
@@ -330,4 +332,10 @@ public class JvmCodegenUtil {
|
||||
|
||||
return receiver;
|
||||
}
|
||||
|
||||
public static boolean isCompanionObjectInInterfaceNotIntrinsic(@NotNull DeclarationDescriptor companionObject) {
|
||||
return isCompanionObject(companionObject) &&
|
||||
isJvmInterface(companionObject.getContainingDeclaration()) &&
|
||||
!JvmAbi.isMappedIntrinsicCompanionObject((ClassDescriptor) companionObject);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -429,7 +429,7 @@ fun ExpressionCodegen.generateCallSingleArgument(call: ResolvedCall<out Callable
|
||||
|
||||
fun ClassDescriptor.isPossiblyUninitializedSingleton() =
|
||||
DescriptorUtils.isEnumEntry(this) ||
|
||||
DescriptorUtils.isCompanionObject(this) && DescriptorUtils.isInterface(this.containingDeclaration)
|
||||
DescriptorUtils.isCompanionObject(this) && JvmCodegenUtil.isJvmInterface(this.containingDeclaration)
|
||||
|
||||
val CodegenContext<*>.parentContextsWithSelf
|
||||
get() = generateSequence(this) { it.parentContext }
|
||||
@@ -438,4 +438,4 @@ val CodegenContext<*>.parentContexts
|
||||
get() = parentContext?.parentContextsWithSelf ?: emptySequence()
|
||||
|
||||
val CodegenContext<*>.contextStackText
|
||||
get() = parentContextsWithSelf.joinToString(separator = "\n") { it.toString() }
|
||||
get() = parentContextsWithSelf.joinToString(separator = "\n") { it.toString() }
|
||||
|
||||
+1
-1
@@ -188,7 +188,7 @@ class ClassCodegen private constructor(
|
||||
|
||||
fun ClassDescriptor.calculateClassFlags(): Int {
|
||||
var flags = 0
|
||||
flags = flags or if (DescriptorUtils.isInterface(this) || DescriptorUtils.isAnnotationClass(this)) Opcodes.ACC_INTERFACE else Opcodes.ACC_SUPER
|
||||
flags = flags or if (JvmCodegenUtil.isJvmInterface(this)) Opcodes.ACC_INTERFACE else Opcodes.ACC_SUPER
|
||||
flags = flags or calcModalityFlag()
|
||||
flags = flags or AsmUtil.getVisibilityAccessFlagForClass(this)
|
||||
flags = flags or if (kind == ClassKind.ENUM_CLASS) Opcodes.ACC_ENUM else 0
|
||||
|
||||
+1
-1
@@ -32,7 +32,7 @@ import org.jetbrains.kotlin.ir.expressions.IrExpression
|
||||
import org.jetbrains.kotlin.ir.expressions.impl.IrCallImpl
|
||||
import org.jetbrains.kotlin.ir.expressions.impl.IrExpressionBodyImpl
|
||||
import org.jetbrains.kotlin.ir.expressions.impl.IrGetFieldImpl
|
||||
import org.jetbrains.kotlin.load.java.JvmAbi.isCompanionObjectInInterfaceNotIntrinsic
|
||||
import org.jetbrains.kotlin.codegen.JvmCodegenUtil.isCompanionObjectInInterfaceNotIntrinsic
|
||||
|
||||
class ObjectClassLowering(val context: JvmBackendContext) : IrElementTransformerVoidWithContext(), FileLoweringPass {
|
||||
|
||||
|
||||
@@ -0,0 +1,19 @@
|
||||
// !LANGUAGE: +NestedClassesInAnnotations
|
||||
// WITH_RUNTIME
|
||||
// TARGET_BACKEND: JVM
|
||||
// FILE: Foo.java
|
||||
|
||||
@Anno(Anno.CONST)
|
||||
public class Foo {}
|
||||
|
||||
// FILE: Anno.kt
|
||||
|
||||
annotation class Anno(val value: Int) {
|
||||
companion object {
|
||||
const val CONST = 42
|
||||
}
|
||||
}
|
||||
|
||||
fun box(): String =
|
||||
if ((Foo::class.java.annotations.single() as Anno).value == 42) "OK" else "Fail"
|
||||
|
||||
+35
-2
@@ -1,10 +1,11 @@
|
||||
// !LANGUAGE: +NestedClassesInAnnotations
|
||||
// WITH_RUNTIME
|
||||
|
||||
import kotlin.test.*
|
||||
|
||||
interface Test {
|
||||
companion object {
|
||||
val x = "OK"
|
||||
val x = "O"
|
||||
|
||||
val y1 = Test.x
|
||||
|
||||
@@ -34,4 +35,36 @@ interface Test {
|
||||
}
|
||||
}
|
||||
|
||||
fun box() = Test.x
|
||||
annotation class Anno {
|
||||
companion object {
|
||||
val x = "K"
|
||||
|
||||
val y1 = Anno.x
|
||||
|
||||
val y2 = 42.let { x }
|
||||
|
||||
val y3: String
|
||||
init {
|
||||
fun localFun() = x
|
||||
y3 = localFun()
|
||||
}
|
||||
|
||||
fun method() = x
|
||||
val y4 = method()
|
||||
|
||||
val anonObject = object {
|
||||
override fun toString() = x
|
||||
}
|
||||
val y5 = anonObject.toString()
|
||||
|
||||
init {
|
||||
assertEquals(x, y1)
|
||||
assertEquals(x, y2)
|
||||
assertEquals(x, y3)
|
||||
assertEquals(x, y4)
|
||||
assertEquals(x, y5)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fun box() = Test.x + Anno.x
|
||||
|
||||
Generated
+6
@@ -69,6 +69,12 @@ public class IrBlackBoxCodegenTestGenerated extends AbstractIrBlackBoxCodegenTes
|
||||
doTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("constValInAnnotation.kt")
|
||||
public void testConstValInAnnotation() throws Exception {
|
||||
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/annotations/constValInAnnotation.kt");
|
||||
doTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("defaultParameterValues.kt")
|
||||
public void testDefaultParameterValues() throws Exception {
|
||||
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/annotations/defaultParameterValues.kt");
|
||||
|
||||
+6
@@ -69,6 +69,12 @@ public class BlackBoxCodegenTestGenerated extends AbstractBlackBoxCodegenTest {
|
||||
doTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("constValInAnnotation.kt")
|
||||
public void testConstValInAnnotation() throws Exception {
|
||||
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/annotations/constValInAnnotation.kt");
|
||||
doTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("defaultParameterValues.kt")
|
||||
public void testDefaultParameterValues() throws Exception {
|
||||
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/annotations/defaultParameterValues.kt");
|
||||
|
||||
+6
@@ -81,6 +81,12 @@ public class LightAnalysisModeTestGenerated extends AbstractLightAnalysisModeTes
|
||||
doTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("constValInAnnotation.kt")
|
||||
public void testConstValInAnnotation() throws Exception {
|
||||
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/annotations/constValInAnnotation.kt");
|
||||
doTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("defaultParameterValues.kt")
|
||||
public void testDefaultParameterValues() throws Exception {
|
||||
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/annotations/defaultParameterValues.kt");
|
||||
|
||||
@@ -29,7 +29,6 @@ import org.jetbrains.kotlin.util.capitalizeDecapitalize.CapitalizeDecapitalizeKt
|
||||
|
||||
import static org.jetbrains.kotlin.resolve.DescriptorUtils.isClassOrEnumClass;
|
||||
import static org.jetbrains.kotlin.resolve.DescriptorUtils.isCompanionObject;
|
||||
import static org.jetbrains.kotlin.resolve.DescriptorUtils.isInterface;
|
||||
|
||||
public final class JvmAbi {
|
||||
public static final String DEFAULT_IMPLS_CLASS_NAME = "DefaultImpls";
|
||||
@@ -118,10 +117,4 @@ public final class JvmAbi {
|
||||
public static boolean isMappedIntrinsicCompanionObject(@NotNull ClassDescriptor companionObject) {
|
||||
return CompanionObjectMapping.INSTANCE.isMappedIntrinsicCompanionObject(companionObject);
|
||||
}
|
||||
|
||||
public static boolean isCompanionObjectInInterfaceNotIntrinsic(@NotNull DeclarationDescriptor companionObject) {
|
||||
return isCompanionObject(companionObject) &&
|
||||
isInterface(companionObject.getContainingDeclaration()) &&
|
||||
!isMappedIntrinsicCompanionObject((ClassDescriptor) companionObject);
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user