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) {
|
public static boolean isPropertyWithBackingFieldCopyInOuterClass(@NotNull PropertyDescriptor propertyDescriptor) {
|
||||||
DeclarationDescriptor propertyContainer = propertyDescriptor.getContainingDeclaration();
|
DeclarationDescriptor propertyContainer = propertyDescriptor.getContainingDeclaration();
|
||||||
return propertyDescriptor.isConst()
|
return propertyDescriptor.isConst()
|
||||||
&& isCompanionObject(propertyContainer) && isInterface(propertyContainer.getContainingDeclaration())
|
&& isCompanionObject(propertyContainer) && isJvmInterface(propertyContainer.getContainingDeclaration())
|
||||||
&& getVisibilityForBackingField(propertyDescriptor, false) == ACC_PUBLIC;
|
&& 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.DescriptorToSourceUtils;
|
||||||
import org.jetbrains.kotlin.resolve.DescriptorUtils;
|
import org.jetbrains.kotlin.resolve.DescriptorUtils;
|
||||||
import org.jetbrains.kotlin.resolve.calls.callUtil.CallUtilKt;
|
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.descriptorUtil.DescriptorUtilsKt;
|
||||||
import org.jetbrains.kotlin.resolve.jvm.diagnostics.JvmDeclarationOrigin;
|
import org.jetbrains.kotlin.resolve.jvm.diagnostics.JvmDeclarationOrigin;
|
||||||
import org.jetbrains.kotlin.resolve.jvm.diagnostics.JvmDeclarationOriginKt;
|
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.ImplicitReceiver;
|
||||||
import org.jetbrains.kotlin.resolve.scopes.receivers.ReceiverValue;
|
import org.jetbrains.kotlin.resolve.scopes.receivers.ReceiverValue;
|
||||||
import org.jetbrains.kotlin.types.KotlinType;
|
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.InstructionAdapter;
|
||||||
import org.jetbrains.org.objectweb.asm.commons.Method;
|
import org.jetbrains.org.objectweb.asm.commons.Method;
|
||||||
|
|
||||||
@@ -974,7 +978,7 @@ public class ImplementationBodyCodegen extends ClassBodyCodegen {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private void generatePrimaryConstructor(DelegationFieldsInfo delegationFieldsInfo) {
|
private void generatePrimaryConstructor(DelegationFieldsInfo delegationFieldsInfo) {
|
||||||
if (isInterface(descriptor) || isAnnotationClass(descriptor)) return;
|
if (isJvmInterface(descriptor)) return;
|
||||||
|
|
||||||
ClassConstructorDescriptor constructorDescriptor = descriptor.getUnsubstitutedPrimaryConstructor();
|
ClassConstructorDescriptor constructorDescriptor = descriptor.getUnsubstitutedPrimaryConstructor();
|
||||||
if (constructorDescriptor == null) return;
|
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.codegen.state.KotlinTypeMapper;
|
||||||
import org.jetbrains.kotlin.descriptors.*;
|
import org.jetbrains.kotlin.descriptors.*;
|
||||||
import org.jetbrains.kotlin.descriptors.impl.LocalVariableDescriptor;
|
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.JavaCallableMemberDescriptor;
|
||||||
import org.jetbrains.kotlin.load.java.descriptors.JavaPropertyDescriptor;
|
import org.jetbrains.kotlin.load.java.descriptors.JavaPropertyDescriptor;
|
||||||
import org.jetbrains.kotlin.load.kotlin.*;
|
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.ABSTRACT;
|
||||||
import static org.jetbrains.kotlin.descriptors.Modality.FINAL;
|
import static org.jetbrains.kotlin.descriptors.Modality.FINAL;
|
||||||
import static org.jetbrains.kotlin.resolve.BindingContext.DELEGATED_PROPERTY_CALL;
|
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;
|
import static org.jetbrains.kotlin.resolve.jvm.annotations.AnnotationUtilKt.hasJvmFieldAnnotation;
|
||||||
|
|
||||||
public class JvmCodegenUtil {
|
public class JvmCodegenUtil {
|
||||||
@@ -330,4 +332,10 @@ public class JvmCodegenUtil {
|
|||||||
|
|
||||||
return receiver;
|
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() =
|
fun ClassDescriptor.isPossiblyUninitializedSingleton() =
|
||||||
DescriptorUtils.isEnumEntry(this) ||
|
DescriptorUtils.isEnumEntry(this) ||
|
||||||
DescriptorUtils.isCompanionObject(this) && DescriptorUtils.isInterface(this.containingDeclaration)
|
DescriptorUtils.isCompanionObject(this) && JvmCodegenUtil.isJvmInterface(this.containingDeclaration)
|
||||||
|
|
||||||
val CodegenContext<*>.parentContextsWithSelf
|
val CodegenContext<*>.parentContextsWithSelf
|
||||||
get() = generateSequence(this) { it.parentContext }
|
get() = generateSequence(this) { it.parentContext }
|
||||||
|
|||||||
+1
-1
@@ -188,7 +188,7 @@ class ClassCodegen private constructor(
|
|||||||
|
|
||||||
fun ClassDescriptor.calculateClassFlags(): Int {
|
fun ClassDescriptor.calculateClassFlags(): Int {
|
||||||
var flags = 0
|
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 calcModalityFlag()
|
||||||
flags = flags or AsmUtil.getVisibilityAccessFlagForClass(this)
|
flags = flags or AsmUtil.getVisibilityAccessFlagForClass(this)
|
||||||
flags = flags or if (kind == ClassKind.ENUM_CLASS) Opcodes.ACC_ENUM else 0
|
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.IrCallImpl
|
||||||
import org.jetbrains.kotlin.ir.expressions.impl.IrExpressionBodyImpl
|
import org.jetbrains.kotlin.ir.expressions.impl.IrExpressionBodyImpl
|
||||||
import org.jetbrains.kotlin.ir.expressions.impl.IrGetFieldImpl
|
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 {
|
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
|
// WITH_RUNTIME
|
||||||
|
|
||||||
import kotlin.test.*
|
import kotlin.test.*
|
||||||
|
|
||||||
interface Test {
|
interface Test {
|
||||||
companion object {
|
companion object {
|
||||||
val x = "OK"
|
val x = "O"
|
||||||
|
|
||||||
val y1 = Test.x
|
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);
|
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")
|
@TestMetadata("defaultParameterValues.kt")
|
||||||
public void testDefaultParameterValues() throws Exception {
|
public void testDefaultParameterValues() throws Exception {
|
||||||
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/annotations/defaultParameterValues.kt");
|
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/annotations/defaultParameterValues.kt");
|
||||||
|
|||||||
+6
@@ -69,6 +69,12 @@ public class BlackBoxCodegenTestGenerated extends AbstractBlackBoxCodegenTest {
|
|||||||
doTest(fileName);
|
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")
|
@TestMetadata("defaultParameterValues.kt")
|
||||||
public void testDefaultParameterValues() throws Exception {
|
public void testDefaultParameterValues() throws Exception {
|
||||||
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/annotations/defaultParameterValues.kt");
|
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/annotations/defaultParameterValues.kt");
|
||||||
|
|||||||
+6
@@ -81,6 +81,12 @@ public class LightAnalysisModeTestGenerated extends AbstractLightAnalysisModeTes
|
|||||||
doTest(fileName);
|
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")
|
@TestMetadata("defaultParameterValues.kt")
|
||||||
public void testDefaultParameterValues() throws Exception {
|
public void testDefaultParameterValues() throws Exception {
|
||||||
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/annotations/defaultParameterValues.kt");
|
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.isClassOrEnumClass;
|
||||||
import static org.jetbrains.kotlin.resolve.DescriptorUtils.isCompanionObject;
|
import static org.jetbrains.kotlin.resolve.DescriptorUtils.isCompanionObject;
|
||||||
import static org.jetbrains.kotlin.resolve.DescriptorUtils.isInterface;
|
|
||||||
|
|
||||||
public final class JvmAbi {
|
public final class JvmAbi {
|
||||||
public static final String DEFAULT_IMPLS_CLASS_NAME = "DefaultImpls";
|
public static final String DEFAULT_IMPLS_CLASS_NAME = "DefaultImpls";
|
||||||
@@ -118,10 +117,4 @@ public final class JvmAbi {
|
|||||||
public static boolean isMappedIntrinsicCompanionObject(@NotNull ClassDescriptor companionObject) {
|
public static boolean isMappedIntrinsicCompanionObject(@NotNull ClassDescriptor companionObject) {
|
||||||
return CompanionObjectMapping.INSTANCE.isMappedIntrinsicCompanionObject(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