[K/N] Implement instantiating of annotation class

This commit is contained in:
Pavel Kunyavskiy
2021-09-21 16:12:53 +03:00
committed by Space
parent a40022efcd
commit fb875c484d
33 changed files with 260 additions and 123 deletions
@@ -407,6 +407,12 @@ public class FirBlackBoxCodegenTestGenerated extends AbstractFirBlackBoxCodegenT
runTest("compiler/testData/codegen/box/annotations/instances/annotationEqHc.kt");
}
@Test
@TestMetadata("annotationFromStdlib.kt")
public void testAnnotationFromStdlib() throws Exception {
runTest("compiler/testData/codegen/box/annotations/instances/annotationFromStdlib.kt");
}
@Test
@TestMetadata("annotationInstances.kt")
public void testAnnotationInstances() throws Exception {
@@ -437,6 +443,12 @@ public class FirBlackBoxCodegenTestGenerated extends AbstractFirBlackBoxCodegenT
runTest("compiler/testData/codegen/box/annotations/instances/annotationType.kt");
}
@Test
@TestMetadata("inInlineFunction.kt")
public void testInInlineFunction() throws Exception {
runTest("compiler/testData/codegen/box/annotations/instances/inInlineFunction.kt");
}
@Test
@TestMetadata("javaAnnotation.kt")
public void testJavaAnnotation() throws Exception {
@@ -1,40 +0,0 @@
/*
* Copyright 2010-2021 JetBrains s.r.o. and Kotlin Programming Language contributors.
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
*/
package org.jetbrains.kotlin.resolve.calls.checkers
import com.intellij.psi.PsiElement
import org.jetbrains.kotlin.config.LanguageFeature
import org.jetbrains.kotlin.descriptors.ConstructorDescriptor
import org.jetbrains.kotlin.diagnostics.Errors
import org.jetbrains.kotlin.psi.KtCallExpression
import org.jetbrains.kotlin.resolve.DescriptorUtils
import org.jetbrains.kotlin.resolve.calls.CallExpressionResolver
import org.jetbrains.kotlin.resolve.calls.model.ResolvedCall
/**
* Additional checker that prohibits usage of LanguageFeature.InstantiationOfAnnotationClasses on backends
* that do not support this feature yet
*/
object InstantiationOfAnnotationClassesCallChecker : CallChecker {
override fun check(resolvedCall: ResolvedCall<*>, reportOn: PsiElement, context: CallCheckerContext) {
if (!context.languageVersionSettings.supportsFeature(LanguageFeature.InstantiationOfAnnotationClasses)) return
val calledDescriptor = resolvedCall.resultingDescriptor as? ConstructorDescriptor ?: return
val constructedClass = calledDescriptor.constructedClass
val expression = resolvedCall.call.callElement as? KtCallExpression ?: return
if (DescriptorUtils.isAnnotationClass(constructedClass) && !CallExpressionResolver.canInstantiateAnnotationClass(
expression,
context.trace
)
) {
val supported = constructedClass.declaredTypeParameters.isEmpty()
if (supported) {
context.trace.report(Errors.ANNOTATION_CLASS_CONSTRUCTOR_CALL.on(expression))
} else {
// already reported in CallExpressionResolver.getCallExpressionTypeInfoWithoutFinalTypeCheck
}
}
}
}
@@ -1,6 +1,5 @@
// IGNORE_BACKEND_FIR: JVM_IR
// IGNORE_BACKEND: JVM
// IGNORE_BACKEND: NATIVE
// IGNORE_BACKEND: WASM
// DONT_TARGET_EXACT_BACKEND: JS
@@ -0,0 +1,17 @@
// IGNORE_BACKEND_FIR: JVM_IR
// IGNORE_BACKEND: JVM
// IGNORE_BACKEND: WASM
// DONT_TARGET_EXACT_BACKEND: JS
// WITH_RUNTIME
// !LANGUAGE: +InstantiationOfAnnotationClasses
import kotlin.reflect.KClass
fun box(): String {
val ann1 = kotlin.SinceKotlin("1.6.0")
val expectedToString = "@kotlin.SinceKotlin(version=1.6.0)"
val actualToString = ann1.toString()
if (actualToString != expectedToString) return "Expected ann1.toString() equals to $expectedToString, but it's $actualToString"
return "OK"
}
@@ -1,6 +1,5 @@
// IGNORE_BACKEND_FIR: JVM_IR
// IGNORE_BACKEND: JVM
// IGNORE_BACKEND: NATIVE
// IGNORE_BACKEND: WASM
// (supported: JVM_IR, JS_IR(_E6))
@@ -1,6 +1,5 @@
// IGNORE_BACKEND_FIR: JVM_IR
// IGNORE_BACKEND: JVM
// IGNORE_BACKEND: NATIVE
// IGNORE_BACKEND: WASM
// DONT_TARGET_EXACT_BACKEND: JS
@@ -1,6 +1,5 @@
// IGNORE_BACKEND_FIR: JVM_IR
// IGNORE_BACKEND: JVM
// IGNORE_BACKEND: NATIVE
// IGNORE_BACKEND: WASM
// DONT_TARGET_EXACT_BACKEND: JS
@@ -49,5 +48,8 @@ fun box(): String {
val targetJVM = "@test.Anno(s=OK, i=42, f=2.718281828, u=43, e=E0, a=@test.A(b=1, s=1, i=1, f=1.0, d=1.0, l=1, c=c, bool=true), " +
"k=interface test.A (Kotlin reflection is not available), arr=[], intArr=[1, 2], arrOfE=[E0], arrOfA=[@test.Empty()])"
val targetJS = "@test.Anno(s=OK, i=42, f=2.718281828, u=43, e=E0, a=@test.A(b=1, s=1, i=1, f=1, d=1, l=1, c=c, bool=true), k=class A, arr=[...], intArr=[...], arrOfE=[...], arrOfA=[...])"
return if (s == targetJS || s == targetJVM) "OK" else "FAILED, got string $s"
val targetNative = targetJVM
.replace(" (Kotlin reflection is not available)", "")
.replace("interface", "class")
return if (s == targetJS || s == targetJVM || s == targetNative) "OK" else "FAILED, got string $s"
}
@@ -0,0 +1,31 @@
// IGNORE_BACKEND_FIR: JVM_IR
// IGNORE_BACKEND: JVM
// IGNORE_BACKEND: WASM
// DONT_TARGET_EXACT_BACKEND: JS
// IGNORE_DEXING
// WITH_RUNTIME
// !LANGUAGE: +InstantiationOfAnnotationClasses
import kotlin.test.*
annotation class A(val i: Int)
inline fun foo(i: Int): A = A(i)
inline fun bar(f: () -> Int): A = A(f())
class C {
fun one(): A = foo(1)
fun two(): A = bar { 2 }
}
fun box(): String {
val one = C().one()
val two = C().two()
assertEquals(1, one.i)
assertEquals(2, two.i)
assertEquals(A(1), one)
assertEquals(A(2), two)
return "OK"
}
@@ -1,6 +1,5 @@
// IGNORE_BACKEND_FIR: JVM_IR
// IGNORE_BACKEND: JVM
// IGNORE_BACKEND: NATIVE
// IGNORE_BACKEND: WASM
// DONT_TARGET_EXACT_BACKEND: JS
@@ -1,6 +1,5 @@
// IGNORE_BACKEND_FIR: JVM_IR
// IGNORE_BACKEND: JVM
// IGNORE_BACKEND: NATIVE
// IGNORE_BACKEND: WASM
// (supported: JVM_IR, JS_IR(_E6))
@@ -1,5 +1,7 @@
// IGNORE_BACKEND_FIR: JVM_IR
// TARGET_BACKEND: JVM_IR
// IGNORE_BACKEND: JVM
// IGNORE_BACKEND: WASM
// DONT_TARGET_EXACT_BACKEND: JS
// WITH_RUNTIME
// !LANGUAGE: +InstantiationOfAnnotationClasses
@@ -1,6 +1,5 @@
// IGNORE_BACKEND_FIR: JVM_IR
// IGNORE_BACKEND: JVM
// IGNORE_BACKEND: NATIVE
// IGNORE_BACKEND: WASM
// IGNORE_BACKEND_MULTI_MODULE: JVM, JVM_MULTI_MODULE_IR_AGAINST_OLD
@@ -1,6 +1,5 @@
// IGNORE_BACKEND_FIR: JVM_IR
// IGNORE_BACKEND: JVM
// IGNORE_BACKEND: NATIVE
// IGNORE_BACKEND: WASM
// IGNORE_BACKEND_MULTI_MODULE: JVM, JVM_MULTI_MODULE_IR_AGAINST_OLD
@@ -1,21 +0,0 @@
// !DIAGNOSTICS: -UNUSED_VARIABLE
// WITH_RUNTIME
// SKIP_TXT
// !LANGUAGE: +InstantiationOfAnnotationClasses
// FILE: test.kt
import kotlin.reflect.KClass
annotation class A
annotation class B(val int: Int)
annotation class C(val int: Int = 42)
annotation class G<T: Any>(val int: KClass<T>)
fun box() {
val a = <!ANNOTATION_CLASS_CONSTRUCTOR_CALL!>A()<!>
val b = <!ANNOTATION_CLASS_CONSTRUCTOR_CALL!>B(4)<!>
val c = <!ANNOTATION_CLASS_CONSTRUCTOR_CALL!>C()<!>
val foo = <!ANNOTATION_CLASS_CONSTRUCTOR_CALL!>G(Int::class)<!>
}
@@ -24,12 +24,6 @@ public class DiagnosticsNativeTestGenerated extends AbstractDiagnosticsNativeTes
KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("compiler/testData/diagnostics/nativeTests"), Pattern.compile("^(.+)\\.kt$"), null, true);
}
@Test
@TestMetadata("annotationConstructorCallNative.kt")
public void testAnnotationConstructorCallNative() throws Exception {
runTest("compiler/testData/diagnostics/nativeTests/annotationConstructorCallNative.kt");
}
@Test
@TestMetadata("identifiers.kt")
public void testIdentifiers() throws Exception {
@@ -395,6 +395,12 @@ public class BlackBoxCodegenTestGenerated extends AbstractBlackBoxCodegenTest {
runTest("compiler/testData/codegen/box/annotations/instances/annotationEqHc.kt");
}
@Test
@TestMetadata("annotationFromStdlib.kt")
public void testAnnotationFromStdlib() throws Exception {
runTest("compiler/testData/codegen/box/annotations/instances/annotationFromStdlib.kt");
}
@Test
@TestMetadata("annotationInstances.kt")
public void testAnnotationInstances() throws Exception {
@@ -413,6 +419,12 @@ public class BlackBoxCodegenTestGenerated extends AbstractBlackBoxCodegenTest {
runTest("compiler/testData/codegen/box/annotations/instances/annotationToString.kt");
}
@Test
@TestMetadata("inInlineFunction.kt")
public void testInInlineFunction() throws Exception {
runTest("compiler/testData/codegen/box/annotations/instances/inInlineFunction.kt");
}
@Test
@TestMetadata("multifileEqHc.kt")
public void testMultifileEqHc() throws Exception {
@@ -424,6 +436,12 @@ public class BlackBoxCodegenTestGenerated extends AbstractBlackBoxCodegenTest {
public void testMultiplatformInstantiation() throws Exception {
runTest("compiler/testData/codegen/box/annotations/instances/multiplatformInstantiation.kt");
}
@Test
@TestMetadata("nestedAnnotationInstances.kt")
public void testNestedAnnotationInstances() throws Exception {
runTest("compiler/testData/codegen/box/annotations/instances/nestedAnnotationInstances.kt");
}
}
@Nested
@@ -407,6 +407,12 @@ public class IrBlackBoxCodegenTestGenerated extends AbstractIrBlackBoxCodegenTes
runTest("compiler/testData/codegen/box/annotations/instances/annotationEqHc.kt");
}
@Test
@TestMetadata("annotationFromStdlib.kt")
public void testAnnotationFromStdlib() throws Exception {
runTest("compiler/testData/codegen/box/annotations/instances/annotationFromStdlib.kt");
}
@Test
@TestMetadata("annotationInstances.kt")
public void testAnnotationInstances() throws Exception {
@@ -437,6 +443,12 @@ public class IrBlackBoxCodegenTestGenerated extends AbstractIrBlackBoxCodegenTes
runTest("compiler/testData/codegen/box/annotations/instances/annotationType.kt");
}
@Test
@TestMetadata("inInlineFunction.kt")
public void testInInlineFunction() throws Exception {
runTest("compiler/testData/codegen/box/annotations/instances/inInlineFunction.kt");
}
@Test
@TestMetadata("javaAnnotation.kt")
public void testJavaAnnotation() throws Exception {
@@ -344,6 +344,11 @@ public class LightAnalysisModeTestGenerated extends AbstractLightAnalysisModeTes
runTest("compiler/testData/codegen/box/annotations/instances/annotationEqHc.kt");
}
@TestMetadata("annotationFromStdlib.kt")
public void ignoreAnnotationFromStdlib() throws Exception {
runTest("compiler/testData/codegen/box/annotations/instances/annotationFromStdlib.kt");
}
@TestMetadata("annotationInstances.kt")
public void ignoreAnnotationInstances() throws Exception {
runTest("compiler/testData/codegen/box/annotations/instances/annotationInstances.kt");
@@ -359,6 +364,11 @@ public class LightAnalysisModeTestGenerated extends AbstractLightAnalysisModeTes
runTest("compiler/testData/codegen/box/annotations/instances/annotationToString.kt");
}
@TestMetadata("inInlineFunction.kt")
public void ignoreInInlineFunction() throws Exception {
runTest("compiler/testData/codegen/box/annotations/instances/inInlineFunction.kt");
}
@TestMetadata("multifileEqHc.kt")
public void ignoreMultifileEqHc() throws Exception {
runTest("compiler/testData/codegen/box/annotations/instances/multifileEqHc.kt");
@@ -369,6 +379,11 @@ public class LightAnalysisModeTestGenerated extends AbstractLightAnalysisModeTes
runTest("compiler/testData/codegen/box/annotations/instances/multiplatformInstantiation.kt");
}
@TestMetadata("nestedAnnotationInstances.kt")
public void ignoreNestedAnnotationInstances() throws Exception {
runTest("compiler/testData/codegen/box/annotations/instances/nestedAnnotationInstances.kt");
}
private void runTest(String testDataFilePath) throws Exception {
KotlinTestUtils.runTest(this::doTest, TargetBackend.JVM, testDataFilePath);
}
@@ -13,7 +13,6 @@ import org.jetbrains.kotlin.js.analyze.JsNativeDiagnosticSuppressor
import org.jetbrains.kotlin.js.naming.NameSuggestion
import org.jetbrains.kotlin.js.resolve.diagnostics.*
import org.jetbrains.kotlin.resolve.PlatformConfiguratorBase
import org.jetbrains.kotlin.resolve.calls.checkers.InstantiationOfAnnotationClassesCallChecker
import org.jetbrains.kotlin.resolve.checkers.ExpectedActualDeclarationChecker
import org.jetbrains.kotlin.types.DynamicTypesAllowed
@@ -97,6 +97,11 @@ public class IrJsCodegenBoxES6TestGenerated extends AbstractIrJsCodegenBoxES6Tes
runTest("compiler/testData/codegen/box/annotations/instances/annotationEqHc.kt");
}
@TestMetadata("annotationFromStdlib.kt")
public void testAnnotationFromStdlib() throws Exception {
runTest("compiler/testData/codegen/box/annotations/instances/annotationFromStdlib.kt");
}
@TestMetadata("annotationInstances.kt")
public void testAnnotationInstances() throws Exception {
runTest("compiler/testData/codegen/box/annotations/instances/annotationInstances.kt");
@@ -112,6 +117,11 @@ public class IrJsCodegenBoxES6TestGenerated extends AbstractIrJsCodegenBoxES6Tes
runTest("compiler/testData/codegen/box/annotations/instances/annotationToString.kt");
}
@TestMetadata("inInlineFunction.kt")
public void testInInlineFunction() throws Exception {
runTest("compiler/testData/codegen/box/annotations/instances/inInlineFunction.kt");
}
@TestMetadata("multifileEqHc.kt")
public void testMultifileEqHc() throws Exception {
runTest("compiler/testData/codegen/box/annotations/instances/multifileEqHc.kt");
@@ -121,6 +131,11 @@ public class IrJsCodegenBoxES6TestGenerated extends AbstractIrJsCodegenBoxES6Tes
public void testMultiplatformInstantiation() throws Exception {
runTest("compiler/testData/codegen/box/annotations/instances/multiplatformInstantiation.kt");
}
@TestMetadata("nestedAnnotationInstances.kt")
public void testNestedAnnotationInstances() throws Exception {
runTest("compiler/testData/codegen/box/annotations/instances/nestedAnnotationInstances.kt");
}
}
@TestMetadata("compiler/testData/codegen/box/annotations/kClassMapping")
@@ -97,6 +97,11 @@ public class IrJsCodegenBoxTestGenerated extends AbstractIrJsCodegenBoxTest {
runTest("compiler/testData/codegen/box/annotations/instances/annotationEqHc.kt");
}
@TestMetadata("annotationFromStdlib.kt")
public void testAnnotationFromStdlib() throws Exception {
runTest("compiler/testData/codegen/box/annotations/instances/annotationFromStdlib.kt");
}
@TestMetadata("annotationInstances.kt")
public void testAnnotationInstances() throws Exception {
runTest("compiler/testData/codegen/box/annotations/instances/annotationInstances.kt");
@@ -112,6 +117,11 @@ public class IrJsCodegenBoxTestGenerated extends AbstractIrJsCodegenBoxTest {
runTest("compiler/testData/codegen/box/annotations/instances/annotationToString.kt");
}
@TestMetadata("inInlineFunction.kt")
public void testInInlineFunction() throws Exception {
runTest("compiler/testData/codegen/box/annotations/instances/inInlineFunction.kt");
}
@TestMetadata("multifileEqHc.kt")
public void testMultifileEqHc() throws Exception {
runTest("compiler/testData/codegen/box/annotations/instances/multifileEqHc.kt");
@@ -121,6 +131,11 @@ public class IrJsCodegenBoxTestGenerated extends AbstractIrJsCodegenBoxTest {
public void testMultiplatformInstantiation() throws Exception {
runTest("compiler/testData/codegen/box/annotations/instances/multiplatformInstantiation.kt");
}
@TestMetadata("nestedAnnotationInstances.kt")
public void testNestedAnnotationInstances() throws Exception {
runTest("compiler/testData/codegen/box/annotations/instances/nestedAnnotationInstances.kt");
}
}
@TestMetadata("compiler/testData/codegen/box/annotations/kClassMapping")
@@ -92,6 +92,11 @@ public class IrCodegenBoxWasmTestGenerated extends AbstractIrCodegenBoxWasmTest
runTest("compiler/testData/codegen/box/annotations/instances/annotationEqHc.kt");
}
@TestMetadata("annotationFromStdlib.kt")
public void testAnnotationFromStdlib() throws Exception {
runTest("compiler/testData/codegen/box/annotations/instances/annotationFromStdlib.kt");
}
@TestMetadata("annotationInstances.kt")
public void testAnnotationInstances() throws Exception {
runTest("compiler/testData/codegen/box/annotations/instances/annotationInstances.kt");
@@ -107,6 +112,11 @@ public class IrCodegenBoxWasmTestGenerated extends AbstractIrCodegenBoxWasmTest
runTest("compiler/testData/codegen/box/annotations/instances/annotationToString.kt");
}
@TestMetadata("inInlineFunction.kt")
public void testInInlineFunction() throws Exception {
runTest("compiler/testData/codegen/box/annotations/instances/inInlineFunction.kt");
}
@TestMetadata("multifileEqHc.kt")
public void testMultifileEqHc() throws Exception {
runTest("compiler/testData/codegen/box/annotations/instances/multifileEqHc.kt");
@@ -116,6 +126,11 @@ public class IrCodegenBoxWasmTestGenerated extends AbstractIrCodegenBoxWasmTest
public void testMultiplatformInstantiation() throws Exception {
runTest("compiler/testData/codegen/box/annotations/instances/multiplatformInstantiation.kt");
}
@TestMetadata("nestedAnnotationInstances.kt")
public void testNestedAnnotationInstances() throws Exception {
runTest("compiler/testData/codegen/box/annotations/instances/nestedAnnotationInstances.kt");
}
}
@TestMetadata("compiler/testData/codegen/box/annotations/kClassMapping")
@@ -5,18 +5,7 @@
package org.jetbrains.kotlin.backend.konan
import org.jetbrains.kotlin.descriptors.ClassKind
import org.jetbrains.kotlin.ir.declarations.IrClass
import org.jetbrains.kotlin.ir.util.hasAnnotation
import org.jetbrains.kotlin.name.FqName
internal fun IrClass.isNonGeneratedAnnotation(): Boolean =
this.kind == ClassKind.ANNOTATION_CLASS &&
!this.annotations.hasAnnotation(serialInfoAnnotationFqName) &&
!this.annotations.hasAnnotation(inheritableSerialInfoFqName)
private val serialInfoAnnotationFqName = FqName("kotlinx.serialization.SerialInfo")
private val inheritableSerialInfoFqName = FqName("kotlinx.serialization.InheritableSerialInfo")
/**
* We don't need to generate RTTI in some cases, e.g. Objective-C external classes.
@@ -87,6 +87,12 @@ internal val stripTypeAliasDeclarationsPhase = makeKonanModuleLoweringPhase(
description = "Strip typealias declarations"
)
internal val annotationImplementationPhase = makeKonanFileLoweringPhase(
{ context -> AnnotationImplementationLowering { NativeAnnotationImplementationTransformer(context, it) } },
name = "AnnotationImplementation",
description = "Create synthetic annotations implementations and use them in annotations constructor calls"
)
internal val lowerBeforeInlinePhase = makeKonanModuleLoweringPhase(
::PreInlineLowering,
name = "LowerBeforeInline",
@@ -7,7 +7,6 @@ import org.jetbrains.kotlin.backend.common.lower.createIrBuilder
import org.jetbrains.kotlin.backend.common.phaser.*
import org.jetbrains.kotlin.backend.common.serialization.CompatibilityMode
import org.jetbrains.kotlin.backend.common.serialization.metadata.KlibMetadataMonolithicSerializer
import org.jetbrains.kotlin.backend.konan.MemoryModel
import org.jetbrains.kotlin.backend.konan.llvm.*
import org.jetbrains.kotlin.backend.konan.lower.ExpectToActualDefaultValueCopier
import org.jetbrains.kotlin.backend.konan.lower.SamSuperTypesChecker
@@ -224,6 +223,7 @@ internal val allLoweringsPhase = NamedCompilerPhase(
name = "IrLowerByFile",
description = "IR Lowering by file",
lower = listOf(
annotationImplementationPhase,
rangeContainsLoweringPhase,
forLoopsPhase,
flattenStringConcatenationPhase,
@@ -16,6 +16,7 @@ import org.jetbrains.kotlin.backend.konan.lower.TestProcessor
import org.jetbrains.kotlin.builtins.StandardNames
import org.jetbrains.kotlin.config.languageVersionSettings
import org.jetbrains.kotlin.descriptors.ClassDescriptor
import org.jetbrains.kotlin.descriptors.FunctionDescriptor
import org.jetbrains.kotlin.descriptors.findClassAcrossModuleDependencies
import org.jetbrains.kotlin.incremental.components.NoLookupLocation
import org.jetbrains.kotlin.ir.IrBuiltIns
@@ -26,6 +27,7 @@ import org.jetbrains.kotlin.ir.symbols.IrEnumEntrySymbol
import org.jetbrains.kotlin.ir.symbols.IrFunctionSymbol
import org.jetbrains.kotlin.ir.symbols.IrSimpleFunctionSymbol
import org.jetbrains.kotlin.ir.types.IrType
import org.jetbrains.kotlin.ir.types.defaultType
import org.jetbrains.kotlin.ir.types.typeWith
import org.jetbrains.kotlin.ir.util.ReferenceSymbolTable
import org.jetbrains.kotlin.ir.util.SymbolTable
@@ -292,18 +294,29 @@ internal class KonanSymbols(
val getProgressionLast = context.getKonanInternalFunctions("getProgressionLast")
.map { Pair(it.returnType, symbolTable.referenceSimpleFunction(it)) }.toMap()
val arrayContentToString = arrays.associateBy({ it }, { findArrayExtension(it, "contentToString") })
private fun arrayToExtensionSymbolMap(name: String, filter: (FunctionDescriptor) -> Boolean = { true }) = arrays.associateWith {
findArrayExtension(it, name, filter)
}
val arrayContentHashCode = arrays.associateBy({ it }, { findArrayExtension(it, "contentHashCode") })
val arrayContentToString = arrayToExtensionSymbolMap("contentToString") {
it.extensionReceiverParameter?.type?.isMarkedNullable == false
}
val arrayContentHashCode = arrayToExtensionSymbolMap("contentHashCode") {
it.extensionReceiverParameter?.type?.isMarkedNullable == false
}
val arrayContentEquals = arrayToExtensionSymbolMap("contentEquals") {
it.extensionReceiverParameter?.type?.isMarkedNullable == false
}
private fun findArrayExtension(classSymbol: IrClassSymbol, name: String): IrSimpleFunctionSymbol =
override val arraysContentEquals by lazy { arrayContentEquals.mapKeys { it.key.defaultType } }
private fun findArrayExtension(classSymbol: IrClassSymbol, name: String, filter: (FunctionDescriptor) -> Boolean): IrSimpleFunctionSymbol =
irBuiltIns.findFunctions(Name.identifier(name), "kotlin", "collections")
.singleOrNull {
it.descriptor.let {
it.valueParameters.isEmpty()
&& it.extensionReceiverParameter?.type?.constructor?.declarationDescriptor == classSymbol.descriptor
&& it.extensionReceiverParameter?.type?.isMarkedNullable == false
it.extensionReceiverParameter?.type?.constructor?.declarationDescriptor == classSymbol.descriptor
&& !it.isExpect
&& filter(it)
}
} ?: error(classSymbol.toString())
@@ -314,14 +327,7 @@ internal class KonanSymbols(
return symbolTable.referenceFunction(descriptor)
}
val copyInto = arrays.map { symbol ->
val funSymbol = irBuiltIns.findFunctions(Name.identifier("copyInto"), StandardNames.COLLECTIONS_PACKAGE_FQ_NAME)
.single {
!it.descriptor.isExpect &&
it.descriptor.extensionReceiverParameter?.type?.constructor?.declarationDescriptor == symbol.descriptor
}
symbol to funSymbol
}.toMap()
val copyInto = arrayToExtensionSymbolMap("copyInto")
val arrayGet = arrays.associateWith { it.descriptor.unsubstitutedMemberScope
.getContributedFunctions(Name.identifier("get"), NoLookupLocation.FROM_BACKEND)
@@ -877,7 +877,7 @@ internal class CodeGeneratorVisitor(val context: Context, val lifetimes: Map<IrE
override fun visitClass(declaration: IrClass) {
context.log{"visitClass : ${ir2string(declaration)}"}
if (declaration.isNonGeneratedAnnotation() || !declaration.requiresCodeGeneration()) {
if (!declaration.requiresCodeGeneration()) {
// For non-generated annotation classes generate only nested classes.
declaration.declarations
.filterIsInstance<IrClass>()
@@ -10,6 +10,7 @@ import org.jetbrains.kotlin.backend.konan.Context
import org.jetbrains.kotlin.backend.konan.descriptors.isExpectMember
import org.jetbrains.kotlin.backend.konan.descriptors.propertyIfAccessor
import org.jetbrains.kotlin.backend.konan.ir.ModuleIndex
import org.jetbrains.kotlin.descriptors.ClassKind
import org.jetbrains.kotlin.descriptors.MemberDescriptor
import org.jetbrains.kotlin.ir.IrElement
import org.jetbrains.kotlin.ir.declarations.*
@@ -34,7 +35,14 @@ import org.jetbrains.kotlin.resolve.multiplatform.OptionalAnnotationUtil
internal class ExpectDeclarationsRemoving(val context: Context) : FileLoweringPass {
override fun lower(irFile: IrFile) {
// All declarations with `isExpect == true` are nested into a top-level declaration with `isExpect == true`.
irFile.declarations.removeAll { it.descriptor.isExpectMember }
irFile.declarations.removeAll {
when (it) {
is IrClass -> it.isExpect
is IrFunction -> it.isExpect
is IrProperty -> it.isExpect
else -> false
}
}
}
}
@@ -11,7 +11,6 @@ import org.jetbrains.kotlin.backend.common.ir.createDispatchReceiverParameter
import org.jetbrains.kotlin.backend.common.lower.createIrBuilder
import org.jetbrains.kotlin.backend.common.lower.irBlockBody
import org.jetbrains.kotlin.backend.konan.descriptors.synthesizedName
import org.jetbrains.kotlin.backend.konan.isNonGeneratedAnnotation
import org.jetbrains.kotlin.descriptors.*
import org.jetbrains.kotlin.ir.IrStatement
import org.jetbrains.kotlin.ir.builders.irDelegatingConstructorCall
@@ -154,16 +153,6 @@ internal class InitializersLowering(val context: CommonBackendContext) : ClassLo
}
private fun lowerConstructors(initializeMethodSymbol: IrSimpleFunctionSymbol?) {
if (irClass.kind == ClassKind.ANNOTATION_CLASS) {
if (irClass.isNonGeneratedAnnotation()) return
val irConstructor = irClass.declarations.filterIsInstance<IrConstructor>().single()
assert(irConstructor.body == null)
irConstructor.body = context.createIrBuilder(irConstructor.symbol).irBlockBody(irConstructor) {
+irDelegatingConstructorCall(context.irBuiltIns.anyClass.owner.constructors.single())
+IrInstanceInitializerCallImpl(startOffset, endOffset, irClass.symbol, context.irBuiltIns.unitType)
}
}
irClass.transformChildrenVoid(object : IrElementTransformerVoid() {
override fun visitClass(declaration: IrClass): IrStatement {
@@ -0,0 +1,64 @@
/*
* Copyright 2010-2021 JetBrains s.r.o. and Kotlin Programming Language contributors.
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
*/
package org.jetbrains.kotlin.backend.konan.lower
import org.jetbrains.kotlin.backend.common.deepCopyWithVariables
import org.jetbrains.kotlin.backend.common.lower.AnnotationImplementationTransformer
import org.jetbrains.kotlin.backend.konan.*
import org.jetbrains.kotlin.ir.declarations.*
import org.jetbrains.kotlin.ir.expressions.*
import org.jetbrains.kotlin.ir.types.*
import org.jetbrains.kotlin.ir.util.*
import org.jetbrains.kotlin.descriptors.DescriptorVisibilities
import org.jetbrains.kotlin.ir.builders.declarations.addValueParameter
import org.jetbrains.kotlin.ir.expressions.impl.IrDelegatingConstructorCallImpl
import org.jetbrains.kotlin.ir.expressions.impl.IrGetValueImpl
internal class NativeAnnotationImplementationTransformer(context: Context, irFile: IrFile) :
AnnotationImplementationTransformer(context, irFile) {
private val arrayContentEqualsMap = context.ir.symbols.arraysContentEquals
override fun getArrayContentEqualsSymbol(type: IrType) =
when {
type.isPrimitiveArray() -> arrayContentEqualsMap[type]
else -> arrayContentEqualsMap.entries.singleOrNull { (k, _) -> k.isArray() }?.value
} ?: error("Can't find an Arrays.contentEquals method for array type ${type.render()}")
override fun IrClass.platformSetup() {
visibility = DescriptorVisibilities.PRIVATE
parent = irFile!!
}
override fun implementAnnotationPropertiesAndConstructor(implClass: IrClass, annotationClass: IrClass, generatedConstructor: IrConstructor) {
val properties = annotationClass.getAnnotationProperties()
properties.forEach { property ->
val propType = property.getter!!.returnType
val propName = property.name
val parameter = generatedConstructor.addValueParameter(propName.asString(), propType)
// VALUE_FROM_PARAMETER
val originalParameter = ((property.backingField?.initializer?.expression as? IrGetValue)?.symbol?.owner as? IrValueParameter)
if (originalParameter?.defaultValue != null) {
parameter.defaultValue = originalParameter.defaultValue!!.deepCopyWithVariables().also { it.transformChildrenVoid() }
}
}
generatedConstructor.body = context.irFactory.createBlockBody(
SYNTHETIC_OFFSET, SYNTHETIC_OFFSET, listOf(
IrDelegatingConstructorCallImpl(
SYNTHETIC_OFFSET, SYNTHETIC_OFFSET, context.irBuiltIns.unitType, annotationClass.constructors.single().symbol,
typeArgumentsCount = 0, valueArgumentsCount = generatedConstructor.valueParameters.size
).apply {
generatedConstructor.valueParameters.forEach {
putValueArgument(it.index, IrGetValueImpl(SYNTHETIC_OFFSET, SYNTHETIC_OFFSET, it.symbol))
}
}
))
}
override val forbidDirectFieldAccessInMethods = true
}
@@ -17,7 +17,6 @@ import org.jetbrains.kotlin.backend.konan.ir.actualCallee
import org.jetbrains.kotlin.backend.konan.ir.isAny
import org.jetbrains.kotlin.backend.konan.ir.isObjCObjectType
import org.jetbrains.kotlin.backend.konan.ir.isVirtualCall
import org.jetbrains.kotlin.backend.konan.isNonGeneratedAnnotation
import org.jetbrains.kotlin.backend.konan.logMultiple
import org.jetbrains.kotlin.backend.konan.lower.erasedUpperBound
import org.jetbrains.kotlin.ir.IrElement
@@ -201,8 +200,8 @@ internal class ModuleDFGBuilder(val context: Context, val irModule: IrModuleFrag
override fun visitConstructor(declaration: IrConstructor) {
val body = declaration.body
assert (body != null || declaration.constructedClass.isNonGeneratedAnnotation()) {
"Non-annotation class constructor has empty body"
assert (body != null) {
"Class constructor has empty body"
}
context.logMultiple {
+"Analysing function ${declaration.descriptor}"
@@ -615,7 +615,6 @@ internal object DataFlowIR {
}
val bridgeTargetSymbol = if (isSpecialBridge || bridgeTarget == null) null else mapFunction(bridgeTarget)
val placeToFunctionsTable = !isAbstract && it !is IrConstructor && irClass != null
&& !irClass.isNonGeneratedAnnotation()
&& (it.isOverridableOrOverrides || bridgeTarget != null || function.isSpecial || !irClass.isFinal())
val symbolTableIndex = if (placeToFunctionsTable) module.numberOfFunctions++ else -1
val frozen = it is IrConstructor && irClass!!.annotations.findAnnotation(KonanFqNames.frozen) != null
@@ -13,7 +13,6 @@ import org.jetbrains.kotlin.descriptors.CallableMemberDescriptor
import org.jetbrains.kotlin.psi.KtCallableDeclaration
import org.jetbrains.kotlin.resolve.BindingContext
import org.jetbrains.kotlin.resolve.PlatformConfiguratorBase
import org.jetbrains.kotlin.resolve.calls.checkers.InstantiationOfAnnotationClassesCallChecker
import org.jetbrains.kotlin.resolve.calls.checkers.TypeOfChecker
import org.jetbrains.kotlin.resolve.checkers.ExpectedActualDeclarationChecker
import org.jetbrains.kotlin.resolve.inline.ReasonableInlineRule
@@ -23,7 +22,6 @@ import org.jetbrains.kotlin.resolve.konan.diagnostics.*
object NativePlatformConfigurator : PlatformConfiguratorBase(
additionalCallCheckers = listOf(
SuperCallWithDefaultArgumentsChecker(),
InstantiationOfAnnotationClassesCallChecker
),
additionalDeclarationCheckers = listOf(
NativeThrowsChecker, NativeSharedImmutableChecker,