mirror of
https://github.com/jlengrand/kotlin.git
synced 2026-03-23 00:21:31 +00:00
Compare commits
143 Commits
rr/stdlib/
...
rr/mitropo
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
4a4eee7b36 | ||
|
|
e13a38a758 | ||
|
|
9e9ca4953f | ||
|
|
62dcfcde79 | ||
|
|
4739adb6dc | ||
|
|
03651f1dd4 | ||
|
|
650469024e | ||
|
|
2be94d9d2f | ||
|
|
c015463926 | ||
|
|
1bb3f60bad | ||
|
|
36f22dafc5 | ||
|
|
41131e46d7 | ||
|
|
95625d0fae | ||
|
|
2fe222e8e7 | ||
|
|
de6154980d | ||
|
|
d2ea108123 | ||
|
|
388e619d90 | ||
|
|
f3a2ff8646 | ||
|
|
117aae8a6b | ||
|
|
9e37b62f62 | ||
|
|
55595fe2c6 | ||
|
|
db127bb414 | ||
|
|
3d86e92bf5 | ||
|
|
64b1cc7fd4 | ||
|
|
cc95c16ac2 | ||
|
|
bc16fbf438 | ||
|
|
7d31d7f20c | ||
|
|
b9fda902fb | ||
|
|
ce20196006 | ||
|
|
631e68c99a | ||
|
|
ace7ae19b4 | ||
|
|
07654b4c0e | ||
|
|
b2e629dceb | ||
|
|
0234678804 | ||
|
|
caa5aadc98 | ||
|
|
463908f6f4 | ||
|
|
cc67ac631f | ||
|
|
a150014e74 | ||
|
|
b543588ccd | ||
|
|
9096d21fcd | ||
|
|
632e88459e | ||
|
|
de7d82e42b | ||
|
|
6f0bd6c122 | ||
|
|
7384c89ddd | ||
|
|
fd9b14ed29 | ||
|
|
2ed68643cb | ||
|
|
d8892ced9d | ||
|
|
5ed7abd15d | ||
|
|
69dc963f97 | ||
|
|
19cc9c81dc | ||
|
|
7b1b50499d | ||
|
|
a3750b6419 | ||
|
|
c0f4ee7dc9 | ||
|
|
447308dcfc | ||
|
|
1cccceabb9 | ||
|
|
d9821412d0 | ||
|
|
a292eb865b | ||
|
|
1329030281 | ||
|
|
10e5dc1f63 | ||
|
|
d9e5407ecb | ||
|
|
439808952d | ||
|
|
901b794af3 | ||
|
|
02f6a03ff7 | ||
|
|
2656eeb164 | ||
|
|
d385a9b29e | ||
|
|
f64f9c2144 | ||
|
|
6f957c7b31 | ||
|
|
aaacbaaaec | ||
|
|
a035404c96 | ||
|
|
3297237f3d | ||
|
|
175e94c0aa | ||
|
|
fe61530357 | ||
|
|
ab5cb13dae | ||
|
|
cbbb497edf | ||
|
|
c4b24548cb | ||
|
|
293df7bd50 | ||
|
|
63394858ac | ||
|
|
e787dbf374 | ||
|
|
1c2fbb61fe | ||
|
|
7a0f986823 | ||
|
|
67158caf73 | ||
|
|
41306d25fd | ||
|
|
8e8710efec | ||
|
|
982cbf1148 | ||
|
|
d3d3b41dea | ||
|
|
74c697af92 | ||
|
|
8fb41e4562 | ||
|
|
a72eeb800d | ||
|
|
060b2eaf27 | ||
|
|
ca15c33a62 | ||
|
|
9db9e2ad57 | ||
|
|
71f53d49ca | ||
|
|
d9b4e24b29 | ||
|
|
7b89717092 | ||
|
|
aaf3410708 | ||
|
|
48ec104a34 | ||
|
|
4080bd1325 | ||
|
|
8f156f3609 | ||
|
|
e51874d46a | ||
|
|
464c8eb77a | ||
|
|
4a52596344 | ||
|
|
1f5012684b | ||
|
|
aab4fd7225 | ||
|
|
92c224b616 | ||
|
|
1a81f02377 | ||
|
|
d0c0ddd7e5 | ||
|
|
3283a10561 | ||
|
|
db42b5b062 | ||
|
|
49710c9509 | ||
|
|
8f679bf1d3 | ||
|
|
1ab6a9bc84 | ||
|
|
34aff5953f | ||
|
|
791dfb78ab | ||
|
|
99e05b777a | ||
|
|
10c501d474 | ||
|
|
f5db4b12ba | ||
|
|
cf65b1f87a | ||
|
|
9f45ef8df5 | ||
|
|
0f47a38042 | ||
|
|
f285a31a5a | ||
|
|
2ca0e37be7 | ||
|
|
eb6e797001 | ||
|
|
6316949e36 | ||
|
|
85840578ad | ||
|
|
af1dd6251e | ||
|
|
ee455abe52 | ||
|
|
3766dbff69 | ||
|
|
846fc13519 | ||
|
|
b93c49afae | ||
|
|
99c5585790 | ||
|
|
1a7b30c13a | ||
|
|
2f89ba9499 | ||
|
|
cb8addc4cd | ||
|
|
9cac2e1945 | ||
|
|
1b47d538ae | ||
|
|
51d74d78c6 | ||
|
|
d5ae06e7ed | ||
|
|
05f9154bdd | ||
|
|
d7df249480 | ||
|
|
a6feae0fbb | ||
|
|
a22fb2c1ba | ||
|
|
fe4bb24a3e | ||
|
|
db50afeafe |
15
.idea/codeStyles/Project.xml
generated
15
.idea/codeStyles/Project.xml
generated
@@ -13,6 +13,21 @@
|
||||
</option>
|
||||
</JavaCodeStyleSettings>
|
||||
<JetCodeStyleSettings>
|
||||
<option name="PACKAGES_TO_USE_STAR_IMPORTS">
|
||||
<value>
|
||||
<package name="java.util" alias="false" withSubpackages="false" />
|
||||
<package name="kotlinx.android.synthetic" alias="false" withSubpackages="true" />
|
||||
</value>
|
||||
</option>
|
||||
<option name="PACKAGES_IMPORT_LAYOUT">
|
||||
<value>
|
||||
<package name="" alias="false" withSubpackages="true" />
|
||||
<package name="java" alias="false" withSubpackages="true" />
|
||||
<package name="javax" alias="false" withSubpackages="true" />
|
||||
<package name="kotlin" alias="false" withSubpackages="true" />
|
||||
<package name="" alias="true" withSubpackages="true" />
|
||||
</value>
|
||||
</option>
|
||||
<option name="CODE_STYLE_DEFAULTS" value="KOTLIN_OFFICIAL" />
|
||||
</JetCodeStyleSettings>
|
||||
<MarkdownNavigatorCodeStyleSettings>
|
||||
|
||||
21
.idea/runConfigurations/Test__stdlib_js_public_kotlin_api_test__overwrite_results.xml
generated
Normal file
21
.idea/runConfigurations/Test__stdlib_js_public_kotlin_api_test__overwrite_results.xml
generated
Normal file
@@ -0,0 +1,21 @@
|
||||
<component name="ProjectRunConfigurationManager">
|
||||
<configuration default="false" name="Test: stdlib-js public kotlin api test, overwrite results" type="GradleRunConfiguration" factoryName="Gradle">
|
||||
<ExternalSystemSettings>
|
||||
<option name="executionName" />
|
||||
<option name="externalProjectPath" value="$PROJECT_DIR$" />
|
||||
<option name="externalSystemIdString" value="GRADLE" />
|
||||
<option name="scriptParameters" value="--tests "org.jetbrains.kotlin.js.test.ApiTest" -Poverwrite.output=true" />
|
||||
<option name="taskDescriptions">
|
||||
<list />
|
||||
</option>
|
||||
<option name="taskNames">
|
||||
<list>
|
||||
<option value=":js:js.tests:test" />
|
||||
</list>
|
||||
</option>
|
||||
<option name="vmOptions" value="" />
|
||||
</ExternalSystemSettings>
|
||||
<GradleScriptDebugEnabled>false</GradleScriptDebugEnabled>
|
||||
<method v="2" />
|
||||
</configuration>
|
||||
</component>
|
||||
2
.idea/scopes/Apply_copyright.xml
generated
2
.idea/scopes/Apply_copyright.xml
generated
@@ -1,3 +1,3 @@
|
||||
<component name="DependencyValidationManager">
|
||||
<scope name="Apply copyright" pattern="!file[*]:*//testData//*&&!file[*]:testData//*&&!file[*]:*.gradle.kts&&!file[*]:*.gradle&&!file[kotlin.kotlin-ultimate]:*/&&!file[kotlin.kotlin-ultimate.*]:*/" />
|
||||
<scope name="Apply copyright" pattern="!file[*]:*//testData//*&&!file[*]:testData//*&&!file[*]:*.gradle.kts&&!file[*]:*.gradle&&!file[kotlin.kotlin-ultimate]:*/&&!file[kotlin.kotlin-ultimate.*]:*/&&!file[kotlin.libraries]:stdlib/api//*" />
|
||||
</component>
|
||||
@@ -1047,3 +1047,15 @@ val Jar.outputFile: File
|
||||
|
||||
val Project.sourceSetsOrNull: SourceSetContainer?
|
||||
get() = convention.findPlugin(JavaPluginConvention::class.java)?.sourceSets
|
||||
|
||||
val disableVerificationTasks = System.getProperty("disable.verification.tasks") == "true"
|
||||
if (disableVerificationTasks) {
|
||||
gradle.taskGraph.whenReady {
|
||||
allTasks.forEach {
|
||||
if (it is VerificationTask) {
|
||||
logger.info("DISABLED: '$it'")
|
||||
it.enabled = false
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -52,7 +52,6 @@ import org.jetbrains.kotlin.descriptors.impl.TypeAliasConstructorDescriptor;
|
||||
import org.jetbrains.kotlin.diagnostics.Errors;
|
||||
import org.jetbrains.kotlin.lexer.KtTokens;
|
||||
import org.jetbrains.kotlin.load.java.JvmAbi;
|
||||
import org.jetbrains.kotlin.resolve.sam.SamConstructorDescriptor;
|
||||
import org.jetbrains.kotlin.load.kotlin.MethodSignatureMappingKt;
|
||||
import org.jetbrains.kotlin.load.kotlin.TypeSignatureMappingKt;
|
||||
import org.jetbrains.kotlin.name.Name;
|
||||
@@ -77,6 +76,7 @@ import org.jetbrains.kotlin.resolve.jvm.diagnostics.JvmDeclarationOriginKt;
|
||||
import org.jetbrains.kotlin.resolve.jvm.jvmSignature.JvmMethodParameterKind;
|
||||
import org.jetbrains.kotlin.resolve.jvm.jvmSignature.JvmMethodParameterSignature;
|
||||
import org.jetbrains.kotlin.resolve.jvm.jvmSignature.JvmMethodSignature;
|
||||
import org.jetbrains.kotlin.resolve.sam.SamConstructorDescriptor;
|
||||
import org.jetbrains.kotlin.resolve.scopes.receivers.*;
|
||||
import org.jetbrains.kotlin.synthetic.SyntheticJavaPropertyDescriptor;
|
||||
import org.jetbrains.kotlin.types.*;
|
||||
@@ -1585,7 +1585,7 @@ public class ExpressionCodegen extends KtVisitor<StackValue, StackValue> impleme
|
||||
assert topOfStack == tryWithFinallyBlockStackElement : "Top element of stack doesn't equals processing finally block";
|
||||
|
||||
KtTryExpression jetTryExpression = tryWithFinallyBlockStackElement.expression;
|
||||
Label finallyStart = new Label();
|
||||
Label finallyStart = linkedLabel();
|
||||
v.mark(finallyStart);
|
||||
tryWithFinallyBlockStackElement.addGapLabel(finallyStart);
|
||||
addGapLabelsForNestedTryCatchWithoutFinally(state, nestedTryBlocksWithoutFinally, finallyStart);
|
||||
|
||||
@@ -60,6 +60,7 @@ import org.jetbrains.org.objectweb.asm.Opcodes.*
|
||||
import org.jetbrains.org.objectweb.asm.Type
|
||||
import org.jetbrains.org.objectweb.asm.commons.InstructionAdapter
|
||||
import org.jetbrains.org.objectweb.asm.commons.Method
|
||||
import org.jetbrains.org.objectweb.asm.tree.LabelNode
|
||||
import java.util.*
|
||||
|
||||
fun generateIsCheck(
|
||||
@@ -666,3 +667,22 @@ private fun generateLambdaForRunSuspend(
|
||||
lambdaBuilder.done()
|
||||
return lambdaBuilder.thisName
|
||||
}
|
||||
|
||||
internal fun LabelNode.linkWithLabel(): LabelNode {
|
||||
// Remember labelNode in label and vise versa.
|
||||
// Before ASM 8 there was JB patch in MethodNode that makes such linking in constructor of LabelNode.
|
||||
//
|
||||
// protected LabelNode getLabelNode(final Label label) {
|
||||
// if (!(label.info instanceof LabelNode)) {
|
||||
// //label.info = new LabelNode(label); //[JB: needed for Coverage agent]
|
||||
// label.info = new LabelNode(); //ASM 8
|
||||
// }
|
||||
// return (LabelNode) label.info;
|
||||
// }
|
||||
if (label.info == null) {
|
||||
label.info = this
|
||||
}
|
||||
return this
|
||||
}
|
||||
|
||||
fun linkedLabel(): Label = LabelNode().linkWithLabel().label
|
||||
@@ -8,6 +8,7 @@ package org.jetbrains.kotlin.codegen.coroutines
|
||||
import com.intellij.util.ArrayUtil
|
||||
import org.jetbrains.kotlin.backend.common.CodegenUtil
|
||||
import org.jetbrains.kotlin.builtins.isSuspendFunctionTypeOrSubtype
|
||||
import org.jetbrains.kotlin.cfg.index
|
||||
import org.jetbrains.kotlin.codegen.*
|
||||
import org.jetbrains.kotlin.codegen.binding.CalculatedClosure
|
||||
import org.jetbrains.kotlin.codegen.binding.CodegenBinding
|
||||
@@ -22,6 +23,7 @@ import org.jetbrains.kotlin.config.LanguageFeature
|
||||
import org.jetbrains.kotlin.config.isReleaseCoroutines
|
||||
import org.jetbrains.kotlin.descriptors.*
|
||||
import org.jetbrains.kotlin.descriptors.annotations.Annotations
|
||||
import org.jetbrains.kotlin.descriptors.impl.AnonymousFunctionDescriptor
|
||||
import org.jetbrains.kotlin.descriptors.impl.SimpleFunctionDescriptorImpl
|
||||
import org.jetbrains.kotlin.descriptors.impl.ValueParameterDescriptorImpl
|
||||
import org.jetbrains.kotlin.incremental.components.NoLookupLocation
|
||||
@@ -229,6 +231,7 @@ class CoroutineCodegenForLambda private constructor(
|
||||
|
||||
override fun generateClosureBody() {
|
||||
for (parameter in allFunctionParameters()) {
|
||||
if (parameter.isUnused()) continue
|
||||
val fieldInfo = parameter.getFieldInfoForCoroutineLambdaParameter()
|
||||
v.newField(
|
||||
OtherOrigin(parameter),
|
||||
@@ -241,6 +244,10 @@ class CoroutineCodegenForLambda private constructor(
|
||||
generateResumeImpl()
|
||||
}
|
||||
|
||||
private fun ParameterDescriptor.isUnused(): Boolean =
|
||||
originalSuspendFunctionDescriptor is AnonymousFunctionDescriptor &&
|
||||
bindingContext[BindingContext.SUSPEND_LAMBDA_PARAMETER_USED, originalSuspendFunctionDescriptor to index()] != true
|
||||
|
||||
private val generateErasedCreate: Boolean = allFunctionParameters().size <= 1
|
||||
|
||||
private val doNotGenerateInvokeBridge: Boolean = !originalSuspendFunctionDescriptor.isLocalSuspendFunctionNotSuspendLambda()
|
||||
@@ -398,39 +405,41 @@ class CoroutineCodegenForLambda private constructor(
|
||||
var index = 1
|
||||
for (parameter in allFunctionParameters()) {
|
||||
val fieldInfoForCoroutineLambdaParameter = parameter.getFieldInfoForCoroutineLambdaParameter()
|
||||
if (isBigArity) {
|
||||
load(cloneIndex, fieldInfoForCoroutineLambdaParameter.ownerType)
|
||||
load(1, AsmTypes.OBJECT_TYPE)
|
||||
iconst(index - 1)
|
||||
aload(AsmTypes.OBJECT_TYPE)
|
||||
StackValue.coerce(
|
||||
AsmTypes.OBJECT_TYPE, builtIns.nullableAnyType,
|
||||
fieldInfoForCoroutineLambdaParameter.fieldType, fieldInfoForCoroutineLambdaParameter.fieldKotlinType,
|
||||
this
|
||||
)
|
||||
putfield(
|
||||
fieldInfoForCoroutineLambdaParameter.ownerInternalName,
|
||||
fieldInfoForCoroutineLambdaParameter.fieldName,
|
||||
fieldInfoForCoroutineLambdaParameter.fieldType.descriptor
|
||||
)
|
||||
} else {
|
||||
if (generateErasedCreate) {
|
||||
load(index, AsmTypes.OBJECT_TYPE)
|
||||
if (!parameter.isUnused()) {
|
||||
if (isBigArity) {
|
||||
load(cloneIndex, fieldInfoForCoroutineLambdaParameter.ownerType)
|
||||
load(1, AsmTypes.OBJECT_TYPE)
|
||||
iconst(index - 1)
|
||||
aload(AsmTypes.OBJECT_TYPE)
|
||||
StackValue.coerce(
|
||||
AsmTypes.OBJECT_TYPE, builtIns.nullableAnyType,
|
||||
fieldInfoForCoroutineLambdaParameter.fieldType, fieldInfoForCoroutineLambdaParameter.fieldKotlinType,
|
||||
this
|
||||
)
|
||||
putfield(
|
||||
fieldInfoForCoroutineLambdaParameter.ownerInternalName,
|
||||
fieldInfoForCoroutineLambdaParameter.fieldName,
|
||||
fieldInfoForCoroutineLambdaParameter.fieldType.descriptor
|
||||
)
|
||||
} else {
|
||||
load(index, fieldInfoForCoroutineLambdaParameter.fieldType)
|
||||
if (generateErasedCreate) {
|
||||
load(index, AsmTypes.OBJECT_TYPE)
|
||||
StackValue.coerce(
|
||||
AsmTypes.OBJECT_TYPE, builtIns.nullableAnyType,
|
||||
fieldInfoForCoroutineLambdaParameter.fieldType, fieldInfoForCoroutineLambdaParameter.fieldKotlinType,
|
||||
this
|
||||
)
|
||||
} else {
|
||||
load(index, fieldInfoForCoroutineLambdaParameter.fieldType)
|
||||
}
|
||||
AsmUtil.genAssignInstanceFieldFromParam(
|
||||
fieldInfoForCoroutineLambdaParameter,
|
||||
index,
|
||||
this,
|
||||
cloneIndex,
|
||||
generateErasedCreate
|
||||
)
|
||||
}
|
||||
AsmUtil.genAssignInstanceFieldFromParam(
|
||||
fieldInfoForCoroutineLambdaParameter,
|
||||
index,
|
||||
this,
|
||||
cloneIndex,
|
||||
generateErasedCreate
|
||||
)
|
||||
}
|
||||
index += if (isBigArity || generateErasedCreate) 1 else fieldInfoForCoroutineLambdaParameter.fieldType.size
|
||||
}
|
||||
@@ -442,6 +451,7 @@ class CoroutineCodegenForLambda private constructor(
|
||||
|
||||
private fun ExpressionCodegen.initializeCoroutineParameters() {
|
||||
for (parameter in allFunctionParameters()) {
|
||||
if (parameter.isUnused()) continue
|
||||
val fieldStackValue =
|
||||
StackValue.field(
|
||||
parameter.getFieldInfoForCoroutineLambdaParameter(), generateThisOrOuter(context.thisDescriptor, false)
|
||||
@@ -463,7 +473,11 @@ class CoroutineCodegenForLambda private constructor(
|
||||
v.visitLocalVariable(name, mappedType.descriptor, null, label, endLabel, newIndex)
|
||||
}
|
||||
|
||||
initializeVariablesForDestructuredLambdaParameters(this, originalSuspendFunctionDescriptor.valueParameters, endLabel)
|
||||
initializeVariablesForDestructuredLambdaParameters(
|
||||
this,
|
||||
originalSuspendFunctionDescriptor.valueParameters.filter { !it.isUnused() },
|
||||
endLabel
|
||||
)
|
||||
}
|
||||
|
||||
private fun allFunctionParameters(): List<ParameterDescriptor> =
|
||||
|
||||
@@ -12,6 +12,7 @@ import org.jetbrains.kotlin.codegen.TransformationMethodVisitor
|
||||
import org.jetbrains.kotlin.codegen.inline.*
|
||||
import org.jetbrains.kotlin.codegen.optimization.common.*
|
||||
import org.jetbrains.kotlin.codegen.optimization.fixStack.FixStackMethodTransformer
|
||||
import org.jetbrains.kotlin.codegen.linkWithLabel
|
||||
import org.jetbrains.kotlin.config.LanguageVersionSettings
|
||||
import org.jetbrains.kotlin.config.isReleaseCoroutines
|
||||
import org.jetbrains.kotlin.resolve.jvm.AsmTypes
|
||||
@@ -593,7 +594,7 @@ class CoroutineTransformerMethodVisitor(
|
||||
|
||||
private fun spillVariables(suspensionPoints: List<SuspensionPoint>, methodNode: MethodNode): List<List<SpilledVariableDescriptor>> {
|
||||
val instructions = methodNode.instructions
|
||||
val frames = performSpilledVariableFieldTypesAnalysis(methodNode, containingClassInternalName)
|
||||
val frames = performRefinedTypeAnalysis(methodNode, containingClassInternalName)
|
||||
fun AbstractInsnNode.index() = instructions.indexOf(this)
|
||||
|
||||
// We postpone these actions because they change instruction indices that we use when obtaining frames
|
||||
@@ -641,11 +642,11 @@ class CoroutineTransformerMethodVisitor(
|
||||
.map { Pair(it, frame.getLocal(it)) }
|
||||
.filter { (index, value) ->
|
||||
(index == 0 && needDispatchReceiver && isForNamedFunction) ||
|
||||
(value.type != null && livenessFrame.isAlive(index))
|
||||
(value != StrictBasicValue.UNINITIALIZED_VALUE && livenessFrame.isAlive(index))
|
||||
}
|
||||
|
||||
for ((index, basicValue) in variablesToSpill) {
|
||||
if (basicValue.type == NULL_TYPE) {
|
||||
if (basicValue === StrictBasicValue.NULL_VALUE) {
|
||||
postponedActions.add {
|
||||
with(instructions) {
|
||||
insert(suspension.tryCatchBlockEndLabelAfterSuspensionCall, withInstructionAdapter {
|
||||
@@ -657,7 +658,7 @@ class CoroutineTransformerMethodVisitor(
|
||||
continue
|
||||
}
|
||||
|
||||
val type = basicValue.type!!
|
||||
val type = basicValue.type
|
||||
val normalizedType = type.normalize()
|
||||
|
||||
val indexBySort = varsCountByType[normalizedType]?.plus(1) ?: 0
|
||||
@@ -741,7 +742,7 @@ class CoroutineTransformerMethodVisitor(
|
||||
suspendMarkerVarIndex: Int,
|
||||
suspendPointLineNumber: LineNumberNode?
|
||||
): LabelNode {
|
||||
val continuationLabel = LabelNode()
|
||||
val continuationLabel = LabelNode().linkWithLabel()
|
||||
val continuationLabelAfterLoadedResult = LabelNode()
|
||||
val suspendElementLineNumber = lineNumber
|
||||
var nextLineNumberNode = nextDefinitelyHitLineNumber(suspension)
|
||||
|
||||
@@ -18,6 +18,7 @@ import org.jetbrains.org.objectweb.asm.Type
|
||||
import org.jetbrains.org.objectweb.asm.tree.*
|
||||
import org.jetbrains.org.objectweb.asm.tree.analysis.BasicInterpreter
|
||||
import org.jetbrains.org.objectweb.asm.tree.analysis.BasicValue
|
||||
import org.jetbrains.org.objectweb.asm.tree.analysis.Frame
|
||||
|
||||
private class PossibleSpilledValue(val source: AbstractInsnNode, type: Type?) : BasicValue(type) {
|
||||
val usages = mutableSetOf<AbstractInsnNode>()
|
||||
|
||||
@@ -1,309 +0,0 @@
|
||||
/*
|
||||
* Copyright 2010-2019 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.codegen.coroutines
|
||||
|
||||
import org.jetbrains.kotlin.codegen.inline.insnOpcodeText
|
||||
import org.jetbrains.kotlin.codegen.optimization.common.MethodAnalyzer
|
||||
import org.jetbrains.kotlin.resolve.jvm.AsmTypes
|
||||
import org.jetbrains.org.objectweb.asm.Handle
|
||||
import org.jetbrains.org.objectweb.asm.Opcodes.*
|
||||
import org.jetbrains.org.objectweb.asm.Type
|
||||
import org.jetbrains.org.objectweb.asm.tree.*
|
||||
import org.jetbrains.org.objectweb.asm.tree.analysis.Frame
|
||||
import org.jetbrains.org.objectweb.asm.tree.analysis.Interpreter
|
||||
import org.jetbrains.org.objectweb.asm.tree.analysis.Value
|
||||
|
||||
// BasicValue interpreter from ASM does not distinct 'int' types from other int-like types like 'byte' or 'boolean',
|
||||
// neither do HotSpot and JVM spec.
|
||||
// But it seems like Dalvik does not follow it, and spilling boolean value into an 'int' field fails with VerifyError on Android 4,
|
||||
// so this function calculates refined frames' markup.
|
||||
// Note that type of some values is only possible to determine by their usages (e.g. ICONST_1, BALOAD both may push boolean or byte on stack)
|
||||
// In this case, update the type of the value.
|
||||
|
||||
// StrictBasicValue with mutable type
|
||||
internal open class SpilledVariableFieldTypeValue(open var type: Type?, val insn: AbstractInsnNode?) : Value {
|
||||
override fun getSize(): Int = type?.size ?: 1
|
||||
|
||||
override fun equals(other: Any?): Boolean = other is SpilledVariableFieldTypeValue && type == other.type && insn == other.insn
|
||||
|
||||
override fun hashCode(): Int = (type?.hashCode() ?: 0) xor insn.hashCode()
|
||||
|
||||
override fun toString() = if (type == null) "." else "$type"
|
||||
}
|
||||
|
||||
private class MergedSpilledVariableFieldTypeValue(
|
||||
val values: Set<SpilledVariableFieldTypeValue>
|
||||
) : SpilledVariableFieldTypeValue(null, null) {
|
||||
override var type: Type?
|
||||
get() = values.first().type
|
||||
set(newType) {
|
||||
for (value in values) {
|
||||
value.type = newType
|
||||
}
|
||||
}
|
||||
|
||||
override fun equals(other: Any?): Boolean = other is MergedSpilledVariableFieldTypeValue && other.values == values
|
||||
|
||||
override fun hashCode(): Int = values.hashCode()
|
||||
|
||||
override fun toString(): String = "M$values"
|
||||
}
|
||||
|
||||
private operator fun SpilledVariableFieldTypeValue?.plus(other: SpilledVariableFieldTypeValue?): SpilledVariableFieldTypeValue? = when {
|
||||
this == null -> other
|
||||
other == null -> this
|
||||
this == other -> this
|
||||
this is MergedSpilledVariableFieldTypeValue -> {
|
||||
if (other is MergedSpilledVariableFieldTypeValue) MergedSpilledVariableFieldTypeValue(values + other.values)
|
||||
else MergedSpilledVariableFieldTypeValue(values + other)
|
||||
}
|
||||
other is MergedSpilledVariableFieldTypeValue -> MergedSpilledVariableFieldTypeValue(other.values + this)
|
||||
else -> MergedSpilledVariableFieldTypeValue(setOf(this, other))
|
||||
}
|
||||
|
||||
internal val NULL_TYPE = Type.getObjectType("null")
|
||||
|
||||
// Same as BasicInterpreter, but updates types based on usages
|
||||
private class SpilledVariableFieldTypesInterpreter(
|
||||
private val methodNode: MethodNode
|
||||
) : Interpreter<SpilledVariableFieldTypeValue>(API_VERSION) {
|
||||
override fun newValue(type: Type?): SpilledVariableFieldTypeValue? =
|
||||
if (type == Type.VOID_TYPE) null else SpilledVariableFieldTypeValue(type, null)
|
||||
|
||||
// INVOKEVIRTUAL, INVOKESPECIAL, INVOKESTATIC, INVOKEINTERFACE,
|
||||
// MULTIANEWARRAY and INVOKEDYNAMIC
|
||||
override fun naryOperation(
|
||||
insn: AbstractInsnNode,
|
||||
values: MutableList<out SpilledVariableFieldTypeValue?>
|
||||
): SpilledVariableFieldTypeValue? {
|
||||
fun updateTypes(argTypes: Array<Type>, withReceiver: Boolean) {
|
||||
val offset = if (withReceiver) 1 else 0
|
||||
for ((index, argType) in argTypes.withIndex()) {
|
||||
val value = values[index + offset] ?: continue
|
||||
if (argType.isIntType()) {
|
||||
value.type = argType
|
||||
} else if (
|
||||
(value.type == AsmTypes.OBJECT_TYPE && argType != AsmTypes.OBJECT_TYPE) ||
|
||||
value.type == NULL_TYPE || value.type == null
|
||||
) {
|
||||
value.type = argType
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return SpilledVariableFieldTypeValue(
|
||||
when (insn.opcode) {
|
||||
MULTIANEWARRAY -> {
|
||||
Type.getType((insn as MultiANewArrayInsnNode).desc)
|
||||
}
|
||||
INVOKEDYNAMIC -> {
|
||||
updateTypes(Type.getArgumentTypes((insn as InvokeDynamicInsnNode).desc), false)
|
||||
Type.getReturnType(insn.desc)
|
||||
}
|
||||
INVOKESTATIC -> {
|
||||
updateTypes(Type.getArgumentTypes((insn as MethodInsnNode).desc), false)
|
||||
Type.getReturnType(insn.desc)
|
||||
}
|
||||
INVOKEVIRTUAL, INVOKEINTERFACE, INVOKESPECIAL -> {
|
||||
updateTypes(Type.getArgumentTypes((insn as MethodInsnNode).desc), true)
|
||||
Type.getReturnType(insn.desc)
|
||||
}
|
||||
else -> {
|
||||
unreachable(insn)
|
||||
}
|
||||
}, insn
|
||||
)
|
||||
}
|
||||
|
||||
private fun Type.isIntType(): Boolean = when (sort) {
|
||||
Type.BOOLEAN, Type.BYTE, Type.CHAR, Type.SHORT, Type.INT -> true
|
||||
else -> false
|
||||
}
|
||||
|
||||
private fun unreachable(insn: AbstractInsnNode): Nothing = error("Unreachable instruction ${insn.insnOpcodeText}")
|
||||
|
||||
// IASTORE, LASTORE, FASTORE, DASTORE, AASTORE, BASTORE, CASTORE, SASTORE
|
||||
override fun ternaryOperation(
|
||||
insn: AbstractInsnNode,
|
||||
arrayref: SpilledVariableFieldTypeValue?,
|
||||
index: SpilledVariableFieldTypeValue?,
|
||||
value: SpilledVariableFieldTypeValue?
|
||||
): SpilledVariableFieldTypeValue? {
|
||||
when (insn.opcode) {
|
||||
IASTORE, LASTORE, FASTORE, DASTORE, AASTORE -> {
|
||||
// nothing to do
|
||||
}
|
||||
BASTORE -> {
|
||||
value?.type = if (arrayref?.type?.descriptor == "[Z") Type.BOOLEAN_TYPE else Type.BYTE_TYPE
|
||||
}
|
||||
CASTORE -> {
|
||||
value?.type = Type.CHAR_TYPE
|
||||
}
|
||||
SASTORE -> {
|
||||
value?.type = Type.SHORT_TYPE
|
||||
}
|
||||
else -> unreachable(insn)
|
||||
}
|
||||
return null
|
||||
}
|
||||
|
||||
override fun merge(v: SpilledVariableFieldTypeValue?, w: SpilledVariableFieldTypeValue?): SpilledVariableFieldTypeValue? = when {
|
||||
v?.type?.isIntType() == true && w?.type?.isIntType() == true -> v + w
|
||||
v != null && v.type == null -> w
|
||||
w != null && w.type == null -> v
|
||||
v?.type == w?.type -> v
|
||||
v?.type?.sort == Type.OBJECT && w?.type?.sort == Type.OBJECT -> {
|
||||
when {
|
||||
v.type == AsmTypes.OBJECT_TYPE -> v
|
||||
w.type == AsmTypes.OBJECT_TYPE -> w
|
||||
else -> SpilledVariableFieldTypeValue(AsmTypes.OBJECT_TYPE, v.insn)
|
||||
}
|
||||
}
|
||||
else -> SpilledVariableFieldTypeValue(null, v?.insn ?: w?.insn)
|
||||
}
|
||||
|
||||
// IRETURN, LRETURN, FRETURN, DRETURN, ARETURN
|
||||
override fun returnOperation(insn: AbstractInsnNode, value: SpilledVariableFieldTypeValue?, expected: SpilledVariableFieldTypeValue?) {
|
||||
if (insn.opcode == IRETURN) {
|
||||
value?.type = expected?.type
|
||||
}
|
||||
}
|
||||
|
||||
// INEG, LNEG, FNEG, DNEG, IINC, I2L, I2F, I2D, L2I, L2F, L2D, F2I, F2L,
|
||||
// F2D, D2I, D2L, D2F, I2B, I2C, I2S, IFEQ, IFNE, IFLT, IFGE, IFGT, IFLE,
|
||||
// TABLESWITCH, LOOKUPSWITCH, IRETURN, LRETURN, FRETURN, DRETURN, ARETURN,
|
||||
// PUTSTATIC, GETFIELD, NEWARRAY, ANEWARRAY, ARRAYLENGTH, ATHROW, CHECKCAST,
|
||||
// INSTANCEOF, MONITORENTER, MONITOREXIT, IFNULL, IFNONNULL
|
||||
override fun unaryOperation(insn: AbstractInsnNode, value: SpilledVariableFieldTypeValue?): SpilledVariableFieldTypeValue? =
|
||||
when (insn.opcode) {
|
||||
INEG, LNEG, FNEG, DNEG, IINC -> SpilledVariableFieldTypeValue(value?.type, insn)
|
||||
I2L, F2L, D2L -> SpilledVariableFieldTypeValue(Type.LONG_TYPE, insn)
|
||||
I2F, L2F, D2F -> SpilledVariableFieldTypeValue(Type.FLOAT_TYPE, insn)
|
||||
L2D, I2D, F2D -> SpilledVariableFieldTypeValue(Type.DOUBLE_TYPE, insn)
|
||||
L2I, F2I, D2I, ARRAYLENGTH -> SpilledVariableFieldTypeValue(Type.INT_TYPE, insn)
|
||||
I2B -> SpilledVariableFieldTypeValue(Type.BYTE_TYPE, insn)
|
||||
I2C -> SpilledVariableFieldTypeValue(Type.CHAR_TYPE, insn)
|
||||
I2S -> SpilledVariableFieldTypeValue(Type.SHORT_TYPE, insn)
|
||||
IFEQ, IFNE, IFLT, IFGE, IFGT, IFLE, TABLESWITCH, LOOKUPSWITCH, IRETURN, LRETURN, FRETURN, DRETURN, ARETURN,
|
||||
ATHROW, MONITORENTER, MONITOREXIT, IFNULL, IFNONNULL -> null
|
||||
PUTSTATIC -> {
|
||||
val expectedType = Type.getType((insn as FieldInsnNode).desc)
|
||||
if (expectedType.isIntType()) {
|
||||
value?.type = expectedType
|
||||
}
|
||||
null
|
||||
}
|
||||
GETFIELD -> SpilledVariableFieldTypeValue(Type.getType((insn as FieldInsnNode).desc), insn)
|
||||
NEWARRAY -> when ((insn as IntInsnNode).operand) {
|
||||
T_BOOLEAN -> SpilledVariableFieldTypeValue(Type.getType("[Z"), insn)
|
||||
T_CHAR -> SpilledVariableFieldTypeValue(Type.getType("[C"), insn)
|
||||
T_BYTE -> SpilledVariableFieldTypeValue(Type.getType("[B"), insn)
|
||||
T_SHORT -> SpilledVariableFieldTypeValue(Type.getType("[S"), insn)
|
||||
T_INT -> SpilledVariableFieldTypeValue(Type.getType("[I"), insn)
|
||||
T_FLOAT -> SpilledVariableFieldTypeValue(Type.getType("[F"), insn)
|
||||
T_DOUBLE -> SpilledVariableFieldTypeValue(Type.getType("[D"), insn)
|
||||
T_LONG -> SpilledVariableFieldTypeValue(Type.getType("[J"), insn)
|
||||
else -> unreachable(insn)
|
||||
}
|
||||
ANEWARRAY -> SpilledVariableFieldTypeValue(Type.getType("[${Type.getObjectType((insn as TypeInsnNode).desc)}"), insn)
|
||||
CHECKCAST -> SpilledVariableFieldTypeValue(Type.getObjectType((insn as TypeInsnNode).desc), insn)
|
||||
INSTANCEOF -> SpilledVariableFieldTypeValue(Type.BOOLEAN_TYPE, insn)
|
||||
else -> unreachable(insn)
|
||||
}
|
||||
|
||||
// IALOAD, LALOAD, FALOAD, DALOAD, AALOAD, BALOAD, CALOAD, SALOAD, IADD,
|
||||
// LADD, FADD, DADD, ISUB, LSUB, FSUB, DSUB, IMUL, LMUL, FMUL, DMUL, IDIV,
|
||||
// LDIV, FDIV, DDIV, IREM, LREM, FREM, DREM, ISHL, LSHL, ISHR, LSHR, IUSHR,
|
||||
// LUSHR, IAND, LAND, IOR, LOR, IXOR, LXOR, LCMP, FCMPL, FCMPG, DCMPL,
|
||||
// DCMPG, IF_ICMPEQ, IF_ICMPNE, IF_ICMPLT, IF_ICMPGE, IF_ICMPGT, IF_ICMPLE,
|
||||
// IF_ACMPEQ, IF_ACMPNE, PUTFIELD
|
||||
override fun binaryOperation(
|
||||
insn: AbstractInsnNode,
|
||||
v: SpilledVariableFieldTypeValue?,
|
||||
w: SpilledVariableFieldTypeValue?
|
||||
): SpilledVariableFieldTypeValue? =
|
||||
when (insn.opcode) {
|
||||
IALOAD, IADD, ISUB, IMUL, IDIV, IREM, ISHL, ISHR, IUSHR, IAND, IOR, IXOR, LCMP, FCMPL, FCMPG, DCMPL,
|
||||
DCMPG -> SpilledVariableFieldTypeValue(Type.INT_TYPE, insn)
|
||||
LALOAD, LADD, LSUB, LMUL, LDIV, LREM, LSHL, LSHR, LUSHR, LAND, LOR, LXOR -> SpilledVariableFieldTypeValue(Type.LONG_TYPE, insn)
|
||||
FALOAD, FADD, FSUB, FMUL, FDIV, FREM -> SpilledVariableFieldTypeValue(Type.FLOAT_TYPE, insn)
|
||||
DALOAD, DADD, DSUB, DMUL, DDIV, DREM -> SpilledVariableFieldTypeValue(Type.DOUBLE_TYPE, insn)
|
||||
AALOAD -> SpilledVariableFieldTypeValue(AsmTypes.OBJECT_TYPE, insn)
|
||||
BALOAD -> SpilledVariableFieldTypeValue(if (v?.type?.descriptor == "[Z") Type.BOOLEAN_TYPE else Type.BYTE_TYPE, insn)
|
||||
CALOAD -> SpilledVariableFieldTypeValue(Type.CHAR_TYPE, insn)
|
||||
SALOAD -> SpilledVariableFieldTypeValue(Type.SHORT_TYPE, insn)
|
||||
IF_ICMPEQ, IF_ICMPNE, IF_ICMPLT, IF_ICMPGE, IF_ICMPGT, IF_ICMPLE, IF_ACMPEQ, IF_ACMPNE -> null
|
||||
PUTFIELD -> {
|
||||
val expectedType = Type.getType((insn as FieldInsnNode).desc)
|
||||
if (expectedType.isIntType()) {
|
||||
w?.type = expectedType
|
||||
}
|
||||
null
|
||||
}
|
||||
else -> unreachable(insn)
|
||||
}
|
||||
|
||||
// ILOAD, LLOAD, FLOAD, DLOAD, ALOAD, ISTORE, LSTORE, FSTORE, DSTORE,
|
||||
// ASTORE, DUP, DUP_X1, DUP_X2, DUP2, DUP2_X1, DUP2_X2, SWAP
|
||||
override fun copyOperation(insn: AbstractInsnNode, value: SpilledVariableFieldTypeValue?): SpilledVariableFieldTypeValue? =
|
||||
when (insn.opcode) {
|
||||
// If same ICONST is stored into several slots, thay can have different types
|
||||
// For example,
|
||||
// val b: Byte = 1
|
||||
// val i: Int = b.toInt()
|
||||
// In this case, `b` and `i` have the same source, but different types.
|
||||
// The example also shows, that the types should be `I`.
|
||||
ISTORE -> SpilledVariableFieldTypeValue(Type.INT_TYPE, insn)
|
||||
// Sometimes we cannot get the type from the usage only
|
||||
// For example,
|
||||
// val c = '1'
|
||||
// if (c == '2) ...
|
||||
// In this case, update the type using information from LVT
|
||||
ILOAD -> {
|
||||
methodNode.localVariables.find { local ->
|
||||
local.index == (insn as VarInsnNode).`var` &&
|
||||
methodNode.instructions.indexOf(local.start) < methodNode.instructions.indexOf(insn) &&
|
||||
methodNode.instructions.indexOf(insn) < methodNode.instructions.indexOf(local.end)
|
||||
}?.let { local ->
|
||||
value?.type = Type.getType(local.desc)
|
||||
}
|
||||
value
|
||||
}
|
||||
else -> value
|
||||
}
|
||||
|
||||
// ACONST_NULL, ICONST_M1, ICONST_0, ICONST_1, ICONST_2, ICONST_3, ICONST_4,
|
||||
// ICONST_5, LCONST_0, LCONST_1, FCONST_0, FCONST_1, FCONST_2, DCONST_0,
|
||||
// DCONST_1, BIPUSH, SIPUSH, LDC, JSR, GETSTATIC, NEW
|
||||
override fun newOperation(insn: AbstractInsnNode): SpilledVariableFieldTypeValue? = when (insn.opcode) {
|
||||
ACONST_NULL -> SpilledVariableFieldTypeValue(NULL_TYPE, insn)
|
||||
ICONST_M1, ICONST_0, ICONST_1, ICONST_2, ICONST_3, ICONST_4, ICONST_5 -> SpilledVariableFieldTypeValue(Type.INT_TYPE, insn)
|
||||
LCONST_0, LCONST_1 -> SpilledVariableFieldTypeValue(Type.LONG_TYPE, insn)
|
||||
FCONST_0, FCONST_1, FCONST_2 -> SpilledVariableFieldTypeValue(Type.FLOAT_TYPE, insn)
|
||||
DCONST_0, DCONST_1 -> SpilledVariableFieldTypeValue(Type.DOUBLE_TYPE, insn)
|
||||
BIPUSH -> SpilledVariableFieldTypeValue(Type.BYTE_TYPE, insn)
|
||||
SIPUSH -> SpilledVariableFieldTypeValue(Type.SHORT_TYPE, insn)
|
||||
LDC -> when (val cst = (insn as LdcInsnNode).cst) {
|
||||
is Int -> SpilledVariableFieldTypeValue(Type.INT_TYPE, insn)
|
||||
is Long -> SpilledVariableFieldTypeValue(Type.LONG_TYPE, insn)
|
||||
is Float -> SpilledVariableFieldTypeValue(Type.FLOAT_TYPE, insn)
|
||||
is Double -> SpilledVariableFieldTypeValue(Type.DOUBLE_TYPE, insn)
|
||||
is String -> SpilledVariableFieldTypeValue(AsmTypes.JAVA_STRING_TYPE, insn)
|
||||
is Type -> SpilledVariableFieldTypeValue(AsmTypes.JAVA_CLASS_TYPE, insn)
|
||||
else -> SpilledVariableFieldTypeValue(AsmTypes.OBJECT_TYPE, insn)
|
||||
}
|
||||
JSR -> SpilledVariableFieldTypeValue(Type.VOID_TYPE, insn)
|
||||
GETSTATIC -> SpilledVariableFieldTypeValue(Type.getType((insn as FieldInsnNode).desc), insn)
|
||||
NEW -> SpilledVariableFieldTypeValue(Type.getObjectType((insn as TypeInsnNode).desc), insn)
|
||||
else -> unreachable(insn)
|
||||
}
|
||||
}
|
||||
|
||||
internal fun performSpilledVariableFieldTypesAnalysis(
|
||||
methodNode: MethodNode,
|
||||
thisName: String
|
||||
): Array<out Frame<SpilledVariableFieldTypeValue>?> =
|
||||
MethodAnalyzer(thisName, methodNode, SpilledVariableFieldTypesInterpreter(methodNode)).analyze()
|
||||
@@ -0,0 +1,221 @@
|
||||
/*
|
||||
* Copyright 2010-2019 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.codegen.coroutines
|
||||
|
||||
import org.jetbrains.kotlin.codegen.optimization.common.*
|
||||
import org.jetbrains.kotlin.codegen.optimization.fixStack.peek
|
||||
import org.jetbrains.kotlin.codegen.optimization.fixStack.top
|
||||
import org.jetbrains.kotlin.codegen.optimization.transformer.MethodTransformer
|
||||
import org.jetbrains.org.objectweb.asm.Opcodes
|
||||
import org.jetbrains.org.objectweb.asm.Type
|
||||
import org.jetbrains.org.objectweb.asm.tree.*
|
||||
import org.jetbrains.org.objectweb.asm.tree.analysis.BasicValue
|
||||
import org.jetbrains.org.objectweb.asm.tree.analysis.Frame
|
||||
import org.jetbrains.org.objectweb.asm.tree.analysis.SourceInterpreter
|
||||
import org.jetbrains.org.objectweb.asm.tree.analysis.SourceValue
|
||||
import java.util.*
|
||||
|
||||
// BasicValue interpreter from ASM does not distinct 'int' types from other int-like types like 'byte' or 'boolean',
|
||||
// neither do HotSpot and JVM spec.
|
||||
// But it seems like Dalvik does not follow it, and spilling boolean value into an 'int' field fails with VerifyError on Android 4,
|
||||
// so this function calculates refined frames' markup.
|
||||
// Note that type of some values is only possible to determine by their usages (e.g. ICONST_1, BALOAD both may push boolean or byte on stack)
|
||||
internal fun performRefinedTypeAnalysis(methodNode: MethodNode, thisName: String): Array<out Frame<out BasicValue>?> {
|
||||
val insnList = methodNode.instructions
|
||||
val basicFrames = MethodTransformer.analyze(thisName, methodNode, OptimizationBasicInterpreter())
|
||||
val sourceValueFrames = MethodTransformer.analyze(thisName, methodNode, MySourceInterpreter())
|
||||
|
||||
val expectedTypeAndSourcesByInsnIndex: Array<Pair<Type, List<SourceValue>>?> = arrayOfNulls(insnList.size())
|
||||
|
||||
fun AbstractInsnNode.index() = insnList.indexOf(this)
|
||||
|
||||
fun saveExpectedType(value: SourceValue?, expectedType: Type) {
|
||||
if (value == null) return
|
||||
if (expectedType.sort !in REFINED_INT_SORTS) return
|
||||
|
||||
for (insn in value.insns) {
|
||||
// If source is something like ICONST_0, ignore it
|
||||
if (!insn.isIntLoad()) continue
|
||||
val index = insnList.indexOf(insn)
|
||||
|
||||
checkUpdatedExpectedType(expectedTypeAndSourcesByInsnIndex[index]?.first, expectedType)
|
||||
|
||||
expectedTypeAndSourcesByInsnIndex[index] =
|
||||
Pair(expectedType,
|
||||
expectedTypeAndSourcesByInsnIndex[index]?.second.orEmpty() + value)
|
||||
}
|
||||
}
|
||||
|
||||
fun saveExpectedTypeForArrayStore(insn: AbstractInsnNode, sourceValueFrame: Frame<SourceValue>) {
|
||||
val arrayStoreType =
|
||||
when (insn.opcode) {
|
||||
Opcodes.BASTORE -> Type.BYTE_TYPE
|
||||
Opcodes.CASTORE -> Type.CHAR_TYPE
|
||||
Opcodes.SASTORE -> Type.SHORT_TYPE
|
||||
else -> return
|
||||
}
|
||||
|
||||
val insnIndex = insnList.indexOf(insn)
|
||||
|
||||
val arrayArg = basicFrames[insnIndex].peek(2)
|
||||
// may be different from 'arrayStoreType' in case of boolean arrays (BASTORE opcode is also used for them)
|
||||
val expectedType =
|
||||
if (arrayArg?.type?.sort == Type.ARRAY)
|
||||
arrayArg.type.elementType
|
||||
else
|
||||
arrayStoreType
|
||||
|
||||
saveExpectedType(sourceValueFrame.top(), expectedType)
|
||||
}
|
||||
|
||||
fun saveExpectedTypeForFieldOrMethod(insn: AbstractInsnNode, sourceValueFrame: Frame<SourceValue>) {
|
||||
when (insn.opcode) {
|
||||
Opcodes.PUTFIELD, Opcodes.PUTSTATIC ->
|
||||
saveExpectedType(sourceValueFrame.top(), Type.getType((insn as FieldInsnNode).desc))
|
||||
|
||||
Opcodes.INVOKESTATIC, Opcodes.INVOKEVIRTUAL, Opcodes.INVOKEINTERFACE, Opcodes.INVOKESPECIAL -> {
|
||||
val argumentTypes = Type.getArgumentTypes((insn as MethodInsnNode).desc)
|
||||
argumentTypes.withIndex().forEach {
|
||||
val (argIndex, type) = it
|
||||
saveExpectedType(sourceValueFrame.peek(argumentTypes.size - argIndex - 1), type)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fun saveExpectedTypeForVarStore(insn: AbstractInsnNode, sourceValueFrame: Frame<SourceValue>) {
|
||||
if (insn.isIntStore()) {
|
||||
val varIndex = (insn as VarInsnNode).`var`
|
||||
// Considering next insn is important because variable initializer is emitted just before
|
||||
// the beginning of variable
|
||||
val nextInsn = InsnSequence(insn.next, insnList.last).firstOrNull(AbstractInsnNode::isMeaningful)
|
||||
|
||||
val variableNode =
|
||||
methodNode.findContainingVariableFromTable(insn, varIndex)
|
||||
?: methodNode.findContainingVariableFromTable(nextInsn ?: return, varIndex)
|
||||
?: return
|
||||
|
||||
saveExpectedType(sourceValueFrame.top(), Type.getType(variableNode.desc))
|
||||
}
|
||||
}
|
||||
|
||||
for ((insnIndex, insn) in insnList.toArray().withIndex()) {
|
||||
assert(insn.opcode != Opcodes.IRETURN) {
|
||||
"Coroutine body must not contain IRETURN instructions because 'doResume' is always void"
|
||||
}
|
||||
|
||||
val sourceValueFrame = sourceValueFrames[insnIndex] ?: continue
|
||||
|
||||
saveExpectedTypeForArrayStore(insn, sourceValueFrame)
|
||||
saveExpectedTypeForFieldOrMethod(insn, sourceValueFrame)
|
||||
saveExpectedTypeForVarStore(insn, sourceValueFrame)
|
||||
}
|
||||
|
||||
val refinedVarFrames = analyze(methodNode, object : BackwardAnalysisInterpreter<VarExpectedTypeFrame> {
|
||||
override fun newFrame(maxLocals: Int): VarExpectedTypeFrame = VarExpectedTypeFrame(maxLocals)
|
||||
|
||||
override fun def(frame: VarExpectedTypeFrame, insn: AbstractInsnNode) {
|
||||
if (insn.isIntStore()) {
|
||||
frame.expectedTypeByVarIndex[(insn as VarInsnNode).`var`] = null
|
||||
}
|
||||
}
|
||||
|
||||
override fun use(frame: VarExpectedTypeFrame, insn: AbstractInsnNode) {
|
||||
val (expectedType, sources) = expectedTypeAndSourcesByInsnIndex[insn.index()] ?: return
|
||||
|
||||
sources.flatMap(SourceValue::insns).forEach { insnNode ->
|
||||
if (insnNode.isIntLoad()) {
|
||||
frame.updateExpectedType((insnNode as VarInsnNode).`var`, expectedType)
|
||||
}
|
||||
}
|
||||
}
|
||||
})
|
||||
|
||||
return Array(basicFrames.size) {
|
||||
insnIndex ->
|
||||
val current = Frame(basicFrames[insnIndex] ?: return@Array null)
|
||||
|
||||
refinedVarFrames[insnIndex].expectedTypeByVarIndex.withIndex().filter { it.value != null }.forEach {
|
||||
assert(current.getLocal(it.index)?.type?.sort in ALL_INT_SORTS) {
|
||||
"int type expected, but ${current.getLocal(it.index)?.type} was found in basic frames"
|
||||
}
|
||||
|
||||
current.setLocal(it.index, StrictBasicValue(it.value))
|
||||
}
|
||||
|
||||
current
|
||||
}
|
||||
}
|
||||
|
||||
private fun AbstractInsnNode.isIntLoad() = opcode == Opcodes.ILOAD
|
||||
private fun AbstractInsnNode.isIntStore() = opcode == Opcodes.ISTORE
|
||||
|
||||
private fun checkUpdatedExpectedType(was: Type?, new: Type) {
|
||||
assert(was == null || was == new) {
|
||||
"Conflicting expected types: $was/$new"
|
||||
}
|
||||
}
|
||||
|
||||
private class MySourceInterpreter : SourceInterpreter(Opcodes.API_VERSION) {
|
||||
override fun copyOperation(insn: AbstractInsnNode, value: SourceValue) =
|
||||
when {
|
||||
insn.isStoreOperation() || insn.isLoadOperation() -> SourceValue(value.size, insn)
|
||||
// For DUP* instructions return the same value (effectively ignore DUP's)
|
||||
else -> value
|
||||
}
|
||||
}
|
||||
|
||||
private val REFINED_INT_SORTS = setOf(Type.BOOLEAN, Type.CHAR, Type.BYTE, Type.SHORT)
|
||||
private val ALL_INT_SORTS = REFINED_INT_SORTS + Type.INT
|
||||
|
||||
private fun MethodNode.findContainingVariableFromTable(insn: AbstractInsnNode, varIndex: Int): LocalVariableNode? {
|
||||
val insnIndex = instructions.indexOf(insn)
|
||||
return localVariables.firstOrNull {
|
||||
it.index == varIndex && it.rangeContainsInsn(insnIndex, instructions)
|
||||
}
|
||||
}
|
||||
|
||||
private fun LocalVariableNode.rangeContainsInsn(insnIndex: Int, insnList: InsnList) =
|
||||
insnList.indexOf(start) < insnIndex && insnIndex < insnList.indexOf(end)
|
||||
|
||||
private class VarExpectedTypeFrame(maxLocals: Int) : VarFrame<VarExpectedTypeFrame> {
|
||||
val expectedTypeByVarIndex = arrayOfNulls<Type>(maxLocals)
|
||||
|
||||
override fun mergeFrom(other: VarExpectedTypeFrame) {
|
||||
assert(expectedTypeByVarIndex.size == other.expectedTypeByVarIndex.size) {
|
||||
"Other VarExpectedTypeFrame has different size: ${expectedTypeByVarIndex.size} / ${other.expectedTypeByVarIndex.size}"
|
||||
}
|
||||
|
||||
for ((varIndex, type) in other.expectedTypeByVarIndex.withIndex()) {
|
||||
updateExpectedType(varIndex, type ?: continue)
|
||||
}
|
||||
}
|
||||
|
||||
fun updateExpectedType(varIndex: Int, new: Type) {
|
||||
val was = expectedTypeByVarIndex[varIndex]
|
||||
// Widening to int is always allowed
|
||||
if (new == Type.INT_TYPE) return
|
||||
|
||||
checkUpdatedExpectedType(was, new)
|
||||
|
||||
expectedTypeByVarIndex[varIndex] = new
|
||||
}
|
||||
|
||||
override fun equals(other: Any?): Boolean {
|
||||
if (this === other) return true
|
||||
if (other == null || other::class.java != this::class.java) return false
|
||||
|
||||
other as VarExpectedTypeFrame
|
||||
|
||||
if (!Arrays.equals(expectedTypeByVarIndex, other.expectedTypeByVarIndex)) return false
|
||||
|
||||
return true
|
||||
}
|
||||
|
||||
override fun hashCode(): Int {
|
||||
return Arrays.hashCode(expectedTypeByVarIndex)
|
||||
}
|
||||
}
|
||||
@@ -6,6 +6,7 @@
|
||||
package org.jetbrains.kotlin.codegen.inline
|
||||
|
||||
import org.jetbrains.kotlin.codegen.*
|
||||
import org.jetbrains.kotlin.codegen.linkWithLabel
|
||||
import org.jetbrains.kotlin.codegen.state.GenerationState
|
||||
import org.jetbrains.kotlin.descriptors.FunctionDescriptor
|
||||
import org.jetbrains.kotlin.descriptors.ValueParameterDescriptor
|
||||
@@ -15,6 +16,7 @@ import org.jetbrains.kotlin.resolve.inline.InlineUtil
|
||||
import org.jetbrains.kotlin.resolve.jvm.jvmSignature.JvmMethodSignature
|
||||
import org.jetbrains.org.objectweb.asm.Label
|
||||
import org.jetbrains.org.objectweb.asm.Type
|
||||
import org.jetbrains.org.objectweb.asm.tree.LabelNode
|
||||
import org.jetbrains.org.objectweb.asm.tree.MethodNode
|
||||
|
||||
class InlineCodegenForDefaultBody(
|
||||
@@ -27,7 +29,7 @@ class InlineCodegenForDefaultBody(
|
||||
) : CallGenerator {
|
||||
private val sourceMapper: SourceMapper = codegen.parentCodegen.orCreateSourceMapper
|
||||
|
||||
private val methodStartLabel = Label()
|
||||
private val methodStartLabel = linkedLabel()
|
||||
|
||||
init {
|
||||
assert(InlineUtil.isInline(function)) {
|
||||
|
||||
@@ -33,6 +33,7 @@ import java.io.PrintWriter;
|
||||
import java.io.StringWriter;
|
||||
import java.util.*;
|
||||
|
||||
import static org.jetbrains.kotlin.codegen.CodegenUtilKt.linkedLabel;
|
||||
import static org.jetbrains.kotlin.codegen.inline.InlineCodegenUtilsKt.*;
|
||||
import static org.jetbrains.kotlin.codegen.inline.MethodInlinerUtilKt.getNextMeaningful;
|
||||
|
||||
@@ -198,7 +199,7 @@ public class InternalFinallyBlockInliner extends CoveringTryCatchNodeProcessor {
|
||||
//Creating temp node for finally block copy with some additional instruction
|
||||
MethodNode finallyBlockCopy = createEmptyMethodNode();
|
||||
Label newFinallyStart = new Label();
|
||||
Label insertedBlockEnd = new Label();
|
||||
Label insertedBlockEnd = linkedLabel();
|
||||
|
||||
boolean generateAloadAstore = nonLocalReturnType != Type.VOID_TYPE && !finallyInfo.isEmpty();
|
||||
if (generateAloadAstore) {
|
||||
|
||||
@@ -102,7 +102,7 @@ class MethodInliner(
|
||||
}
|
||||
|
||||
//substitute returns with "goto end" instruction to keep non local returns in lambdas
|
||||
val end = Label()
|
||||
val end = linkedLabel()
|
||||
val isTransformingAnonymousObject = nodeRemapper is RegeneratedLambdaFieldRemapper
|
||||
transformedNode = doInline(transformedNode)
|
||||
if (!isTransformingAnonymousObject) {
|
||||
|
||||
@@ -30,7 +30,7 @@ class LabelNormalizationMethodTransformer : MethodTransformer() {
|
||||
|
||||
private class TransformerForMethod(val methodNode: MethodNode) {
|
||||
val instructions = methodNode.instructions
|
||||
val newLabelNodes = SmartIdentityTable<Label, LabelNode>()
|
||||
val newLabelNodes = SmartIdentityTable<LabelNode, LabelNode>()
|
||||
|
||||
fun transform() {
|
||||
if (rewriteLabelInstructions()) {
|
||||
@@ -48,11 +48,11 @@ class LabelNormalizationMethodTransformer : MethodTransformer() {
|
||||
if (thisNode is LabelNode) {
|
||||
val prevNode = thisNode.previous
|
||||
if (prevNode is LabelNode) {
|
||||
newLabelNodes[thisNode.label] = prevNode
|
||||
newLabelNodes[thisNode] = prevNode
|
||||
removedAnyLabels = true
|
||||
thisNode = instructions.removeNodeGetNext(thisNode)
|
||||
} else {
|
||||
newLabelNodes[thisNode.label] = thisNode
|
||||
newLabelNodes[thisNode] = thisNode
|
||||
thisNode = thisNode.next
|
||||
}
|
||||
} else {
|
||||
@@ -145,12 +145,12 @@ class LabelNormalizationMethodTransformer : MethodTransformer() {
|
||||
}
|
||||
|
||||
private fun getNew(oldLabelNode: LabelNode): LabelNode {
|
||||
return newLabelNodes[oldLabelNode.label]
|
||||
return newLabelNodes[oldLabelNode]
|
||||
?: throw IllegalStateException("Label wasn't found during iterating through instructions")
|
||||
}
|
||||
|
||||
private fun getNewOrOld(oldLabelNode: LabelNode): LabelNode =
|
||||
newLabelNodes[oldLabelNode.label] ?: oldLabelNode
|
||||
newLabelNodes[oldLabelNode] ?: oldLabelNode
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -19,6 +19,7 @@ package org.jetbrains.kotlin.codegen.optimization.nullCheck
|
||||
import org.jetbrains.kotlin.codegen.coroutines.withInstructionAdapter
|
||||
import org.jetbrains.kotlin.codegen.inline.ReifiedTypeInliner
|
||||
import org.jetbrains.kotlin.codegen.intrinsics.IntrinsicMethods
|
||||
import org.jetbrains.kotlin.codegen.linkWithLabel
|
||||
import org.jetbrains.kotlin.codegen.optimization.common.StrictBasicValue
|
||||
import org.jetbrains.kotlin.codegen.optimization.common.debugText
|
||||
import org.jetbrains.kotlin.codegen.optimization.common.isInsn
|
||||
@@ -269,7 +270,7 @@ class RedundantNullCheckMethodTransformer(private val generationState: Generatio
|
||||
// <...> -- v is null here
|
||||
|
||||
val jumpsIfNull = insn.opcode == Opcodes.IFNULL
|
||||
val originalLabel = insn.label
|
||||
val originalLabel = insn.label.linkWithLabel()
|
||||
originalLabels[insn] = originalLabel
|
||||
insn.label = synthetic(LabelNode(Label()))
|
||||
|
||||
@@ -342,7 +343,7 @@ class RedundantNullCheckMethodTransformer(private val generationState: Generatio
|
||||
val originalLabel: LabelNode?
|
||||
val insertAfterNotNull: AbstractInsnNode
|
||||
if (jumpsIfInstance) {
|
||||
originalLabel = next.label
|
||||
originalLabel = next.label.linkWithLabel()
|
||||
originalLabels[next] = next.label
|
||||
val newLabel = synthetic(LabelNode(Label()))
|
||||
methodNode.instructions.add(newLabel)
|
||||
|
||||
@@ -77,44 +77,52 @@ object PluginCliParser {
|
||||
configuration: CompilerConfiguration,
|
||||
classLoader: URLClassLoader
|
||||
) {
|
||||
val optionValuesByPlugin = pluginOptions?.map(::parsePluginOption)?.groupBy {
|
||||
if (it == null) throw CliOptionProcessingException("Wrong plugin option format: $it, should be ${CommonCompilerArguments.PLUGIN_OPTION_FORMAT}")
|
||||
it.pluginId
|
||||
} ?: mapOf()
|
||||
|
||||
// TODO issue a warning on using deprecated command line processors when all official plugin migrate to the newer convention
|
||||
val commandLineProcessors = ServiceLoaderLite.loadImplementations(CommandLineProcessor::class.java, classLoader)
|
||||
|
||||
for (processor in commandLineProcessors) {
|
||||
val declaredOptions = processor.pluginOptions.associateBy { it.optionName }
|
||||
val optionsToValues = MultiMap<AbstractCliOption, CliOptionValue>()
|
||||
processCompilerPluginsOptions(configuration, pluginOptions, commandLineProcessors)
|
||||
}
|
||||
}
|
||||
|
||||
for (optionValue in optionValuesByPlugin[processor.pluginId].orEmpty()) {
|
||||
val option = declaredOptions[optionValue!!.optionName]
|
||||
?: throw CliOptionProcessingException("Unsupported plugin option: $optionValue")
|
||||
optionsToValues.putValue(option, optionValue)
|
||||
fun processCompilerPluginsOptions(
|
||||
configuration: CompilerConfiguration,
|
||||
pluginOptions: Iterable<String>?,
|
||||
commandLineProcessors: List<CommandLineProcessor>
|
||||
) {
|
||||
val optionValuesByPlugin = pluginOptions?.map(::parsePluginOption)?.groupBy {
|
||||
if (it == null) throw CliOptionProcessingException("Wrong plugin option format: $it, should be ${CommonCompilerArguments.PLUGIN_OPTION_FORMAT}")
|
||||
it.pluginId
|
||||
} ?: mapOf()
|
||||
|
||||
for (processor in commandLineProcessors) {
|
||||
val declaredOptions = processor.pluginOptions.associateBy { it.optionName }
|
||||
val optionsToValues = MultiMap<AbstractCliOption, CliOptionValue>()
|
||||
|
||||
for (optionValue in optionValuesByPlugin[processor.pluginId].orEmpty()) {
|
||||
val option = declaredOptions[optionValue!!.optionName]
|
||||
?: throw CliOptionProcessingException("Unsupported plugin option: $optionValue")
|
||||
optionsToValues.putValue(option, optionValue)
|
||||
}
|
||||
|
||||
for (option in processor.pluginOptions) {
|
||||
val values = optionsToValues[option]
|
||||
if (option.required && values.isEmpty()) {
|
||||
throw PluginCliOptionProcessingException(
|
||||
processor.pluginId,
|
||||
processor.pluginOptions,
|
||||
"Required plugin option not present: ${processor.pluginId}:${option.optionName}"
|
||||
)
|
||||
}
|
||||
if (!option.allowMultipleOccurrences && values.size > 1) {
|
||||
throw PluginCliOptionProcessingException(
|
||||
processor.pluginId,
|
||||
processor.pluginOptions,
|
||||
"Multiple values are not allowed for plugin option ${processor.pluginId}:${option.optionName}"
|
||||
)
|
||||
}
|
||||
|
||||
for (option in processor.pluginOptions) {
|
||||
val values = optionsToValues[option]
|
||||
if (option.required && values.isEmpty()) {
|
||||
throw PluginCliOptionProcessingException(
|
||||
processor.pluginId,
|
||||
processor.pluginOptions,
|
||||
"Required plugin option not present: ${processor.pluginId}:${option.optionName}"
|
||||
)
|
||||
}
|
||||
if (!option.allowMultipleOccurrences && values.size > 1) {
|
||||
throw PluginCliOptionProcessingException(
|
||||
processor.pluginId,
|
||||
processor.pluginOptions,
|
||||
"Multiple values are not allowed for plugin option ${processor.pluginId}:${option.optionName}"
|
||||
)
|
||||
}
|
||||
|
||||
for (value in values) {
|
||||
processor.processOption(option, value.value, configuration)
|
||||
}
|
||||
for (value in values) {
|
||||
processor.processOption(option, value.value, configuration)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -16,7 +16,7 @@
|
||||
|
||||
package org.jetbrains.kotlin.daemon.client
|
||||
|
||||
import org.jetbrains.kotlin.cli.common.messages.CompilerMessageLocation
|
||||
import org.jetbrains.kotlin.cli.common.messages.CompilerMessageSourceLocation
|
||||
import org.jetbrains.kotlin.cli.common.messages.CompilerMessageSeverity
|
||||
import org.jetbrains.kotlin.cli.common.messages.MessageCollector
|
||||
import org.jetbrains.kotlin.cli.common.messages.OutputMessageUtil
|
||||
@@ -66,7 +66,7 @@ fun MessageCollector.reportFromDaemon(outputsCollector: ((File, List<File>) -> U
|
||||
else -> throw IllegalStateException("Unexpected compiler message report severity $severity")
|
||||
}
|
||||
if (message != null) {
|
||||
report(compilerSeverity, message, attachment as? CompilerMessageLocation)
|
||||
report(compilerSeverity, message, attachment as? CompilerMessageSourceLocation)
|
||||
}
|
||||
else {
|
||||
reportUnexpected(category, severity, message, attachment)
|
||||
|
||||
@@ -44,7 +44,7 @@ digraph localClassesWithImplicit_kt {
|
||||
}
|
||||
20 [label="Exit local class test"];
|
||||
21 [label="Exit anonymous object"];
|
||||
22 [label="Variable declaration: lval x: R|anonymous|"];
|
||||
22 [label="Variable declaration: lval x: R|<anonymous>|"];
|
||||
6 [label="Exit function test" style="filled" fillcolor=red];
|
||||
}
|
||||
5 -> {7};
|
||||
@@ -284,7 +284,7 @@ digraph localClassesWithImplicit_kt {
|
||||
99 [label="Enter block"];
|
||||
100 [label="Access variable R|<local>/b|"];
|
||||
101 [label="Access variable R|kotlin/String.length|"];
|
||||
102 [label="Function call: this@R|/anonymous|.R|/anonymous.bar|()"];
|
||||
102 [label="Function call: this@R|/<anonymous>|.R|/<anonymous>.bar|()"];
|
||||
103 [label="Exit block"];
|
||||
}
|
||||
104 [label="Exit when branch result"];
|
||||
@@ -299,7 +299,7 @@ digraph localClassesWithImplicit_kt {
|
||||
^ when () {
|
||||
(R|<local>/b| is R|kotlin/String|) -> {
|
||||
R|<local>/b|.R|kotlin/String.length|
|
||||
this@R|/anonymous|.R|/anonymous.bar|()
|
||||
this@R|/<anonymous>|.R|/<anonymous>.bar|()
|
||||
}
|
||||
else -> {
|
||||
Int(1)
|
||||
@@ -356,7 +356,7 @@ digraph localClassesWithImplicit_kt {
|
||||
122 [label="Access variable R|kotlin/String.length|"];
|
||||
123 [label="Access variable R|<local>/b|"];
|
||||
124 [label="Access variable <Unresolved name: length>#"];
|
||||
125 [label="Function call: this@R|/anonymous|.R|/anonymous.baz|()"];
|
||||
125 [label="Function call: this@R|/<anonymous>|.R|/<anonymous>.baz|()"];
|
||||
120 [label="Exit function anonymousFunction" style="filled" fillcolor=red];
|
||||
}
|
||||
115 [label="Postponed exit from lambda"];
|
||||
@@ -364,7 +364,7 @@ digraph localClassesWithImplicit_kt {
|
||||
117 [label="Jump: ^bar R|/myRun|<R|kotlin/Int|>(<L> = myRun@fun <anonymous>(): R|kotlin/Int| <kind=UNKNOWN> {
|
||||
R|<local>/a|.R|kotlin/String.length|
|
||||
R|<local>/b|.<Unresolved name: length>#
|
||||
^ this@R|/anonymous|.R|/anonymous.baz|()
|
||||
^ this@R|/<anonymous>|.R|/<anonymous>.baz|()
|
||||
}
|
||||
)"];
|
||||
118 [label="Stub" style="filled" fillcolor=gray];
|
||||
|
||||
@@ -46,8 +46,8 @@ FILE: localClassesWithImplicit.kt
|
||||
|
||||
}
|
||||
|
||||
lval x: R|anonymous| = object : R|kotlin/Any| {
|
||||
private[local] constructor(): R|anonymous| {
|
||||
lval x: R|<anonymous>| = object : R|kotlin/Any| {
|
||||
private[local] constructor(): R|<anonymous>| {
|
||||
super<R|kotlin/Any|>()
|
||||
}
|
||||
|
||||
@@ -57,7 +57,7 @@ FILE: localClassesWithImplicit.kt
|
||||
^ when () {
|
||||
(R|<local>/b| is R|kotlin/String|) -> {
|
||||
R|<local>/b|.R|kotlin/String.length|
|
||||
this@R|/anonymous|.R|/anonymous.bar|()
|
||||
this@R|/<anonymous>|.R|/<anonymous>.bar|()
|
||||
}
|
||||
else -> {
|
||||
Int(1)
|
||||
@@ -72,7 +72,7 @@ FILE: localClassesWithImplicit.kt
|
||||
^bar R|/myRun|<R|kotlin/Int|>(<L> = myRun@fun <anonymous>(): R|kotlin/Int| <kind=UNKNOWN> {
|
||||
R|<local>/a|.R|kotlin/String.length|
|
||||
R|<local>/b|.<Unresolved name: length>#
|
||||
^ this@R|/anonymous|.R|/anonymous.baz|()
|
||||
^ this@R|/<anonymous>|.R|/<anonymous>.baz|()
|
||||
}
|
||||
)
|
||||
}
|
||||
|
||||
@@ -22,7 +22,7 @@ FILE: enum.kt
|
||||
public get(): R|Some|
|
||||
|
||||
public final static enum entry FIRST: R|SomeEnum| = object : R|SomeEnum| {
|
||||
private[local] constructor(): R|anonymous| {
|
||||
private[local] constructor(): R|<anonymous>| {
|
||||
super<R|SomeEnum|>(Q|O1|)
|
||||
}
|
||||
|
||||
@@ -33,7 +33,7 @@ FILE: enum.kt
|
||||
}
|
||||
|
||||
public final static enum entry SECOND: R|SomeEnum| = object : R|SomeEnum| {
|
||||
private[local] constructor(): R|anonymous| {
|
||||
private[local] constructor(): R|<anonymous>| {
|
||||
super<R|SomeEnum|>(Q|O2|)
|
||||
}
|
||||
|
||||
@@ -71,7 +71,7 @@ FILE: enum.kt
|
||||
}
|
||||
|
||||
public final static enum entry E1: R|EnumClass| = object : R|EnumClass| {
|
||||
private[local] constructor(): R|anonymous| {
|
||||
private[local] constructor(): R|<anonymous>| {
|
||||
super<R|EnumClass|>()
|
||||
}
|
||||
|
||||
@@ -85,14 +85,14 @@ FILE: enum.kt
|
||||
}
|
||||
|
||||
public final static enum entry E2: R|EnumClass| = object : R|EnumClass| {
|
||||
private[local] constructor(): R|anonymous| {
|
||||
private[local] constructor(): R|<anonymous>| {
|
||||
super<R|EnumClass|>()
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public final static enum entry E3: R|EnumClass| = object : R|EnumClass| {
|
||||
private[local] constructor(): R|anonymous| {
|
||||
private[local] constructor(): R|<anonymous>| {
|
||||
super<R|EnumClass|>()
|
||||
}
|
||||
|
||||
|
||||
@@ -30,17 +30,17 @@ FILE: CallBasedInExpressionGenerator.kt
|
||||
|
||||
private final fun gen(argument: R|ERROR CLASS: Symbol not found, for `StackValue`|): R|ERROR CLASS: Symbol not found, for `BranchedValue`| {
|
||||
^gen object : R|ERROR CLASS: Symbol not found, for `BranchedValue`| {
|
||||
private[local] constructor(): R|anonymous| {
|
||||
private[local] constructor(): R|<anonymous>| {
|
||||
super<R|ERROR CLASS: Symbol not found, for `BranchedValue`|>(R|<local>/argument|, Null(null), R|<local>/argument|.<Unresolved name: type>#, <Unresolved name: Opcodes>#.<Unresolved name: IFEQ>#)
|
||||
}
|
||||
|
||||
public[local] final override fun putSelector(type: R|ERROR CLASS: Symbol not found, for `Type`|, kotlinType: R|ERROR CLASS: Symbol not found, for `KotlinType?`|, v: R|ERROR CLASS: Symbol not found, for `InstructionAdapter`|): R|kotlin/Unit| {
|
||||
this@R|/anonymous|.R|/anonymous.invokeFunction|(R|<local>/v|)
|
||||
this@R|/<anonymous>|.R|/<anonymous>.invokeFunction|(R|<local>/v|)
|
||||
<Unresolved name: coerceTo>#(R|<local>/type|, R|<local>/kotlinType|, R|<local>/v|)
|
||||
}
|
||||
|
||||
public[local] final override fun condJump(jumpLabel: R|ERROR CLASS: Symbol not found, for `Label`|, v: R|ERROR CLASS: Symbol not found, for `InstructionAdapter`|, jumpIfFalse: R|kotlin/Boolean|): R|kotlin/Unit| {
|
||||
this@R|/anonymous|.R|/anonymous.invokeFunction|(R|<local>/v|)
|
||||
this@R|/<anonymous>|.R|/<anonymous>.invokeFunction|(R|<local>/v|)
|
||||
R|<local>/v|.<Unresolved name: visitJumpInsn>#(when () {
|
||||
R|<local>/jumpIfFalse| -> {
|
||||
<Unresolved name: Opcodes>#.<Unresolved name: IFEQ>#
|
||||
|
||||
@@ -7,7 +7,7 @@ FILE: enumEntryUse.kt
|
||||
public final static enum entry FIRST: R|TestEnum|
|
||||
public final static enum entry SECOND: R|TestEnum|
|
||||
public final static enum entry THIRD: R|TestEnum| = object : R|TestEnum| {
|
||||
private[local] constructor(): R|anonymous| {
|
||||
private[local] constructor(): R|<anonymous>| {
|
||||
super<R|TestEnum|>()
|
||||
}
|
||||
|
||||
|
||||
@@ -1,12 +1,12 @@
|
||||
FILE: localImplicitBodies.kt
|
||||
public final fun foo(): R|kotlin/Unit| {
|
||||
lval x: R|anonymous| = object : R|kotlin/Any| {
|
||||
private[local] constructor(): R|anonymous| {
|
||||
lval x: R|<anonymous>| = object : R|kotlin/Any| {
|
||||
private[local] constructor(): R|<anonymous>| {
|
||||
super<R|kotlin/Any|>()
|
||||
}
|
||||
|
||||
public[local] final fun sss(): R|kotlin/Int| {
|
||||
^sss this@R|/anonymous|.R|/anonymous.abc|()
|
||||
^sss this@R|/<anonymous>|.R|/<anonymous>.abc|()
|
||||
}
|
||||
|
||||
public[local] final fun abc(): R|kotlin/Int| {
|
||||
@@ -15,5 +15,5 @@ FILE: localImplicitBodies.kt
|
||||
|
||||
}
|
||||
|
||||
lval g: R|kotlin/Int| = R|<local>/x|.R|/anonymous.sss|()
|
||||
lval g: R|kotlin/Int| = R|<local>/x|.R|/<anonymous>.sss|()
|
||||
}
|
||||
|
||||
@@ -3,12 +3,12 @@ FILE: localInnerClass.kt
|
||||
}
|
||||
public final fun bar(): R|kotlin/Unit| {
|
||||
object : R|Foo| {
|
||||
private[local] constructor(): R|anonymous| {
|
||||
private[local] constructor(): R|<anonymous>| {
|
||||
super<R|kotlin/Any|>()
|
||||
}
|
||||
|
||||
public[local] final fun foo(): R|Foo| {
|
||||
^foo this@R|/anonymous|.R|/<anonymous>.Derived.Derived|(Int(42))
|
||||
^foo this@R|/<anonymous>|.R|/<anonymous>.Derived.Derived|(Int(42))
|
||||
}
|
||||
|
||||
local final inner class Derived : R|Foo| {
|
||||
|
||||
@@ -20,8 +20,8 @@ FILE: localObjects.kt
|
||||
}
|
||||
public final fun test(): R|kotlin/Unit| {
|
||||
Q|A|.R|/A.x|
|
||||
lval b: R|anonymous| = object : R|Foo| {
|
||||
private[local] constructor(): R|anonymous| {
|
||||
lval b: R|<anonymous>| = object : R|Foo| {
|
||||
private[local] constructor(): R|<anonymous>| {
|
||||
super<R|Foo|>()
|
||||
}
|
||||
|
||||
|
||||
@@ -22,8 +22,8 @@ FILE: localScopes.kt
|
||||
lval base: R|BaseLocal| = R|/BaseLocal.BaseLocal|()
|
||||
R|<local>/base|.R|/BaseLocal.baz|()
|
||||
R|<local>/base|.R|/Bar.foo|()
|
||||
lval anonymous: R|anonymous| = object : R|Bar| {
|
||||
private[local] constructor(): R|anonymous| {
|
||||
lval anonymous: R|<anonymous>| = object : R|Bar| {
|
||||
private[local] constructor(): R|<anonymous>| {
|
||||
super<R|Bar|>()
|
||||
}
|
||||
|
||||
@@ -32,7 +32,7 @@ FILE: localScopes.kt
|
||||
|
||||
}
|
||||
|
||||
R|<local>/anonymous|.R|/anonymous.baz|()
|
||||
R|<local>/anonymous|.R|/<anonymous>.baz|()
|
||||
R|<local>/anonymous|.R|/Bar.foo|()
|
||||
local final class DerivedLocal : R|BaseLocal| {
|
||||
public[local] constructor(): R|DerivedLocal| {
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
FILE: foo.kt
|
||||
public final fun foo(): R|kotlin/Boolean| {
|
||||
object : R|Node<kotlin/Boolean>| {
|
||||
private[local] constructor(): R|anonymous| {
|
||||
private[local] constructor(): R|<anonymous>| {
|
||||
super<R|kotlin/Any|>()
|
||||
}
|
||||
|
||||
@@ -10,11 +10,11 @@ FILE: foo.kt
|
||||
private set(value: R|kotlin/Boolean|): R|kotlin/Unit|
|
||||
|
||||
public[local] final fun bar(): R|kotlin/Boolean| {
|
||||
^bar this@R|/anonymous|.R|/anonymous.result|.R|kotlin/Boolean.not|()
|
||||
^bar this@R|/<anonymous>|.R|/<anonymous>.result|.R|kotlin/Boolean.not|()
|
||||
}
|
||||
|
||||
public[local] final override fun result(): R|kotlin/Boolean| {
|
||||
^result this@R|/anonymous|.R|/anonymous.result|
|
||||
^result this@R|/<anonymous>|.R|/<anonymous>.result|
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -31,8 +31,8 @@ FILE: O.kt
|
||||
|
||||
public[private] final fun test(): R|kotlin/Unit| {
|
||||
lval x: R|kotlin/Int| = this@R|/O.Derived|.R|/O.Derived.bar|
|
||||
lval o: R|anonymous| = object : R|Wrapper| {
|
||||
private[local] constructor(): R|anonymous| {
|
||||
lval o: R|<anonymous>| = object : R|Wrapper| {
|
||||
private[local] constructor(): R|<anonymous>| {
|
||||
super<R|Wrapper|>(this@R|/O.Derived.Some|.R|/O.Derived.Some.z|)
|
||||
}
|
||||
|
||||
@@ -40,8 +40,8 @@ FILE: O.kt
|
||||
lval y: R|ft<kotlin/String, kotlin/String?>!| = this@R|/O.Derived|.R|/Base.foo|()
|
||||
}
|
||||
|
||||
public[local] final val oo: R|anonymous| = object : R|kotlin/Any| {
|
||||
private[local] constructor(): R|anonymous| {
|
||||
public[local] final val oo: R|<anonymous>| = object : R|kotlin/Any| {
|
||||
private[local] constructor(): R|<anonymous>| {
|
||||
super<R|kotlin/Any|>()
|
||||
}
|
||||
|
||||
@@ -50,7 +50,7 @@ FILE: O.kt
|
||||
|
||||
}
|
||||
|
||||
public get(): R|anonymous|
|
||||
public get(): R|<anonymous>|
|
||||
|
||||
}
|
||||
|
||||
@@ -60,8 +60,8 @@ FILE: O.kt
|
||||
|
||||
public[private] final fun test(): R|kotlin/Unit| {
|
||||
lval x: R|kotlin/Int| = this@R|/O.Derived|.R|/O.Derived.bar|
|
||||
lval o: R|anonymous| = object : R|kotlin/Any| {
|
||||
private[local] constructor(): R|anonymous| {
|
||||
lval o: R|<anonymous>| = object : R|kotlin/Any| {
|
||||
private[local] constructor(): R|<anonymous>| {
|
||||
super<R|kotlin/Any|>()
|
||||
}
|
||||
|
||||
@@ -86,7 +86,7 @@ FILE: O.kt
|
||||
|
||||
private final fun gen(): R|kotlin/Any| {
|
||||
^gen object : R|Wrapper| {
|
||||
private[local] constructor(): R|anonymous| {
|
||||
private[local] constructor(): R|<anonymous>| {
|
||||
super<R|Wrapper|>(Boolean(true))
|
||||
}
|
||||
|
||||
|
||||
@@ -4,8 +4,8 @@ FILE: privateObjectLiteral.kt
|
||||
super<R|kotlin/Any|>()
|
||||
}
|
||||
|
||||
private final val x: R|anonymous| = object : R|kotlin/Any| {
|
||||
private[local] constructor(): R|anonymous| {
|
||||
private final val x: R|<anonymous>| = object : R|kotlin/Any| {
|
||||
private[local] constructor(): R|<anonymous>| {
|
||||
super<R|kotlin/Any|>()
|
||||
}
|
||||
|
||||
@@ -15,13 +15,13 @@ FILE: privateObjectLiteral.kt
|
||||
|
||||
}
|
||||
|
||||
private get(): R|anonymous|
|
||||
private get(): R|<anonymous>|
|
||||
|
||||
public final val y: R|kotlin/Int| = this@R|/C|.R|/C.x|.R|/anonymous.foo|()
|
||||
public final val y: R|kotlin/Int| = this@R|/C|.R|/C.x|.R|/<anonymous>.foo|()
|
||||
public get(): R|kotlin/Int|
|
||||
|
||||
internal final val z: R|anonymous| = object : R|kotlin/Any| {
|
||||
private[local] constructor(): R|anonymous| {
|
||||
internal final val z: R|<anonymous>| = object : R|kotlin/Any| {
|
||||
private[local] constructor(): R|<anonymous>| {
|
||||
super<R|kotlin/Any|>()
|
||||
}
|
||||
|
||||
@@ -31,9 +31,9 @@ FILE: privateObjectLiteral.kt
|
||||
|
||||
}
|
||||
|
||||
internal get(): R|anonymous|
|
||||
internal get(): R|<anonymous>|
|
||||
|
||||
public final val w: R|kotlin/Int| = this@R|/C|.R|/C.z|.R|/anonymous.foo|()
|
||||
public final val w: R|kotlin/Int| = this@R|/C|.R|/C.z|.R|/<anonymous>.foo|()
|
||||
public get(): R|kotlin/Int|
|
||||
|
||||
}
|
||||
|
||||
@@ -26,7 +26,7 @@ FILE: enums.kt
|
||||
internal get(): R|kotlin/Double|
|
||||
|
||||
public final static enum entry MERCURY: R|Planet| = object : R|Planet| {
|
||||
private[local] constructor(): R|anonymous| {
|
||||
private[local] constructor(): R|<anonymous>| {
|
||||
super<R|Planet|>(Double(1.0), Double(2.0))
|
||||
}
|
||||
|
||||
@@ -37,7 +37,7 @@ FILE: enums.kt
|
||||
}
|
||||
|
||||
public final static enum entry VENERA: R|Planet| = object : R|Planet| {
|
||||
private[local] constructor(): R|anonymous| {
|
||||
private[local] constructor(): R|<anonymous>| {
|
||||
super<R|Planet|>(Double(3.0), Double(4.0))
|
||||
}
|
||||
|
||||
@@ -48,7 +48,7 @@ FILE: enums.kt
|
||||
}
|
||||
|
||||
public final static enum entry EARTH: R|Planet| = object : R|Planet| {
|
||||
private[local] constructor(): R|anonymous| {
|
||||
private[local] constructor(): R|<anonymous>| {
|
||||
super<R|Planet|>(Double(5.0), Double(6.0))
|
||||
}
|
||||
|
||||
|
||||
@@ -1,35 +1,35 @@
|
||||
FILE: implicitInAnonymous.kt
|
||||
private final val x: R|anonymous| = object : R|kotlin/Any| {
|
||||
private[local] constructor(): R|anonymous| {
|
||||
private final val x: R|<anonymous>| = object : R|kotlin/Any| {
|
||||
private[local] constructor(): R|<anonymous>| {
|
||||
super<R|kotlin/Any|>()
|
||||
}
|
||||
|
||||
public[local] final fun foo(x: R|kotlin/Int|): R|kotlin/Boolean| {
|
||||
^foo this@R|/anonymous|.R|/anonymous.bar|(R|<local>/x|)
|
||||
^foo this@R|/<anonymous>|.R|/<anonymous>.bar|(R|<local>/x|)
|
||||
}
|
||||
|
||||
public[local] final fun bar(y: R|kotlin/Int|): R|kotlin/Boolean| {
|
||||
^bar CMP(>, this@R|/anonymous|.R|kotlin/Any.hashCode|().R|kotlin/Int.plus|(R|<local>/y|).R|kotlin/Int.compareTo|(Int(0)))
|
||||
^bar CMP(>, this@R|/<anonymous>|.R|kotlin/Any.hashCode|().R|kotlin/Int.plus|(R|<local>/y|).R|kotlin/Int.compareTo|(Int(0)))
|
||||
}
|
||||
|
||||
public[local] final val w: R|kotlin/Boolean|
|
||||
public get(): R|kotlin/Boolean| {
|
||||
^ this@R|/anonymous|.R|/anonymous.z|
|
||||
^ this@R|/<anonymous>|.R|/<anonymous>.z|
|
||||
}
|
||||
|
||||
public[local] final val z: R|kotlin/Boolean|
|
||||
public get(): R|kotlin/Boolean| {
|
||||
^ ==(this@R|/anonymous|.R|kotlin/Any.hashCode|(), Int(0))
|
||||
^ ==(this@R|/<anonymous>|.R|kotlin/Any.hashCode|(), Int(0))
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private get(): R|anonymous|
|
||||
private get(): R|<anonymous>|
|
||||
public final fun useBoolean(b: R|kotlin/Boolean|): R|kotlin/Unit| {
|
||||
}
|
||||
public final fun main(): R|kotlin/Unit| {
|
||||
R|/useBoolean|(R|/x|.R|/anonymous.foo|(Int(1)))
|
||||
R|/useBoolean|(R|/x|.R|/anonymous.bar|(Int(2)))
|
||||
R|/useBoolean|(R|/x|.R|/anonymous.w|)
|
||||
R|/useBoolean|(R|/x|.R|/anonymous.z|)
|
||||
R|/useBoolean|(R|/x|.R|/<anonymous>.foo|(Int(1)))
|
||||
R|/useBoolean|(R|/x|.R|/<anonymous>.bar|(Int(2)))
|
||||
R|/useBoolean|(R|/x|.R|/<anonymous>.w|)
|
||||
R|/useBoolean|(R|/x|.R|/<anonymous>.z|)
|
||||
}
|
||||
|
||||
@@ -12,7 +12,7 @@ FILE: typesFromSuperClasses.kt
|
||||
}
|
||||
public final fun main(): R|kotlin/Unit| {
|
||||
object : R|Outer| {
|
||||
private[local] constructor(): R|anonymous| {
|
||||
private[local] constructor(): R|<anonymous>| {
|
||||
super<R|Outer|>()
|
||||
}
|
||||
|
||||
|
||||
@@ -8,8 +8,8 @@ FILE: localObject.kt
|
||||
}
|
||||
public final fun tesLambda(x: R|kotlin/Int|): R|kotlin/Int| {
|
||||
^tesLambda R|/run|<R|kotlin/Int|>(<L> = run@fun <anonymous>(): R|kotlin/Int| {
|
||||
lval obj: R|anonymous| = object : R|Foo| {
|
||||
private[local] constructor(): R|anonymous| {
|
||||
lval obj: R|<anonymous>| = object : R|Foo| {
|
||||
private[local] constructor(): R|<anonymous>| {
|
||||
super<R|kotlin/Any|>()
|
||||
}
|
||||
|
||||
@@ -34,8 +34,8 @@ FILE: localObject.kt
|
||||
public final var x: R|kotlin/Int| = Int(1)
|
||||
public get(): R|kotlin/Int|
|
||||
public set(value: R|kotlin/Int|): R|kotlin/Unit| {
|
||||
lval obj: R|anonymous| = object : R|Foo| {
|
||||
private[local] constructor(): R|anonymous| {
|
||||
lval obj: R|<anonymous>| = object : R|Foo| {
|
||||
private[local] constructor(): R|<anonymous>| {
|
||||
super<R|kotlin/Any|>()
|
||||
}
|
||||
|
||||
@@ -50,8 +50,8 @@ FILE: localObject.kt
|
||||
|
||||
public final val y: R|kotlin/Int|
|
||||
public get(): R|kotlin/Int| {
|
||||
lval obj: R|anonymous| = object : R|Foo| {
|
||||
private[local] constructor(): R|anonymous| {
|
||||
lval obj: R|<anonymous>| = object : R|Foo| {
|
||||
private[local] constructor(): R|<anonymous>| {
|
||||
super<R|kotlin/Any|>()
|
||||
}
|
||||
|
||||
@@ -65,8 +65,8 @@ FILE: localObject.kt
|
||||
}
|
||||
|
||||
public final val z: R|kotlin/Int| = this@R|/TestProperty|.R|kotlin/run|<R|TestProperty|, R|kotlin/Int|>(<L> = run@fun R|TestProperty|.<anonymous>(): R|kotlin/Int| <kind=EXACTLY_ONCE> {
|
||||
lval obj: R|anonymous| = object : R|Foo| {
|
||||
private[local] constructor(): R|anonymous| {
|
||||
lval obj: R|<anonymous>| = object : R|Foo| {
|
||||
private[local] constructor(): R|<anonymous>| {
|
||||
super<R|kotlin/Any|>()
|
||||
}
|
||||
|
||||
|
||||
@@ -1,12 +1,12 @@
|
||||
FILE: objectInnerClass.kt
|
||||
public final val case1: R|anonymous| = object : R|A| {
|
||||
private[local] constructor(): R|anonymous| {
|
||||
public final val case1: R|<anonymous>| = object : R|A| {
|
||||
private[local] constructor(): R|<anonymous>| {
|
||||
super<R|kotlin/Any|>()
|
||||
}
|
||||
|
||||
local final inner class Child : R|<anonymous>.Base| {
|
||||
public[local] constructor(property: R|B|): R|<anonymous>.Child| {
|
||||
this@R|/anonymous|.super<R|<anonymous>.Base|>(R|<local>/property|)
|
||||
this@R|/<anonymous>|.super<R|<anonymous>.Base|>(R|<local>/property|)
|
||||
}
|
||||
|
||||
public[local] final fun R|<anonymous>.Base|.zoo(): R|kotlin/Unit| {
|
||||
@@ -17,17 +17,17 @@ FILE: objectInnerClass.kt
|
||||
this@R|/<anonymous>.Child|.R|/<anonymous>.Base.baseFun|()
|
||||
lval x: R|B| = this@R|/<anonymous>.Child|.R|/<anonymous>.Base.property|
|
||||
(this@R|/<anonymous>.Child|, this@R|/<anonymous>.Child|).R|/<anonymous>.Child.zoo|()
|
||||
(this@R|/anonymous|, this@R|/<anonymous>.Child|).R|/anonymous.hoo|()
|
||||
(this@R|/<anonymous>|, this@R|/<anonymous>.Child|).R|/<anonymous>.hoo|()
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public[local] final fun R|<anonymous>.Child|.voo(): R|kotlin/Unit| {
|
||||
lval x: R|B| = this@R|/anonymous.voo|.R|/<anonymous>.Base.property|
|
||||
lval x: R|B| = this@R|/<anonymous>.voo|.R|/<anonymous>.Base.property|
|
||||
}
|
||||
|
||||
public[local] final fun R|<anonymous>.Base|.hoo(): R|kotlin/Unit| {
|
||||
lval x: R|B| = this@R|/anonymous.hoo|.R|/<anonymous>.Base.property|
|
||||
lval x: R|B| = this@R|/<anonymous>.hoo|.R|/<anonymous>.Base.property|
|
||||
}
|
||||
|
||||
local open inner class Base : R|kotlin/Any| {
|
||||
@@ -44,48 +44,48 @@ FILE: objectInnerClass.kt
|
||||
}
|
||||
|
||||
public[local] final fun caseForBase(): R|kotlin/Unit| {
|
||||
lval base: R|<anonymous>.Base| = this@R|/anonymous|.R|/<anonymous>.Base.Base|(R|/B.B|())
|
||||
lval base: R|<anonymous>.Base| = this@R|/<anonymous>|.R|/<anonymous>.Base.Base|(R|/B.B|())
|
||||
R|<local>/base|.R|/<anonymous>.Base.baseFun|()
|
||||
R|<local>/base|.R|/<anonymous>.Base.property|
|
||||
(this@R|/anonymous|, R|<local>/base|).R|/anonymous.hoo|()
|
||||
(this@R|/<anonymous>|, R|<local>/base|).R|/<anonymous>.hoo|()
|
||||
}
|
||||
|
||||
public[local] final fun caseForChild(): R|kotlin/Unit| {
|
||||
lval child: R|<anonymous>.Child| = this@R|/anonymous|.R|/<anonymous>.Child.Child|(R|/B.B|())
|
||||
lval child: R|<anonymous>.Child| = this@R|/<anonymous>|.R|/<anonymous>.Child.Child|(R|/B.B|())
|
||||
R|<local>/child|.R|/<anonymous>.Base.baseFun|()
|
||||
R|<local>/child|.R|/<anonymous>.Base.property|
|
||||
R|<local>/child|.R|/<anonymous>.Child.foo|()
|
||||
(this@R|/anonymous|, R|<local>/child|).R|/anonymous.hoo|()
|
||||
(this@R|/anonymous|, R|<local>/child|).R|/anonymous.voo|()
|
||||
(this@R|/<anonymous>|, R|<local>/child|).R|/<anonymous>.hoo|()
|
||||
(this@R|/<anonymous>|, R|<local>/child|).R|/<anonymous>.voo|()
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public get(): R|anonymous|
|
||||
public get(): R|<anonymous>|
|
||||
public final class Case2 : R|kotlin/Any| {
|
||||
public constructor(): R|Case2| {
|
||||
super<R|kotlin/Any|>()
|
||||
}
|
||||
|
||||
public final val x: R|anonymous| = object : R|Case2.Base| {
|
||||
private[local] constructor(): R|anonymous| {
|
||||
public final val x: R|<anonymous>| = object : R|Case2.Base| {
|
||||
private[local] constructor(): R|<anonymous>| {
|
||||
this@R|/Case2|.super<R|Case2.Base|>(R|/B.B|())
|
||||
}
|
||||
|
||||
public[local] final fun R|Case2.Base|.zoo(): R|kotlin/Unit| {
|
||||
lval x: R|B| = this@R|/anonymous.zoo|.R|/Case2.Base.property|
|
||||
lval x: R|B| = this@R|/<anonymous>.zoo|.R|/Case2.Base.property|
|
||||
}
|
||||
|
||||
public[local] final fun foo(): R|kotlin/Unit| {
|
||||
this@R|/anonymous|.R|/Case2.Base.baseFun|()
|
||||
lval x: R|B| = this@R|/anonymous|.R|/Case2.Base.property|
|
||||
(this@R|/anonymous|, this@R|/anonymous|).R|/anonymous.zoo|()
|
||||
(this@R|/Case2|, this@R|/anonymous|).R|/Case2.hoo|()
|
||||
this@R|/<anonymous>|.R|/Case2.Base.baseFun|()
|
||||
lval x: R|B| = this@R|/<anonymous>|.R|/Case2.Base.property|
|
||||
(this@R|/<anonymous>|, this@R|/<anonymous>|).R|/<anonymous>.zoo|()
|
||||
(this@R|/Case2|, this@R|/<anonymous>|).R|/Case2.hoo|()
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public get(): R|anonymous|
|
||||
public get(): R|<anonymous>|
|
||||
|
||||
public final fun R|Case2.Base|.hoo(): R|kotlin/Unit| {
|
||||
lval x: R|B| = this@R|/Case2.hoo|.R|/Case2.Base.property|
|
||||
@@ -112,7 +112,7 @@ FILE: objectInnerClass.kt
|
||||
}
|
||||
|
||||
public final fun caseForChild(): R|kotlin/Unit| {
|
||||
lval child: R|anonymous| = this@R|/Case2|.R|/Case2.x|
|
||||
lval child: R|<anonymous>| = this@R|/Case2|.R|/Case2.x|
|
||||
R|<local>/child|.R|/Case2.Base.baseFun|()
|
||||
R|<local>/child|.R|/Case2.Base.property|
|
||||
(this@R|/Case2|, R|<local>/child|).R|/Case2.hoo|()
|
||||
@@ -124,14 +124,14 @@ FILE: objectInnerClass.kt
|
||||
super<R|kotlin/Any|>()
|
||||
}
|
||||
|
||||
public final val x: R|anonymous| = object : R|A| {
|
||||
private[local] constructor(): R|anonymous| {
|
||||
public final val x: R|<anonymous>| = object : R|A| {
|
||||
private[local] constructor(): R|<anonymous>| {
|
||||
super<R|kotlin/Any|>()
|
||||
}
|
||||
|
||||
local final inner class Child : R|Case3.<anonymous>.Base| {
|
||||
public[local] constructor(property: R|B|): R|Case3.<anonymous>.Child| {
|
||||
this@R|/anonymous|.super<R|Case3.<anonymous>.Base|>(R|<local>/property|)
|
||||
this@R|/<anonymous>|.super<R|Case3.<anonymous>.Base|>(R|<local>/property|)
|
||||
}
|
||||
|
||||
public[local] final fun R|Case3.<anonymous>.Base|.zoo(): R|kotlin/Unit| {
|
||||
@@ -142,17 +142,17 @@ FILE: objectInnerClass.kt
|
||||
this@R|/Case3.<anonymous>.Child|.R|/Case3.<anonymous>.Base.baseFun|()
|
||||
lval x: R|B| = this@R|/Case3.<anonymous>.Child|.R|/Case3.<anonymous>.Base.property|
|
||||
(this@R|/Case3.<anonymous>.Child|, this@R|/Case3.<anonymous>.Child|).R|/Case3.<anonymous>.Child.zoo|()
|
||||
(this@R|/anonymous|, this@R|/Case3.<anonymous>.Child|).R|/anonymous.hoo|()
|
||||
(this@R|/<anonymous>|, this@R|/Case3.<anonymous>.Child|).R|/<anonymous>.hoo|()
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public[local] final fun R|Case3.<anonymous>.Child|.voo(): R|kotlin/Unit| {
|
||||
lval x: R|B| = this@R|/anonymous.voo|.R|/Case3.<anonymous>.Base.property|
|
||||
lval x: R|B| = this@R|/<anonymous>.voo|.R|/Case3.<anonymous>.Base.property|
|
||||
}
|
||||
|
||||
public[local] final fun R|Case3.<anonymous>.Base|.hoo(): R|kotlin/Unit| {
|
||||
lval x: R|B| = this@R|/anonymous.hoo|.R|/Case3.<anonymous>.Base.property|
|
||||
lval x: R|B| = this@R|/<anonymous>.hoo|.R|/Case3.<anonymous>.Base.property|
|
||||
}
|
||||
|
||||
local open inner class Base : R|kotlin/Any| {
|
||||
@@ -169,24 +169,24 @@ FILE: objectInnerClass.kt
|
||||
}
|
||||
|
||||
public[local] final fun caseForBase(): R|kotlin/Unit| {
|
||||
lval base: R|Case3.<anonymous>.Base| = this@R|/anonymous|.R|/Case3.<anonymous>.Base.Base|(R|/B.B|())
|
||||
lval base: R|Case3.<anonymous>.Base| = this@R|/<anonymous>|.R|/Case3.<anonymous>.Base.Base|(R|/B.B|())
|
||||
R|<local>/base|.R|/Case3.<anonymous>.Base.baseFun|()
|
||||
R|<local>/base|.R|/Case3.<anonymous>.Base.property|
|
||||
(this@R|/anonymous|, R|<local>/base|).R|/anonymous.hoo|()
|
||||
(this@R|/<anonymous>|, R|<local>/base|).R|/<anonymous>.hoo|()
|
||||
}
|
||||
|
||||
public[local] final fun caseForChild(): R|kotlin/Unit| {
|
||||
lval child: R|Case3.<anonymous>.Child| = this@R|/anonymous|.R|/Case3.<anonymous>.Child.Child|(R|/B.B|())
|
||||
lval child: R|Case3.<anonymous>.Child| = this@R|/<anonymous>|.R|/Case3.<anonymous>.Child.Child|(R|/B.B|())
|
||||
R|<local>/child|.R|/Case3.<anonymous>.Base.baseFun|()
|
||||
R|<local>/child|.R|/Case3.<anonymous>.Base.property|
|
||||
R|<local>/child|.R|/Case3.<anonymous>.Child.foo|()
|
||||
(this@R|/anonymous|, R|<local>/child|).R|/anonymous.hoo|()
|
||||
(this@R|/anonymous|, R|<local>/child|).R|/anonymous.voo|()
|
||||
(this@R|/<anonymous>|, R|<local>/child|).R|/<anonymous>.hoo|()
|
||||
(this@R|/<anonymous>|, R|<local>/child|).R|/<anonymous>.voo|()
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public get(): R|anonymous|
|
||||
public get(): R|<anonymous>|
|
||||
|
||||
}
|
||||
public abstract interface A : R|kotlin/Any| {
|
||||
|
||||
@@ -13,8 +13,8 @@ FILE: objectDerivedFromInnerClass.kt
|
||||
|
||||
}
|
||||
public final fun test(): R|kotlin/Unit| {
|
||||
lval x: R|anonymous| = object : R|Outer.Inner| {
|
||||
private[local] constructor(): R|anonymous| {
|
||||
lval x: R|<anonymous>| = object : R|Outer.Inner| {
|
||||
private[local] constructor(): R|<anonymous>| {
|
||||
super<R|Outer.Inner|>()
|
||||
}
|
||||
|
||||
|
||||
@@ -51,7 +51,7 @@ FILE: singletonConstructors.kt
|
||||
}
|
||||
|
||||
public final static enum entry X: R|E| = object : R|E| {
|
||||
private[local] constructor(): R|anonymous| {
|
||||
private[local] constructor(): R|<anonymous>| {
|
||||
super<R|E|>()
|
||||
}
|
||||
|
||||
|
||||
@@ -4,8 +4,8 @@ FILE: anonymousInDelegate.kt
|
||||
|
||||
}
|
||||
public final val x: R|kotlin/Int|by R|kotlin/lazy|<R|kotlin/Int|>(<L> = lazy@fun <anonymous>(): R|kotlin/Int| {
|
||||
lval foo: R|anonymous| = object : R|Foo| {
|
||||
private[local] constructor(): R|anonymous| {
|
||||
lval foo: R|<anonymous>| = object : R|Foo| {
|
||||
private[local] constructor(): R|<anonymous>| {
|
||||
super<R|kotlin/Any|>()
|
||||
}
|
||||
|
||||
@@ -15,7 +15,7 @@ FILE: anonymousInDelegate.kt
|
||||
|
||||
}
|
||||
|
||||
^ R|<local>/foo|.R|/anonymous.bar|()
|
||||
^ R|<local>/foo|.R|/<anonymous>.bar|()
|
||||
}
|
||||
)
|
||||
public get(): R|kotlin/Int| {
|
||||
|
||||
@@ -24,7 +24,7 @@ FILE: delegateWithAnonymousObject.kt
|
||||
|
||||
public final var issueListView: R|IssueListView|by this@R|/IssuesListUserProfile|.R|/delegate|<R|IssuesListUserProfile|, R|IssuesListUserProfile|, R|IssueListView|>(<L> = delegate@fun <anonymous>(): R|kotlin/properties/ReadWriteProperty<IssuesListUserProfile, IssueListView>| {
|
||||
^ object : R|kotlin/properties/ReadWriteProperty<IssuesListUserProfile, IssueListView>| {
|
||||
private[local] constructor(): R|anonymous| {
|
||||
private[local] constructor(): R|<anonymous>| {
|
||||
super<R|kotlin/Any|>()
|
||||
}
|
||||
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
FILE: problems.kt
|
||||
public final val sb: R|java/lang/StringBuilder| = R|java/lang/StringBuilder.StringBuilder|()
|
||||
public get(): R|java/lang/StringBuilder|
|
||||
public final val o: R|anonymous| = object : R|kotlin/Any| {
|
||||
private[local] constructor(): R|anonymous| {
|
||||
public final val o: R|<anonymous>| = object : R|kotlin/Any| {
|
||||
private[local] constructor(): R|<anonymous>| {
|
||||
super<R|kotlin/Any|>()
|
||||
}
|
||||
|
||||
@@ -10,12 +10,12 @@ FILE: problems.kt
|
||||
public get(): R|kotlin/String|
|
||||
|
||||
public[local] final fun test(): R|kotlin/Unit| {
|
||||
this@R|/anonymous|.R|/anonymous.name|
|
||||
this@R|/<anonymous>|.R|/<anonymous>.name|
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public get(): R|anonymous|
|
||||
public get(): R|<anonymous>|
|
||||
public final fun test(): R|kotlin/Unit| {
|
||||
local final class Local : R|kotlin/Any| {
|
||||
public[local] constructor(): R|Local| {
|
||||
|
||||
@@ -10286,6 +10286,11 @@ public class FirOldFrontendDiagnosticsTestGenerated extends AbstractFirOldFronte
|
||||
runTest("compiler/testData/diagnostics/tests/inference/resolveWithUnknownLambdaParameterType.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("returningLambdaInSuspendContext.kt")
|
||||
public void testReturningLambdaInSuspendContext() throws Exception {
|
||||
runTest("compiler/testData/diagnostics/tests/inference/returningLambdaInSuspendContext.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("starApproximation.kt")
|
||||
public void testStarApproximation() throws Exception {
|
||||
runTest("compiler/testData/diagnostics/tests/inference/starApproximation.kt");
|
||||
|
||||
@@ -11,9 +11,11 @@ import org.jetbrains.kotlin.descriptors.ClassDescriptor
|
||||
import org.jetbrains.kotlin.fir.backend.Fir2IrComponents
|
||||
import org.jetbrains.kotlin.fir.resolve.firSymbolProvider
|
||||
import org.jetbrains.kotlin.fir.symbols.impl.FirClassSymbol
|
||||
import org.jetbrains.kotlin.ir.ObsoleteDescriptorBasedAPI
|
||||
import org.jetbrains.org.objectweb.asm.Type
|
||||
|
||||
class FirJvmBackendClassResolver(val components: Fir2IrComponents) : JvmBackendClassResolver {
|
||||
@ObsoleteDescriptorBasedAPI
|
||||
override fun resolveToClassDescriptors(type: Type): List<ClassDescriptor> {
|
||||
if (type.sort != Type.OBJECT) return emptyList()
|
||||
|
||||
|
||||
@@ -30,6 +30,7 @@ import org.jetbrains.kotlin.fir.types.ConeKotlinErrorType
|
||||
import org.jetbrains.kotlin.fir.types.ConeKotlinType
|
||||
import org.jetbrains.kotlin.fir.types.FirTypeRef
|
||||
import org.jetbrains.kotlin.fir.types.coneTypeUnsafe
|
||||
import org.jetbrains.kotlin.ir.ObsoleteDescriptorBasedAPI
|
||||
import org.jetbrains.kotlin.ir.declarations.IrClass
|
||||
import org.jetbrains.kotlin.ir.declarations.IrField
|
||||
import org.jetbrains.kotlin.ir.declarations.IrFunction
|
||||
@@ -96,6 +97,7 @@ class FirJvmClassCodegen(
|
||||
}
|
||||
}
|
||||
|
||||
@OptIn(ObsoleteDescriptorBasedAPI::class)
|
||||
override fun generateKotlinMetadataAnnotation() {
|
||||
|
||||
val localDelegatedProperties = (irClass.attributeOwnerId as? IrClass)?.let(context.localDelegatedProperties::get)
|
||||
|
||||
@@ -23,6 +23,7 @@ import org.jetbrains.kotlin.fir.serialization.FirElementSerializer
|
||||
import org.jetbrains.kotlin.fir.serialization.FirSerializerExtension
|
||||
import org.jetbrains.kotlin.fir.serialization.nonSourceAnnotations
|
||||
import org.jetbrains.kotlin.fir.types.*
|
||||
import org.jetbrains.kotlin.ir.ObsoleteDescriptorBasedAPI
|
||||
import org.jetbrains.kotlin.ir.declarations.IrClass
|
||||
import org.jetbrains.kotlin.load.java.JvmAbi
|
||||
import org.jetbrains.kotlin.load.kotlin.NON_EXISTENT_CLASS_NAME
|
||||
@@ -75,6 +76,7 @@ class FirJvmSerializerExtension @JvmOverloads constructor(
|
||||
return classBuilderMode != ClassBuilderMode.ABI || nestedClass.effectiveVisibility != FirEffectiveVisibilityImpl.Private
|
||||
}
|
||||
|
||||
@OptIn(ObsoleteDescriptorBasedAPI::class)
|
||||
override fun serializeClass(
|
||||
klass: FirClass<*>,
|
||||
proto: ProtoBuf.Class.Builder,
|
||||
|
||||
@@ -27,6 +27,7 @@ import org.jetbrains.kotlin.fir.scopes.impl.FirClassSubstitutionScope
|
||||
import org.jetbrains.kotlin.fir.symbols.*
|
||||
import org.jetbrains.kotlin.fir.symbols.impl.*
|
||||
import org.jetbrains.kotlin.fir.types.*
|
||||
import org.jetbrains.kotlin.ir.ObsoleteDescriptorBasedAPI
|
||||
import org.jetbrains.kotlin.ir.UNDEFINED_OFFSET
|
||||
import org.jetbrains.kotlin.ir.declarations.*
|
||||
import org.jetbrains.kotlin.ir.declarations.impl.*
|
||||
@@ -45,6 +46,7 @@ import org.jetbrains.kotlin.name.FqName
|
||||
import org.jetbrains.kotlin.name.Name
|
||||
import org.jetbrains.kotlin.serialization.deserialization.descriptors.DeserializedContainerSource
|
||||
|
||||
@OptIn(ObsoleteDescriptorBasedAPI::class)
|
||||
class Fir2IrDeclarationStorage(
|
||||
private val components: Fir2IrComponents,
|
||||
private val moduleDescriptor: FirModuleDescriptor,
|
||||
@@ -600,7 +602,9 @@ class Fir2IrDeclarationStorage(
|
||||
Name.special("<$prefix-${correspondingProperty.name}>"),
|
||||
propertyAccessor?.visibility ?: correspondingProperty.visibility,
|
||||
correspondingProperty.modality, accessorReturnType,
|
||||
isInline = false, isExternal = false, isTailrec = false, isSuspend = false, isExpect = false,
|
||||
isInline = propertyAccessor?.isInline == true,
|
||||
isExternal = propertyAccessor?.isExternal == true,
|
||||
isTailrec = false, isSuspend = false, isExpect = false,
|
||||
isFakeOverride = origin == IrDeclarationOrigin.FAKE_OVERRIDE,
|
||||
isOperator = false
|
||||
).apply {
|
||||
@@ -647,7 +651,6 @@ class Fir2IrDeclarationStorage(
|
||||
name: Name,
|
||||
isFinal: Boolean,
|
||||
firInitializerExpression: FirExpression?,
|
||||
thisReceiverOwner: IrClass?,
|
||||
type: IrType? = null
|
||||
): IrField {
|
||||
val inferredType = type ?: firInitializerExpression!!.typeRef.toIrType()
|
||||
@@ -657,14 +660,11 @@ class Fir2IrDeclarationStorage(
|
||||
IrFieldImpl(
|
||||
startOffset, endOffset, origin, symbol,
|
||||
name, inferredType,
|
||||
visibility, isFinal = isFinal, isExternal = false,
|
||||
visibility, isFinal = isFinal,
|
||||
isExternal = property.isExternal,
|
||||
isStatic = property.isStatic || parent !is IrClass,
|
||||
isFakeOverride = origin == IrDeclarationOrigin.FAKE_OVERRIDE
|
||||
).also {
|
||||
it.correspondingPropertySymbol = this@createBackingField.symbol
|
||||
if (!isFakeOverride && thisReceiverOwner != null) {
|
||||
it.populateOverriddenSymbols(thisReceiverOwner)
|
||||
}
|
||||
}.apply {
|
||||
metadata = FirMetadataSource.Property(property)
|
||||
convertAnnotationsFromLibrary(property)
|
||||
@@ -710,8 +710,7 @@ class Fir2IrDeclarationStorage(
|
||||
isConst = property.isConst,
|
||||
isLateinit = property.isLateInit,
|
||||
isDelegated = property.delegate != null,
|
||||
// TODO
|
||||
isExternal = false,
|
||||
isExternal = property.isExternal,
|
||||
isExpect = property.isExpect,
|
||||
isFakeOverride = origin == IrDeclarationOrigin.FAKE_OVERRIDE
|
||||
).apply {
|
||||
@@ -734,7 +733,7 @@ class Fir2IrDeclarationStorage(
|
||||
backingField = createBackingField(
|
||||
property, IrDeclarationOrigin.PROPERTY_BACKING_FIELD, descriptor,
|
||||
property.fieldVisibility, property.name, property.isVal, initializer,
|
||||
thisReceiverOwner, type
|
||||
type
|
||||
).also { field ->
|
||||
if (initializer is FirConstExpression<*>) {
|
||||
// TODO: Normally we shouldn't have error type here
|
||||
@@ -745,8 +744,7 @@ class Fir2IrDeclarationStorage(
|
||||
} else if (delegate != null) {
|
||||
backingField = createBackingField(
|
||||
property, IrDeclarationOrigin.PROPERTY_DELEGATE, descriptor,
|
||||
property.fieldVisibility, Name.identifier("${property.name}\$delegate"), true, delegate,
|
||||
thisReceiverOwner
|
||||
property.fieldVisibility, Name.identifier("${property.name}\$delegate"), true, delegate
|
||||
)
|
||||
}
|
||||
if (irParent != null) {
|
||||
@@ -799,8 +797,7 @@ class Fir2IrDeclarationStorage(
|
||||
field.name, type, field.visibility,
|
||||
isFinal = field.modality == Modality.FINAL,
|
||||
isExternal = false,
|
||||
isStatic = field.isStatic,
|
||||
isFakeOverride = false
|
||||
isStatic = field.isStatic
|
||||
).apply {
|
||||
metadata = FirMetadataSource.Variable(field)
|
||||
descriptor.bind(this)
|
||||
@@ -1024,13 +1021,6 @@ class Fir2IrDeclarationStorage(
|
||||
}
|
||||
}
|
||||
|
||||
private fun IrField.populateOverriddenSymbols(thisReceiverOwner: IrClass) {
|
||||
thisReceiverOwner.findMatchingOverriddenSymbolsFromSupertypes(components.irBuiltIns, this)
|
||||
.filterIsInstance<IrFieldSymbol>().singleOrNull()?.let {
|
||||
overriddenSymbols = listOf(it)
|
||||
}
|
||||
}
|
||||
|
||||
private fun IrMutableAnnotationContainer.convertAnnotationsFromLibrary(firAnnotationContainer: FirAnnotationContainer) {
|
||||
if ((firAnnotationContainer as? FirDeclaration)?.isFromLibrary == true) {
|
||||
annotationGenerator?.generate(this, firAnnotationContainer)
|
||||
|
||||
@@ -581,11 +581,15 @@ class Fir2IrVisitor(
|
||||
KtNodeTypes.POSTFIX_EXPRESSION -> IrStatementOrigin.EXCLEXCL
|
||||
else -> null
|
||||
}
|
||||
// If the constant true branch has empty body, it won't be converted. Thus, the entire `when` expression is effectively _not_
|
||||
// exhaustive anymore. In that case, coerce the return type of `when` expression to Unit as per the backend expectation.
|
||||
val effectivelyNotExhaustive = !whenExpression.isExhaustive ||
|
||||
whenExpression.branches.any { it.condition is FirElseIfTrueCondition && it.result.statements.isEmpty() }
|
||||
return conversionScope.withWhenSubject(subjectVariable) {
|
||||
whenExpression.convertWithOffsets { startOffset, endOffset ->
|
||||
val irWhen = IrWhenImpl(
|
||||
startOffset, endOffset,
|
||||
whenExpression.typeRef.toIrType(),
|
||||
if (effectivelyNotExhaustive) irBuiltIns.unitType else whenExpression.typeRef.toIrType(),
|
||||
origin
|
||||
).apply {
|
||||
var unconditionalBranchFound = false
|
||||
|
||||
@@ -27,6 +27,7 @@ import org.jetbrains.kotlin.fir.types.impl.FirImplicitNullableAnyTypeRef
|
||||
import org.jetbrains.kotlin.fir.types.impl.FirImplicitStringTypeRef
|
||||
import org.jetbrains.kotlin.fir.declarations.*
|
||||
import org.jetbrains.kotlin.incremental.components.NoLookupLocation
|
||||
import org.jetbrains.kotlin.ir.ObsoleteDescriptorBasedAPI
|
||||
import org.jetbrains.kotlin.ir.UNDEFINED_OFFSET
|
||||
import org.jetbrains.kotlin.ir.builders.IrGeneratorContextBase
|
||||
import org.jetbrains.kotlin.ir.declarations.*
|
||||
@@ -50,6 +51,7 @@ import org.jetbrains.kotlin.name.Name
|
||||
* fir own logic that traverses class hierarchies in fir elements. Also, this one creates and passes IR elements, instead of providing how
|
||||
* to declare them, to [DataClassMembersGenerator].
|
||||
*/
|
||||
@OptIn(ObsoleteDescriptorBasedAPI::class)
|
||||
class DataClassMembersGenerator(val components: Fir2IrComponents) {
|
||||
|
||||
fun generateInlineClassMembers(klass: FirClass<*>, irClass: IrClass): List<Name> =
|
||||
|
||||
@@ -8,6 +8,7 @@ package org.jetbrains.kotlin.fir.symbols
|
||||
import org.jetbrains.kotlin.descriptors.DeclarationDescriptor
|
||||
import org.jetbrains.kotlin.descriptors.SourceElement
|
||||
import org.jetbrains.kotlin.descriptors.annotations.Annotations
|
||||
import org.jetbrains.kotlin.ir.ObsoleteDescriptorBasedAPI
|
||||
import org.jetbrains.kotlin.ir.declarations.*
|
||||
import org.jetbrains.kotlin.ir.descriptors.*
|
||||
import org.jetbrains.kotlin.ir.symbols.IrBindableSymbol
|
||||
@@ -36,6 +37,7 @@ abstract class Fir2IrBindableSymbol<out D : DeclarationDescriptor, B : IrSymbolO
|
||||
override val isBound: Boolean
|
||||
get() = _owner != null
|
||||
|
||||
@ObsoleteDescriptorBasedAPI
|
||||
override val descriptor: D by lazy {
|
||||
when (val owner = owner) {
|
||||
is IrEnumEntry -> WrappedEnumEntryDescriptor().apply { bind(owner) }
|
||||
|
||||
@@ -7495,11 +7495,6 @@ public class FirBlackBoxCodegenTestGenerated extends AbstractFirBlackBoxCodegenT
|
||||
runTestWithPackageReplacement("compiler/testData/codegen/box/coroutines/intLikeVarSpilling/i2bResult.kt", "kotlin.coroutines");
|
||||
}
|
||||
|
||||
@TestMetadata("listThrowablePairInOneSlot.kt")
|
||||
public void testListThrowablePairInOneSlot() throws Exception {
|
||||
runTest("compiler/testData/codegen/box/coroutines/intLikeVarSpilling/listThrowablePairInOneSlot.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("loadFromBooleanArray.kt")
|
||||
public void testLoadFromBooleanArray_1_3() throws Exception {
|
||||
runTestWithPackageReplacement("compiler/testData/codegen/box/coroutines/intLikeVarSpilling/loadFromBooleanArray.kt", "kotlin.coroutines");
|
||||
@@ -8343,11 +8338,6 @@ public class FirBlackBoxCodegenTestGenerated extends AbstractFirBlackBoxCodegenT
|
||||
runTestWithPackageReplacement("compiler/testData/codegen/box/coroutines/varSpilling/kt19475.kt", "kotlin.coroutines");
|
||||
}
|
||||
|
||||
@TestMetadata("kt38925.kt")
|
||||
public void testKt38925_1_3() throws Exception {
|
||||
runTestWithPackageReplacement("compiler/testData/codegen/box/coroutines/varSpilling/kt38925.kt", "kotlin.coroutines");
|
||||
}
|
||||
|
||||
@TestMetadata("nullSpilling.kt")
|
||||
public void testNullSpilling_1_3() throws Exception {
|
||||
runTestWithPackageReplacement("compiler/testData/codegen/box/coroutines/varSpilling/nullSpilling.kt", "kotlin.coroutines");
|
||||
@@ -14140,6 +14130,11 @@ public class FirBlackBoxCodegenTestGenerated extends AbstractFirBlackBoxCodegenT
|
||||
runTest("compiler/testData/codegen/box/innerNested/innerGenericClassFromJava.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("innerImplicitParameter.kt")
|
||||
public void testInnerImplicitParameter() throws Exception {
|
||||
runTest("compiler/testData/codegen/box/innerNested/innerImplicitParameter.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("innerJavaClass.kt")
|
||||
public void testInnerJavaClass() throws Exception {
|
||||
runTest("compiler/testData/codegen/box/innerNested/innerJavaClass.kt");
|
||||
@@ -26082,6 +26077,11 @@ public class FirBlackBoxCodegenTestGenerated extends AbstractFirBlackBoxCodegenT
|
||||
KotlinTestUtils.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("compiler/testData/codegen/box/reflection/mapping/types"), Pattern.compile("^(.+)\\.kt$"), null, TargetBackend.JVM_IR, true);
|
||||
}
|
||||
|
||||
@TestMetadata("allSupertypes.kt")
|
||||
public void testAllSupertypes() throws Exception {
|
||||
runTest("compiler/testData/codegen/box/reflection/mapping/types/allSupertypes.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("annotationConstructorParameters.kt")
|
||||
public void testAnnotationConstructorParameters() throws Exception {
|
||||
runTest("compiler/testData/codegen/box/reflection/mapping/types/annotationConstructorParameters.kt");
|
||||
@@ -26097,6 +26097,11 @@ public class FirBlackBoxCodegenTestGenerated extends AbstractFirBlackBoxCodegenT
|
||||
runTest("compiler/testData/codegen/box/reflection/mapping/types/constructors.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("createType.kt")
|
||||
public void testCreateType() throws Exception {
|
||||
runTest("compiler/testData/codegen/box/reflection/mapping/types/createType.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("genericArrayElementType.kt")
|
||||
public void testGenericArrayElementType() throws Exception {
|
||||
runTest("compiler/testData/codegen/box/reflection/mapping/types/genericArrayElementType.kt");
|
||||
|
||||
@@ -1012,6 +1012,11 @@ public class Fir2IrTextTestGenerated extends AbstractFir2IrTextTest {
|
||||
runTest("compiler/testData/ir/irText/expressions/javaSyntheticPropertyAccess.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("jvmFieldReferenceWithIntersectionTypes.kt")
|
||||
public void testJvmFieldReferenceWithIntersectionTypes() throws Exception {
|
||||
runTest("compiler/testData/ir/irText/expressions/jvmFieldReferenceWithIntersectionTypes.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("jvmInstanceFieldReference.kt")
|
||||
public void testJvmInstanceFieldReference() throws Exception {
|
||||
runTest("compiler/testData/ir/irText/expressions/jvmInstanceFieldReference.kt");
|
||||
|
||||
@@ -99,7 +99,7 @@ abstract class BaseFirBuilder<T>(val baseSession: FirSession, val context: Conte
|
||||
CallableId(name, pathFqName)
|
||||
}
|
||||
context.className == FqName.ROOT -> CallableId(context.packageFqName, name)
|
||||
context.className.shortName() === ANONYMOUS_OBJECT_NAME -> CallableId(ANONYMOUS_CLASS_ID, name)
|
||||
context.className.shortName() == ANONYMOUS_OBJECT_NAME -> CallableId(ANONYMOUS_CLASS_ID, name)
|
||||
else -> CallableId(context.packageFqName, context.className, name)
|
||||
}
|
||||
|
||||
|
||||
@@ -726,7 +726,7 @@ class DeclarationsConverter(
|
||||
source = anonymousInitializer.toFirSourceElement()
|
||||
session = baseSession
|
||||
origin = FirDeclarationOrigin.Source
|
||||
body = if (stubMode) buildEmptyExpressionBlock() else firBlock
|
||||
body = if (stubMode) buildEmptyExpressionBlock() else firBlock ?: buildEmptyExpressionBlock()
|
||||
}
|
||||
}
|
||||
|
||||
@@ -940,16 +940,8 @@ class DeclarationsConverter(
|
||||
}
|
||||
|
||||
val propertyVisibility = modifiers.getVisibility()
|
||||
status = FirDeclarationStatusImpl(propertyVisibility, modifiers.getModality()).apply {
|
||||
isExpect = modifiers.hasExpect()
|
||||
isActual = modifiers.hasActual()
|
||||
isOverride = modifiers.hasOverride()
|
||||
isConst = modifiers.isConst()
|
||||
isLateInit = modifiers.hasLateinit()
|
||||
}
|
||||
|
||||
|
||||
val convertedAccessors = accessors.map { convertGetterOrSetter(it, returnType, propertyVisibility) }
|
||||
val convertedAccessors = accessors.map { convertGetterOrSetter(it, returnType, propertyVisibility, modifiers) }
|
||||
this.getter = convertedAccessors.find { it.isGetter }
|
||||
?: FirDefaultPropertyGetter(null, session, FirDeclarationOrigin.Source, returnType, propertyVisibility)
|
||||
this.setter =
|
||||
@@ -958,6 +950,19 @@ class DeclarationsConverter(
|
||||
?: FirDefaultPropertySetter(null, session, FirDeclarationOrigin.Source, returnType, propertyVisibility)
|
||||
} else null
|
||||
|
||||
// Upward propagation of `inline` and `external` modifiers (from accessors to property)
|
||||
// Note that, depending on `var` or `val`, checking setter's modifiers should be careful: for `val`, setter doesn't
|
||||
// exist (null); for `var`, the retrieval of the specific modifier is supposed to be `true`
|
||||
status = FirDeclarationStatusImpl(propertyVisibility, modifiers.getModality()).apply {
|
||||
isExpect = modifiers.hasExpect()
|
||||
isActual = modifiers.hasActual()
|
||||
isOverride = modifiers.hasOverride()
|
||||
isConst = modifiers.isConst()
|
||||
isLateInit = modifiers.hasLateinit()
|
||||
isInline = modifiers.hasInline() || (getter!!.isInline && setter?.isInline != false)
|
||||
isExternal = modifiers.hasExternal() || (getter!!.isExternal && setter?.isExternal != false)
|
||||
}
|
||||
|
||||
val receiver = delegateExpression?.let {
|
||||
expressionConverter.getAsFirExpression<FirExpression>(it, "Should have delegate")
|
||||
}
|
||||
@@ -1031,7 +1036,8 @@ class DeclarationsConverter(
|
||||
private fun convertGetterOrSetter(
|
||||
getterOrSetter: LighterASTNode,
|
||||
propertyTypeRef: FirTypeRef,
|
||||
propertyVisibility: Visibility
|
||||
propertyVisibility: Visibility,
|
||||
propertyModifiers: Modifier
|
||||
): FirPropertyAccessor {
|
||||
var modifiers = Modifier()
|
||||
var isGetter = true
|
||||
@@ -1060,6 +1066,12 @@ class DeclarationsConverter(
|
||||
if (accessorVisibility == Visibilities.UNKNOWN) {
|
||||
accessorVisibility = propertyVisibility
|
||||
}
|
||||
val status =
|
||||
// Downward propagation of `inline` and `external` modifiers (from property to its accessors)
|
||||
FirDeclarationStatusImpl(accessorVisibility, Modality.FINAL).apply {
|
||||
isInline = propertyModifiers.hasInline() || modifiers.hasInline()
|
||||
isExternal = propertyModifiers.hasExternal() || modifiers.hasExternal()
|
||||
}
|
||||
val sourceElement = getterOrSetter.toFirSourceElement()
|
||||
if (block == null && expression == null) {
|
||||
return FirDefaultPropertyAccessor
|
||||
@@ -1073,6 +1085,7 @@ class DeclarationsConverter(
|
||||
)
|
||||
.also {
|
||||
it.annotations += modifiers.annotations
|
||||
it.status = status
|
||||
}
|
||||
}
|
||||
val target = FirFunctionTarget(labelName = null, isLambda = false)
|
||||
@@ -1083,7 +1096,7 @@ class DeclarationsConverter(
|
||||
returnTypeRef = returnType ?: if (isGetter) propertyTypeRef else implicitUnitType
|
||||
symbol = FirPropertyAccessorSymbol()
|
||||
this.isGetter = isGetter
|
||||
status = FirDeclarationStatusImpl(accessorVisibility, Modality.FINAL)
|
||||
this.status = status
|
||||
context.firFunctionTargets += target
|
||||
annotations += modifiers.annotations
|
||||
|
||||
|
||||
@@ -261,6 +261,14 @@ class RawFirBuilder(
|
||||
): FirPropertyAccessor {
|
||||
val accessorVisibility =
|
||||
if (this?.visibility != null && this.visibility != Visibilities.UNKNOWN) this.visibility else property.visibility
|
||||
// Downward propagation of `inline` and `external` modifiers (from property to its accessors)
|
||||
val status =
|
||||
FirDeclarationStatusImpl(accessorVisibility, Modality.FINAL).apply {
|
||||
isInline = property.hasModifier(INLINE_KEYWORD) ||
|
||||
this@toFirPropertyAccessor?.hasModifier(INLINE_KEYWORD) == true
|
||||
isExternal = property.hasModifier(EXTERNAL_KEYWORD) ||
|
||||
this@toFirPropertyAccessor?.hasModifier(EXTERNAL_KEYWORD) == true
|
||||
}
|
||||
if (this == null || !hasBody()) {
|
||||
val propertySource = property.toFirSourceElement()
|
||||
return FirDefaultPropertyAccessor
|
||||
@@ -276,6 +284,7 @@ class RawFirBuilder(
|
||||
if (this != null) {
|
||||
it.extractAnnotationsFrom(this)
|
||||
}
|
||||
it.status = status
|
||||
}
|
||||
}
|
||||
val source = this.toFirSourceElement()
|
||||
@@ -290,7 +299,7 @@ class RawFirBuilder(
|
||||
returnTypeReference.toFirOrUnitType()
|
||||
}
|
||||
this.isGetter = isGetter
|
||||
status = FirDeclarationStatusImpl(accessorVisibility, Modality.FINAL)
|
||||
this.status = status
|
||||
extractAnnotationsTo(this)
|
||||
this@RawFirBuilder.context.firFunctionTargets += accessorTarget
|
||||
extractValueParametersTo(this, propertyTypeRef)
|
||||
@@ -1078,19 +1087,25 @@ class RawFirBuilder(
|
||||
expression = { delegateExpression }.toFirExpression("Should have delegate")
|
||||
}
|
||||
} else null
|
||||
|
||||
getter = this@toFirProperty.getter.toFirPropertyAccessor(this@toFirProperty, propertyType, isGetter = true)
|
||||
setter = if (isVar) {
|
||||
this@toFirProperty.setter.toFirPropertyAccessor(this@toFirProperty, propertyType, isGetter = false)
|
||||
} else null
|
||||
|
||||
// Upward propagation of `inline` and `external` modifiers (from accessors to property)
|
||||
// Note that, depending on `var` or `val`, checking setter's modifiers should be careful: for `val`, setter doesn't
|
||||
// exist (null); for `var`, the retrieval of the specific modifier is supposed to be `true`
|
||||
status = FirDeclarationStatusImpl(visibility, modality).apply {
|
||||
isExpect = hasExpectModifier()
|
||||
isActual = hasActualModifier()
|
||||
isOverride = hasModifier(OVERRIDE_KEYWORD)
|
||||
isConst = hasModifier(CONST_KEYWORD)
|
||||
isLateInit = hasModifier(LATEINIT_KEYWORD)
|
||||
isInline = hasModifier(INLINE_KEYWORD) || (getter!!.isInline && setter?.isInline != false)
|
||||
isExternal = hasModifier(EXTERNAL_KEYWORD) || (getter!!.isExternal && setter?.isExternal != false)
|
||||
}
|
||||
|
||||
getter = this@toFirProperty.getter.toFirPropertyAccessor(this@toFirProperty, propertyType, isGetter = true)
|
||||
setter = if (isVar) {
|
||||
this@toFirProperty.setter.toFirPropertyAccessor(this@toFirProperty, propertyType, isGetter = false)
|
||||
} else null
|
||||
|
||||
val receiver = delegateExpression?.toFirExpression("Should have delegate")
|
||||
generateAccessorsByDelegate(
|
||||
delegateBuilder,
|
||||
@@ -1350,6 +1365,7 @@ class RawFirBuilder(
|
||||
else -> null
|
||||
}
|
||||
val hasSubject = subjectExpression != null
|
||||
|
||||
@OptIn(FirContractViolation::class)
|
||||
val ref = FirExpressionRef<FirWhenExpression>()
|
||||
return buildWhenExpression {
|
||||
|
||||
@@ -30,14 +30,14 @@ FILE: annotation.kt
|
||||
}
|
||||
|
||||
public final static enum entry FIRST: R|My| = @base() object : R|My| {
|
||||
private constructor(): R|anonymous| {
|
||||
private constructor(): R|<anonymous>| {
|
||||
super<R|My|>()
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public final static enum entry SECOND: R|My| = @base() object : R|My| {
|
||||
private constructor(): R|anonymous| {
|
||||
private constructor(): R|<anonymous>| {
|
||||
super<R|My|>()
|
||||
}
|
||||
|
||||
|
||||
@@ -14,12 +14,12 @@ FILE: constructorInObject.kt
|
||||
}
|
||||
|
||||
public final static enum entry X: R|B| = object : R|B| {
|
||||
private constructor(): R|anonymous| {
|
||||
private constructor(): R|<anonymous>| {
|
||||
super<R|B|>()
|
||||
}
|
||||
|
||||
public? constructor(): R|anonymous| {
|
||||
this<R|anonymous|>()
|
||||
public? constructor(): R|<anonymous>| {
|
||||
this<R|<anonymous>|>()
|
||||
}
|
||||
|
||||
}
|
||||
@@ -45,7 +45,7 @@ FILE: constructorInObject.kt
|
||||
|
||||
}
|
||||
public? final? val anonObject: <implicit> = object : R|kotlin/Any| {
|
||||
public? constructor(): R|anonymous| {
|
||||
public? constructor(): R|<anonymous>| {
|
||||
super<R|kotlin/Any|>()
|
||||
}
|
||||
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
FILE: constructorOfAnonymousObject.kt
|
||||
private final? fun resolveAccessorCall(suspendPropertyDescriptor: PropertyDescriptor, context: TranslationContext): ResolvedCall<PropertyDescriptor> {
|
||||
^resolveAccessorCall object : ResolvedCall<PropertyDescriptor> {
|
||||
private constructor(): R|anonymous| {
|
||||
private constructor(): R|<anonymous>| {
|
||||
super<<implicit>>()
|
||||
}
|
||||
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
FILE: emptyAnonymousObject.kt
|
||||
public? final? fun test(): R|kotlin/Unit| {
|
||||
lval x: <implicit> = object : R|kotlin/Any| {
|
||||
private constructor(): R|anonymous| {
|
||||
private constructor(): R|<anonymous>| {
|
||||
super<R|kotlin/Any|>()
|
||||
}
|
||||
|
||||
|
||||
@@ -26,7 +26,7 @@ FILE: enums.kt
|
||||
internal get(): Double
|
||||
|
||||
public final static enum entry MERCURY: R|Planet| = object : R|Planet| {
|
||||
private constructor(): R|anonymous| {
|
||||
private constructor(): R|<anonymous>| {
|
||||
super<R|Planet|>(Double(1.0), Double(2.0))
|
||||
}
|
||||
|
||||
@@ -37,7 +37,7 @@ FILE: enums.kt
|
||||
}
|
||||
|
||||
public final static enum entry VENERA: R|Planet| = object : R|Planet| {
|
||||
private constructor(): R|anonymous| {
|
||||
private constructor(): R|<anonymous>| {
|
||||
super<R|Planet|>(Double(3.0), Double(4.0))
|
||||
}
|
||||
|
||||
@@ -48,7 +48,7 @@ FILE: enums.kt
|
||||
}
|
||||
|
||||
public final static enum entry EARTH: R|Planet| = object : R|Planet| {
|
||||
private constructor(): R|anonymous| {
|
||||
private constructor(): R|<anonymous>| {
|
||||
super<R|Planet|>(Double(5.0), Double(6.0))
|
||||
}
|
||||
|
||||
@@ -89,49 +89,49 @@ FILE: enums.kt
|
||||
public? get(): String
|
||||
|
||||
public final static enum entry FIX_STACK_BEFORE_JUMP: R|PseudoInsn| = object : R|PseudoInsn| {
|
||||
private constructor(): R|anonymous| {
|
||||
private constructor(): R|<anonymous>| {
|
||||
super<R|PseudoInsn|>()
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public final static enum entry FAKE_ALWAYS_TRUE_IFEQ: R|PseudoInsn| = object : R|PseudoInsn| {
|
||||
private constructor(): R|anonymous| {
|
||||
private constructor(): R|<anonymous>| {
|
||||
super<R|PseudoInsn|>(String(()I))
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public final static enum entry FAKE_ALWAYS_FALSE_IFEQ: R|PseudoInsn| = object : R|PseudoInsn| {
|
||||
private constructor(): R|anonymous| {
|
||||
private constructor(): R|<anonymous>| {
|
||||
super<R|PseudoInsn|>(String(()I))
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public final static enum entry SAVE_STACK_BEFORE_TRY: R|PseudoInsn| = object : R|PseudoInsn| {
|
||||
private constructor(): R|anonymous| {
|
||||
private constructor(): R|<anonymous>| {
|
||||
super<R|PseudoInsn|>()
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public final static enum entry RESTORE_STACK_IN_TRY_CATCH: R|PseudoInsn| = object : R|PseudoInsn| {
|
||||
private constructor(): R|anonymous| {
|
||||
private constructor(): R|<anonymous>| {
|
||||
super<R|PseudoInsn|>()
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public final static enum entry STORE_NOT_NULL: R|PseudoInsn| = object : R|PseudoInsn| {
|
||||
private constructor(): R|anonymous| {
|
||||
private constructor(): R|<anonymous>| {
|
||||
super<R|PseudoInsn|>()
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public final static enum entry AS_NOT_NULL: R|PseudoInsn| = object : R|PseudoInsn| {
|
||||
private constructor(): R|anonymous| {
|
||||
private constructor(): R|<anonymous>| {
|
||||
super<R|PseudoInsn|>(String((Ljava/lang/Object;)Ljava/lang/Object;))
|
||||
}
|
||||
|
||||
|
||||
@@ -22,7 +22,7 @@ FILE: enums2.kt
|
||||
public? get(): Some
|
||||
|
||||
public final static enum entry FIRST: R|SomeEnum| = object : R|SomeEnum| {
|
||||
private constructor(): R|anonymous| {
|
||||
private constructor(): R|<anonymous>| {
|
||||
super<R|SomeEnum|>(O1#)
|
||||
}
|
||||
|
||||
@@ -33,7 +33,7 @@ FILE: enums2.kt
|
||||
}
|
||||
|
||||
public final static enum entry SECOND: R|SomeEnum| = object : R|SomeEnum| {
|
||||
private constructor(): R|anonymous| {
|
||||
private constructor(): R|<anonymous>| {
|
||||
super<R|SomeEnum|>(O2#)
|
||||
}
|
||||
|
||||
|
||||
@@ -20,7 +20,7 @@ FILE: locals.kt
|
||||
}
|
||||
|
||||
lval code: <implicit> = object : Any {
|
||||
private constructor(): R|anonymous| {
|
||||
private constructor(): R|<anonymous>| {
|
||||
super<Any>()
|
||||
}
|
||||
|
||||
|
||||
@@ -20,7 +20,6 @@ import org.jetbrains.kotlin.fir.references.FirErrorNamedReference
|
||||
import org.jetbrains.kotlin.fir.render
|
||||
import org.jetbrains.kotlin.fir.visitors.FirVisitorVoid
|
||||
import org.jetbrains.kotlin.psi.*
|
||||
import org.jetbrains.kotlin.psi.psiUtil.getStartOffsetIn
|
||||
import org.jetbrains.kotlin.psi.psiUtil.getStrictParentOfType
|
||||
import org.jetbrains.kotlin.psi.psiUtil.parents
|
||||
import org.jetbrains.kotlin.test.JUnit3RunnerWithInners
|
||||
@@ -52,7 +51,8 @@ class RawFirBuilderTotalKotlinTestCase : AbstractRawFirBuilderTestCase() {
|
||||
println("BASE PATH: $testDataPath")
|
||||
for (file in root.walkTopDown()) {
|
||||
if (file.isDirectory) continue
|
||||
if (file.path.contains("testData") || file.path.contains("resources")) continue
|
||||
val path = file.path
|
||||
if ("testData" in path || "resources" in path || "api/js" in path.replace('\\', '/')) continue
|
||||
if (file.extension != "kt") continue
|
||||
try {
|
||||
val ktFile = createKtFile(file.toRelativeString(root))
|
||||
@@ -175,7 +175,8 @@ class RawFirBuilderTotalKotlinTestCase : AbstractRawFirBuilderTestCase() {
|
||||
val root = File(testDataPath)
|
||||
for (file in root.walkTopDown()) {
|
||||
if (file.isDirectory) continue
|
||||
if (file.path.contains("testData") || file.path.contains("resources")) continue
|
||||
val path = file.path
|
||||
if ("testData" in path || "resources" in path || "api/js" in path.replace('\\', '/')) continue
|
||||
if (file.extension != "kt") continue
|
||||
val ktFile = createKtFile(file.toRelativeString(root))
|
||||
val firFile = ktFile.toFirFile(stubMode = false)
|
||||
@@ -201,7 +202,8 @@ class RawFirBuilderTotalKotlinTestCase : AbstractRawFirBuilderTestCase() {
|
||||
var counter = 0
|
||||
for (file in root.walkTopDown()) {
|
||||
if (file.isDirectory) continue
|
||||
if (file.path.contains("testData") || file.path.contains("resources")) continue
|
||||
val path = file.path
|
||||
if ("testData" in path || "resources" in path || "api/js" in path.replace('\\', '/')) continue
|
||||
if (file.extension != "kt") continue
|
||||
val ktFile = createKtFile(file.toRelativeString(root))
|
||||
val firFile: FirFile = ktFile.toFirFile(stubMode = false)
|
||||
|
||||
@@ -63,6 +63,8 @@ inline val FirMemberDeclaration.isFromEnumClass: Boolean get() = status.isFromEn
|
||||
|
||||
inline val FirPropertyAccessor.modality get() = status.modality
|
||||
inline val FirPropertyAccessor.visibility get() = status.visibility
|
||||
inline val FirPropertyAccessor.isInline get() = status.isInline
|
||||
inline val FirPropertyAccessor.isExternal get() = status.isExternal
|
||||
inline val FirPropertyAccessor.allowsToHaveFakeOverride: Boolean
|
||||
get() = !Visibilities.isPrivate(visibility) && visibility != Visibilities.INVISIBLE_FAKE
|
||||
|
||||
|
||||
@@ -10,6 +10,7 @@ import org.jetbrains.kotlin.fir.declarations.*
|
||||
import org.jetbrains.kotlin.fir.symbols.ConeClassLikeLookupTag
|
||||
import org.jetbrains.kotlin.name.ClassId
|
||||
import org.jetbrains.kotlin.name.FqName
|
||||
import org.jetbrains.kotlin.name.Name
|
||||
|
||||
sealed class FirClassLikeSymbol<D>(
|
||||
val classId: ClassId
|
||||
@@ -27,7 +28,7 @@ sealed class FirClassSymbol<C : FirClass<C>>(classId: ClassId) : FirClassLikeSym
|
||||
|
||||
class FirRegularClassSymbol(classId: ClassId) : FirClassSymbol<FirRegularClass>(classId)
|
||||
|
||||
val ANONYMOUS_CLASS_ID = ClassId(FqName.ROOT, FqName("anonymous"), true)
|
||||
val ANONYMOUS_CLASS_ID = ClassId(FqName.ROOT, FqName.topLevel(Name.special("<anonymous>")), true)
|
||||
|
||||
class FirAnonymousObjectSymbol : FirClassSymbol<FirAnonymousObject>(ANONYMOUS_CLASS_ID)
|
||||
|
||||
|
||||
@@ -24,8 +24,6 @@ import java.util.ArrayList
|
||||
|
||||
class JavaClassifierTypeImpl(psiClassType: PsiClassType) : JavaTypeImpl<PsiClassType>(psiClassType), JavaClassifierType {
|
||||
|
||||
private var resolutionResult: ResolutionResult? = null
|
||||
|
||||
override val classifier: JavaClassifierImpl<*>?
|
||||
get() = resolve().classifier
|
||||
|
||||
@@ -65,15 +63,13 @@ class JavaClassifierTypeImpl(psiClassType: PsiClassType) : JavaTypeImpl<PsiClass
|
||||
)
|
||||
|
||||
private fun resolve(): ResolutionResult {
|
||||
return resolutionResult ?: run {
|
||||
return run {
|
||||
val result = psi.resolveGenerics()
|
||||
val psiClass = result.element
|
||||
val substitutor = result.substitutor
|
||||
ResolutionResult(
|
||||
psiClass?.let { JavaClassifierImpl.create(it) }, substitutor, PsiClassType.isRaw(result)
|
||||
).apply {
|
||||
resolutionResult = this
|
||||
}
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -25,7 +25,8 @@ class SuspensionPointInsideMutexLockChecker : CallChecker {
|
||||
val descriptor = resolvedCall.candidateDescriptor
|
||||
if (descriptor !is FunctionDescriptor || !descriptor.isSuspend) return
|
||||
|
||||
val enclosingSuspendFunctionSource = findEnclosingSuspendFunction(context)?.source?.getPsi() ?: return
|
||||
val enclosingSuspendFunctionSource =
|
||||
findEnclosingSuspendFunction(context, resolvedCall.call.callElement)?.source?.getPsi() ?: return
|
||||
|
||||
// Search for `synchronized` call
|
||||
var parent = reportOn
|
||||
|
||||
@@ -15,6 +15,7 @@ import org.jetbrains.kotlin.cfg.pseudocode.instructions.InstructionVisitor
|
||||
import org.jetbrains.kotlin.cfg.pseudocode.instructions.KtElementInstruction
|
||||
import org.jetbrains.kotlin.cfg.pseudocode.instructions.eval.*
|
||||
import org.jetbrains.kotlin.cfg.pseudocode.instructions.jumps.*
|
||||
import org.jetbrains.kotlin.cfg.pseudocode.instructions.special.LocalFunctionDeclarationInstruction
|
||||
import org.jetbrains.kotlin.cfg.pseudocode.instructions.special.MarkInstruction
|
||||
import org.jetbrains.kotlin.cfg.pseudocode.instructions.special.VariableDeclarationInstruction
|
||||
import org.jetbrains.kotlin.cfg.pseudocode.sideEffectFree
|
||||
@@ -24,6 +25,8 @@ import org.jetbrains.kotlin.cfg.variable.VariableUseState.*
|
||||
import org.jetbrains.kotlin.config.LanguageFeature
|
||||
import org.jetbrains.kotlin.config.LanguageVersionSettings
|
||||
import org.jetbrains.kotlin.descriptors.*
|
||||
import org.jetbrains.kotlin.descriptors.impl.AnonymousFunctionDescriptor
|
||||
import org.jetbrains.kotlin.descriptors.impl.LocalVariableDescriptor
|
||||
import org.jetbrains.kotlin.diagnostics.Diagnostic
|
||||
import org.jetbrains.kotlin.diagnostics.DiagnosticFactory
|
||||
import org.jetbrains.kotlin.diagnostics.Errors
|
||||
@@ -43,7 +46,9 @@ import org.jetbrains.kotlin.resolve.bindingContextUtil.isUsedAsExpression
|
||||
import org.jetbrains.kotlin.resolve.bindingContextUtil.isUsedAsResultOfLambda
|
||||
import org.jetbrains.kotlin.resolve.bindingContextUtil.isUsedAsStatement
|
||||
import org.jetbrains.kotlin.resolve.calls.callUtil.getResolvedCall
|
||||
import org.jetbrains.kotlin.resolve.calls.checkers.findDestructuredVariable
|
||||
import org.jetbrains.kotlin.resolve.calls.model.ResolvedCall
|
||||
import org.jetbrains.kotlin.resolve.calls.model.VariableAsFunctionResolvedCall
|
||||
import org.jetbrains.kotlin.resolve.calls.resolvedCallUtil.getDispatchReceiverWithSmartCast
|
||||
import org.jetbrains.kotlin.resolve.calls.resolvedCallUtil.hasThisOrNoDispatchReceiver
|
||||
import org.jetbrains.kotlin.resolve.calls.util.FakeCallableDescriptorForObject
|
||||
@@ -51,6 +56,7 @@ import org.jetbrains.kotlin.resolve.calls.util.isSingleUnderscore
|
||||
import org.jetbrains.kotlin.resolve.checkers.PlatformDiagnosticSuppressor
|
||||
import org.jetbrains.kotlin.resolve.descriptorUtil.isEffectivelyExternal
|
||||
import org.jetbrains.kotlin.resolve.descriptorUtil.module
|
||||
import org.jetbrains.kotlin.resolve.scopes.receivers.ExtensionReceiver
|
||||
import org.jetbrains.kotlin.types.KotlinType
|
||||
import org.jetbrains.kotlin.types.TypeUtils.*
|
||||
import org.jetbrains.kotlin.types.expressions.ExpressionTypingUtils
|
||||
@@ -101,6 +107,8 @@ class ControlFlowInformationProvider private constructor(
|
||||
markUnusedVariables()
|
||||
}
|
||||
|
||||
checkForSuspendLambdaAndMarkParameters(pseudocode)
|
||||
|
||||
markStatements()
|
||||
markAnnotationArguments()
|
||||
|
||||
@@ -808,6 +816,88 @@ class ControlFlowInformationProvider private constructor(
|
||||
}
|
||||
}
|
||||
|
||||
private fun checkForSuspendLambdaAndMarkParameters(pseudocode: Pseudocode) {
|
||||
for (instruction in pseudocode.instructionsIncludingDeadCode) {
|
||||
if (instruction is LocalFunctionDeclarationInstruction) {
|
||||
val psi = instruction.body.correspondingElement
|
||||
if (psi is KtFunctionLiteral) {
|
||||
val descriptor = trace.bindingContext[DECLARATION_TO_DESCRIPTOR, psi]
|
||||
if (descriptor is AnonymousFunctionDescriptor && descriptor.isSuspend) {
|
||||
markReadOfSuspendLambdaParameters(instruction.body)
|
||||
continue
|
||||
}
|
||||
}
|
||||
checkForSuspendLambdaAndMarkParameters(instruction.body)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun markReadOfSuspendLambdaParameters(pseudocode: Pseudocode) {
|
||||
val instructions = pseudocode.instructionsIncludingDeadCode
|
||||
for (instruction in instructions) {
|
||||
if (instruction is LocalFunctionDeclarationInstruction) {
|
||||
markReadOfSuspendLambdaParameters(instruction.body)
|
||||
continue
|
||||
}
|
||||
markReadOfSuspendLambdaParameter(instruction)
|
||||
markImplicitReceiverOfSuspendLambda(instruction)
|
||||
}
|
||||
}
|
||||
|
||||
private fun markReadOfSuspendLambdaParameter(instruction: Instruction) {
|
||||
if (instruction !is ReadValueInstruction) return
|
||||
val target = instruction.target as? AccessTarget.Call ?: return
|
||||
val descriptor = target.resolvedCall.resultingDescriptor
|
||||
if (descriptor is ParameterDescriptor) {
|
||||
val containing = descriptor.containingDeclaration
|
||||
if (containing is AnonymousFunctionDescriptor && containing.isSuspend) {
|
||||
trace.record(SUSPEND_LAMBDA_PARAMETER_USED, containing to descriptor.index())
|
||||
}
|
||||
} else if (descriptor is LocalVariableDescriptor) {
|
||||
val containing = descriptor.containingDeclaration
|
||||
if (containing is AnonymousFunctionDescriptor && containing.isSuspend) {
|
||||
findDestructuredVariable(descriptor, containing)?.let {
|
||||
trace.record(SUSPEND_LAMBDA_PARAMETER_USED, containing to it.index)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun markImplicitReceiverOfSuspendLambda(instruction: Instruction) {
|
||||
if (instruction !is MagicInstruction || instruction.kind != MagicKind.IMPLICIT_RECEIVER) return
|
||||
|
||||
fun CallableDescriptor?.markIfNeeded() {
|
||||
if (this is AnonymousFunctionDescriptor && isSuspend) {
|
||||
trace.record(SUSPEND_LAMBDA_PARAMETER_USED, this to -1)
|
||||
}
|
||||
}
|
||||
|
||||
if (instruction.element is KtDestructuringDeclarationEntry || instruction.element is KtCallExpression) {
|
||||
val visited = mutableSetOf<Instruction>()
|
||||
fun dfs(insn: Instruction) {
|
||||
if (!visited.add(insn)) return
|
||||
if (insn is CallInstruction && insn.element == instruction.element) {
|
||||
for ((_, receiver) in insn.receiverValues) {
|
||||
(receiver as? ExtensionReceiver)?.declarationDescriptor?.apply { markIfNeeded() }
|
||||
}
|
||||
}
|
||||
for (next in insn.nextInstructions) {
|
||||
dfs(next)
|
||||
}
|
||||
}
|
||||
|
||||
instruction.next?.let { dfs(it) }
|
||||
} else if (instruction.element is KtNameReferenceExpression) {
|
||||
val call = instruction.element.getResolvedCall(trace.bindingContext)
|
||||
if (call is VariableAsFunctionResolvedCall) {
|
||||
(call.variableCall.dispatchReceiver as? ExtensionReceiver)?.declarationDescriptor?.apply { markIfNeeded() }
|
||||
(call.variableCall.extensionReceiver as? ExtensionReceiver)?.declarationDescriptor?.apply { markIfNeeded() }
|
||||
}
|
||||
(call?.dispatchReceiver as? ExtensionReceiver)?.declarationDescriptor?.apply { markIfNeeded() }
|
||||
(call?.extensionReceiver as? ExtensionReceiver)?.declarationDescriptor?.apply { markIfNeeded() }
|
||||
}
|
||||
}
|
||||
|
||||
private fun markAnnotationArguments() {
|
||||
if (subroutine is KtAnnotationEntry) {
|
||||
markAnnotationArguments(subroutine)
|
||||
@@ -1219,3 +1309,10 @@ class ControlFlowInformationProvider private constructor(
|
||||
|| diagnosticFactory === UNUSED_CHANGED_VALUE
|
||||
}
|
||||
}
|
||||
|
||||
fun ParameterDescriptor.index(): Int =
|
||||
when (this) {
|
||||
is ReceiverParameterDescriptor -> -1
|
||||
is ValueParameterDescriptor -> index
|
||||
else -> error("expected either receiver or value parameter, but got: $this")
|
||||
}
|
||||
@@ -8,6 +8,7 @@ package org.jetbrains.kotlin.resolve;
|
||||
import com.google.common.collect.ImmutableMap;
|
||||
import com.intellij.openapi.util.Ref;
|
||||
import com.intellij.psi.PsiElement;
|
||||
import kotlin.Pair;
|
||||
import kotlin.annotations.jvm.ReadOnly;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
@@ -18,13 +19,13 @@ import org.jetbrains.kotlin.contracts.description.InvocationKind;
|
||||
import org.jetbrains.kotlin.contracts.model.Computation;
|
||||
import org.jetbrains.kotlin.descriptors.*;
|
||||
import org.jetbrains.kotlin.descriptors.annotations.AnnotationDescriptor;
|
||||
import org.jetbrains.kotlin.descriptors.impl.AnonymousFunctionDescriptor;
|
||||
import org.jetbrains.kotlin.name.FqName;
|
||||
import org.jetbrains.kotlin.name.FqNameUnsafe;
|
||||
import org.jetbrains.kotlin.psi.*;
|
||||
import org.jetbrains.kotlin.resolve.calls.context.BasicCallResolutionContext;
|
||||
import org.jetbrains.kotlin.resolve.calls.inference.ConstraintSystemCompleter;
|
||||
import org.jetbrains.kotlin.resolve.calls.model.PartialCallContainer;
|
||||
import org.jetbrains.kotlin.resolve.calls.model.PartialCallResolutionResult;
|
||||
import org.jetbrains.kotlin.resolve.calls.model.ResolvedCall;
|
||||
import org.jetbrains.kotlin.resolve.calls.smartcasts.DataFlowInfo;
|
||||
import org.jetbrains.kotlin.resolve.calls.smartcasts.DataFlowValue;
|
||||
@@ -169,6 +170,8 @@ public interface BindingContext {
|
||||
WritableSlice<KtExpression, Boolean> VARIABLE_REASSIGNMENT = Slices.createSimpleSetSlice();
|
||||
WritableSlice<ValueParameterDescriptor, Boolean> AUTO_CREATED_IT = Slices.createSimpleSetSlice();
|
||||
|
||||
WritableSlice<Pair<AnonymousFunctionDescriptor, Integer>, Boolean> SUSPEND_LAMBDA_PARAMETER_USED = Slices.createSimpleSlice();
|
||||
|
||||
/**
|
||||
* Has type of current expression has been already resolved
|
||||
*/
|
||||
|
||||
@@ -56,7 +56,13 @@ fun KtReturnExpression.getTargetFunction(context: BindingContext): KtCallableDec
|
||||
return getTargetFunctionDescriptor(context)?.let { DescriptorToSourceUtils.descriptorToDeclaration(it) as? KtCallableDeclaration }
|
||||
}
|
||||
|
||||
fun KtExpression.isUsedAsExpression(context: BindingContext): Boolean = context[USED_AS_EXPRESSION, this]!!
|
||||
fun KtExpression.isUsedAsExpression(context: BindingContext): Boolean =
|
||||
context[USED_AS_EXPRESSION, this]
|
||||
?: throw AssertionError(
|
||||
"BindingContext returned null for Boolean slice: " +
|
||||
if (context == EMPTY) "BindingContext.EMPTY" else context.javaClass.toString()
|
||||
)
|
||||
|
||||
fun KtExpression.isUsedAsResultOfLambda(context: BindingContext): Boolean = context[USED_AS_RESULT_OF_LAMBDA, this]!!
|
||||
fun KtExpression.isUsedAsStatement(context: BindingContext): Boolean = !isUsedAsExpression(context)
|
||||
|
||||
|
||||
@@ -103,7 +103,7 @@ class CapturingInClosureChecker : CallChecker {
|
||||
// We cannot box function/lambda arguments, destructured lambda arguments, for-loop index variables,
|
||||
// exceptions inside catch blocks ans vals in when
|
||||
return if (isArgument(variable, variableParent) ||
|
||||
isDestructuredVariable(variable, variableParent) ||
|
||||
findDestructuredVariable(variable, variableParent) != null ||
|
||||
isForLoopParameter(variable) ||
|
||||
isCatchBlockParameter(variable) ||
|
||||
isValInWhen(variable)
|
||||
@@ -118,12 +118,6 @@ class CapturingInClosureChecker : CallChecker {
|
||||
variable is ValueParameterDescriptor && variableParent is CallableDescriptor
|
||||
&& variableParent.valueParameters.contains(variable)
|
||||
|
||||
private fun isDestructuredVariable(variable: VariableDescriptor, variableParent: DeclarationDescriptor): Boolean =
|
||||
variable is LocalVariableDescriptor && variableParent is AnonymousFunctionDescriptor &&
|
||||
variableParent.valueParameters.any {
|
||||
it is ValueParameterDescriptorImpl.WithDestructuringDeclaration && it.destructuringVariables.contains(variable)
|
||||
}
|
||||
|
||||
private fun isValInWhen(variable: VariableDescriptor): Boolean {
|
||||
val psi = ((variable as? LocalVariableDescriptor)?.source as? KotlinSourceElement)?.psi ?: return false
|
||||
return (psi.parent as? KtWhenExpression)?.let { it.subjectVariable == psi } == true
|
||||
@@ -178,3 +172,10 @@ class CapturingInClosureChecker : CallChecker {
|
||||
return getCalleeDescriptorAndParameter(bindingContext, argument)?.second?.isCrossinline == true
|
||||
}
|
||||
}
|
||||
|
||||
fun findDestructuredVariable(variable: VariableDescriptor, variableParent: DeclarationDescriptor): ValueParameterDescriptor? =
|
||||
if (variable is LocalVariableDescriptor && variableParent is AnonymousFunctionDescriptor) {
|
||||
variableParent.valueParameters.find {
|
||||
it is ValueParameterDescriptorImpl.WithDestructuringDeclaration && it.destructuringVariables.contains(variable)
|
||||
}
|
||||
} else null
|
||||
|
||||
@@ -12,13 +12,12 @@ import org.jetbrains.kotlin.descriptors.*
|
||||
import org.jetbrains.kotlin.diagnostics.DiagnosticSink
|
||||
import org.jetbrains.kotlin.diagnostics.Errors
|
||||
import org.jetbrains.kotlin.name.Name
|
||||
import org.jetbrains.kotlin.psi.KtCodeFragment
|
||||
import org.jetbrains.kotlin.psi.KtExpression
|
||||
import org.jetbrains.kotlin.psi.KtThisExpression
|
||||
import org.jetbrains.kotlin.psi.*
|
||||
import org.jetbrains.kotlin.psi.psiUtil.getParentOfType
|
||||
import org.jetbrains.kotlin.resolve.BindingContext
|
||||
import org.jetbrains.kotlin.resolve.DescriptorUtils
|
||||
import org.jetbrains.kotlin.resolve.calls.callUtil.isCallableReference
|
||||
import org.jetbrains.kotlin.resolve.calls.context.CallResolutionContext
|
||||
import org.jetbrains.kotlin.resolve.calls.model.ResolvedCall
|
||||
import org.jetbrains.kotlin.resolve.descriptorUtil.fqNameSafe
|
||||
import org.jetbrains.kotlin.resolve.inline.InlineUtil
|
||||
@@ -50,11 +49,28 @@ fun PropertyDescriptor.isBuiltInCoroutineContext(languageVersionSettings: Langua
|
||||
|
||||
private val ALLOWED_SCOPE_KINDS = setOf(LexicalScopeKind.FUNCTION_INNER_SCOPE, LexicalScopeKind.FUNCTION_HEADER_FOR_DESTRUCTURING)
|
||||
|
||||
fun findEnclosingSuspendFunction(context: CallCheckerContext): FunctionDescriptor? = context.scope
|
||||
.parentsWithSelf.firstOrNull {
|
||||
it is LexicalScope && it.kind in ALLOWED_SCOPE_KINDS &&
|
||||
it.ownerDescriptor.safeAs<FunctionDescriptor>()?.isSuspend == true
|
||||
}?.cast<LexicalScope>()?.ownerDescriptor?.cast()
|
||||
fun findEnclosingSuspendFunction(context: CallCheckerContext, checkingCall: KtElement): FunctionDescriptor? {
|
||||
/*
|
||||
* If checking call isn't equal to call in resolution context, we should look at lexical scope from trace.
|
||||
* It means there is a parent function analysis of which isn't completed yet
|
||||
* and their lexical scope in the resolution context isn't recorded yet (but there is lexical scope with not completed descriptor in trace).
|
||||
* Example (suggest that we're analyzing the last expression of lambda now):
|
||||
* fun main() {
|
||||
* runBlocking {
|
||||
* retry { 1 } // `fun main` lexical scope in the resolution context, `runBlocking { ... }` one in the recorded in trace lexical scope
|
||||
* }
|
||||
* }
|
||||
*/
|
||||
val scope = if (context.resolutionContext !is CallResolutionContext<*> || context.resolutionContext.call.callElement == checkingCall) {
|
||||
context.scope
|
||||
} else {
|
||||
context.trace.get(BindingContext.LEXICAL_SCOPE, checkingCall)
|
||||
}
|
||||
|
||||
return scope?.parentsWithSelf?.firstOrNull {
|
||||
it is LexicalScope && it.kind in ALLOWED_SCOPE_KINDS && it.ownerDescriptor.safeAs<FunctionDescriptor>()?.isSuspend == true
|
||||
}?.cast<LexicalScope>()?.ownerDescriptor?.cast()
|
||||
}
|
||||
|
||||
object CoroutineSuspendCallChecker : CallChecker {
|
||||
override fun check(resolvedCall: ResolvedCall<*>, reportOn: PsiElement, context: CallCheckerContext) {
|
||||
@@ -69,12 +85,11 @@ object CoroutineSuspendCallChecker : CallChecker {
|
||||
else -> return
|
||||
}
|
||||
|
||||
val enclosingSuspendFunction = findEnclosingSuspendFunction(context)
|
||||
val callElement = resolvedCall.call.callElement as KtExpression
|
||||
val enclosingSuspendFunction = findEnclosingSuspendFunction(context, callElement)
|
||||
|
||||
when {
|
||||
enclosingSuspendFunction != null -> {
|
||||
val callElement = resolvedCall.call.callElement as KtExpression
|
||||
|
||||
if (!InlineUtil.checkNonLocalReturnUsage(enclosingSuspendFunction, callElement, context.resolutionContext)) {
|
||||
var shouldReport = true
|
||||
|
||||
|
||||
@@ -5,13 +5,16 @@
|
||||
|
||||
package org.jetbrains.kotlin.resolve.calls.inference
|
||||
|
||||
import com.intellij.psi.PsiElement
|
||||
import org.jetbrains.kotlin.builtins.KotlinBuiltIns
|
||||
import org.jetbrains.kotlin.descriptors.CallableDescriptor
|
||||
import org.jetbrains.kotlin.descriptors.ModuleDescriptor
|
||||
import org.jetbrains.kotlin.descriptors.impl.LocalVariableDescriptor
|
||||
import org.jetbrains.kotlin.psi.KtDotQualifiedExpression
|
||||
import org.jetbrains.kotlin.psi.KtDoubleColonExpression
|
||||
import org.jetbrains.kotlin.psi.KtElement
|
||||
import org.jetbrains.kotlin.psi.KtReferenceExpression
|
||||
import org.jetbrains.kotlin.psi.psiUtil.anyDescendantOfType
|
||||
import org.jetbrains.kotlin.psi.psiUtil.getParentOfType
|
||||
import org.jetbrains.kotlin.psi.psiUtil.isAncestor
|
||||
import org.jetbrains.kotlin.resolve.BindingTrace
|
||||
@@ -337,6 +340,19 @@ class CoroutineInferenceSession(
|
||||
deprecationResolver, moduleDescriptor, context.dataFlowValueFactory, typeApproximator, missingSupertypesResolver
|
||||
)
|
||||
}
|
||||
|
||||
/*
|
||||
* It's used only for `+=` resolve to clear calls info before the second analysis of right side.
|
||||
* TODO: remove it after moving `+=` resolve into OR mechanism
|
||||
*/
|
||||
fun clearCallsInfoByContainingElement(containingElement: KtElement) {
|
||||
commonCalls.removeIf remove@{ callInfo ->
|
||||
val atom = callInfo.callResolutionResult.resultCallAtom.atom
|
||||
if (atom !is PSIKotlinCallImpl) return@remove false
|
||||
|
||||
containingElement.anyDescendantOfType<KtElement> { it == atom.psiCall.callElement }
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
class ComposedSubstitutor(val left: NewTypeSubstitutor, val right: NewTypeSubstitutor) : NewTypeSubstitutor {
|
||||
|
||||
@@ -44,7 +44,6 @@ import org.jetbrains.kotlin.storage.getValue
|
||||
import org.jetbrains.kotlin.types.KotlinType
|
||||
import org.jetbrains.kotlin.types.checker.KotlinTypeRefiner
|
||||
import org.jetbrains.kotlin.types.refinement.TypeRefinement
|
||||
import org.jetbrains.kotlin.utils.addToStdlib.flatMapToNullable
|
||||
import java.util.*
|
||||
|
||||
open class LazyClassMemberScope(
|
||||
@@ -67,7 +66,7 @@ open class LazyClassMemberScope(
|
||||
)
|
||||
)
|
||||
result.addAll(computeExtraDescriptors(NoLookupLocation.FOR_ALREADY_TRACKED))
|
||||
result
|
||||
result.toList()
|
||||
}
|
||||
|
||||
override fun getContributedDescriptors(
|
||||
@@ -116,7 +115,6 @@ open class LazyClassMemberScope(
|
||||
by lazy(LazyThreadSafetyMode.PUBLICATION) {
|
||||
mutableSetOf<Name>().apply {
|
||||
addAll(declarationProvider.getDeclarationNames())
|
||||
addAll(c.syntheticResolveExtension.getSyntheticFunctionNames(thisDescriptor))
|
||||
supertypes.flatMapTo(this) {
|
||||
it.memberScope.getFunctionNames()
|
||||
}
|
||||
@@ -125,32 +123,6 @@ open class LazyClassMemberScope(
|
||||
}
|
||||
}
|
||||
|
||||
private val _classifierNames: Set<Name>?
|
||||
by lazy(LazyThreadSafetyMode.PUBLICATION) {
|
||||
mutableSetOf<Name>().apply {
|
||||
supertypes.flatMapToNullable(this) {
|
||||
it.memberScope.getClassifierNames()
|
||||
} ?: return@lazy null
|
||||
|
||||
addAll(declarationProvider.getDeclarationNames())
|
||||
with(c.syntheticResolveExtension) {
|
||||
getSyntheticCompanionObjectNameIfNeeded(thisDescriptor)?.let { add(it) }
|
||||
addAll(getSyntheticNestedClassNames(thisDescriptor))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private val _allNames: Set<Name>?
|
||||
by lazy(LazyThreadSafetyMode.PUBLICATION) {
|
||||
val classifiers = getClassifierNames() ?: return@lazy null
|
||||
|
||||
mutableSetOf<Name>().apply {
|
||||
addAll(getVariableNames())
|
||||
addAll(getFunctionNames())
|
||||
addAll(classifiers)
|
||||
}
|
||||
}
|
||||
|
||||
private fun getDataClassRelatedFunctionNames(): Collection<Name> {
|
||||
val declarations = mutableListOf<DeclarationDescriptor>()
|
||||
addDataClassMethods(declarations, NoLookupLocation.WHEN_GET_ALL_DESCRIPTORS)
|
||||
@@ -159,11 +131,6 @@ open class LazyClassMemberScope(
|
||||
|
||||
override fun getVariableNames() = _variableNames
|
||||
override fun getFunctionNames() = _functionNames
|
||||
override fun getClassifierNames() = _classifierNames
|
||||
|
||||
override fun definitelyDoesNotContainName(name: Name): Boolean {
|
||||
return _allNames?.let { name !in it } ?: false
|
||||
}
|
||||
|
||||
private interface MemberExtractor<out T : CallableMemberDescriptor> {
|
||||
fun extract(extractFrom: KotlinType, name: Name): Collection<T>
|
||||
|
||||
@@ -34,6 +34,7 @@ import org.jetbrains.kotlin.resolve.calls.ArgumentTypeResolver;
|
||||
import org.jetbrains.kotlin.resolve.calls.context.CallPosition;
|
||||
import org.jetbrains.kotlin.resolve.calls.context.ContextDependency;
|
||||
import org.jetbrains.kotlin.resolve.calls.context.TemporaryTraceAndCache;
|
||||
import org.jetbrains.kotlin.resolve.calls.inference.CoroutineInferenceSession;
|
||||
import org.jetbrains.kotlin.resolve.calls.model.ResolvedCall;
|
||||
import org.jetbrains.kotlin.resolve.calls.results.OverloadResolutionResults;
|
||||
import org.jetbrains.kotlin.resolve.calls.results.OverloadResolutionResultsImpl;
|
||||
@@ -245,6 +246,10 @@ public class ExpressionTypingVisitorForStatements extends ExpressionTypingVisito
|
||||
boolean lhsAssignable = basic.checkLValue(ignoreReportsTrace, context, left, right, expression, false);
|
||||
if (assignmentOperationType == null || lhsAssignable) {
|
||||
// Check for '+'
|
||||
// We should clear calls info for coroutine inference within right side as here we analyze it a second time in another context
|
||||
if (context.inferenceSession instanceof CoroutineInferenceSession) {
|
||||
((CoroutineInferenceSession) context.inferenceSession).clearCallsInfoByContainingElement(expression);
|
||||
}
|
||||
Name counterpartName = OperatorConventions.BINARY_OPERATION_NAMES.get(OperatorConventions.ASSIGNMENT_OPERATION_COUNTERPARTS.get(operationType));
|
||||
binaryOperationDescriptors = components.callResolver.resolveBinaryCall(
|
||||
context.replaceTraceAndCache(temporaryForBinaryOperation).replaceScope(scope),
|
||||
|
||||
@@ -17,6 +17,7 @@
|
||||
package org.jetbrains.kotlin.backend.common
|
||||
|
||||
import org.jetbrains.kotlin.descriptors.*
|
||||
import org.jetbrains.kotlin.ir.ObsoleteDescriptorBasedAPI
|
||||
import org.jetbrains.kotlin.ir.IrElement
|
||||
import org.jetbrains.kotlin.ir.declarations.IrClass
|
||||
import org.jetbrains.kotlin.ir.declarations.IrFunction
|
||||
@@ -30,6 +31,7 @@ import java.util.*
|
||||
|
||||
class Closure(val capturedValues: List<ValueDescriptor>)
|
||||
|
||||
@OptIn(ObsoleteDescriptorBasedAPI::class)
|
||||
abstract class AbstractClosureAnnotator : IrElementVisitorVoid {
|
||||
protected abstract fun recordFunctionClosure(functionDescriptor: FunctionDescriptor, closure: Closure)
|
||||
protected abstract fun recordClassClosure(classDescriptor: ClassDescriptor, closure: Closure)
|
||||
|
||||
@@ -18,6 +18,7 @@ package org.jetbrains.kotlin.backend.common
|
||||
|
||||
import org.jetbrains.kotlin.descriptors.CallableMemberDescriptor
|
||||
import org.jetbrains.kotlin.descriptors.Visibilities
|
||||
import org.jetbrains.kotlin.ir.ObsoleteDescriptorBasedAPI
|
||||
import org.jetbrains.kotlin.ir.IrElement
|
||||
import org.jetbrains.kotlin.ir.declarations.*
|
||||
import org.jetbrains.kotlin.ir.descriptors.IrBuiltIns
|
||||
@@ -31,6 +32,7 @@ import org.jetbrains.kotlin.resolve.descriptorUtil.isEffectivelyExternal
|
||||
|
||||
typealias ReportError = (element: IrElement, message: String) -> Unit
|
||||
|
||||
@OptIn(ObsoleteDescriptorBasedAPI::class)
|
||||
class CheckIrElementVisitor(
|
||||
val irBuiltIns: IrBuiltIns,
|
||||
val reportError: ReportError,
|
||||
|
||||
@@ -17,7 +17,7 @@
|
||||
package org.jetbrains.kotlin.backend.common
|
||||
|
||||
import org.jetbrains.kotlin.descriptors.VariableDescriptor
|
||||
import org.jetbrains.kotlin.descriptors.impl.LocalVariableDescriptor
|
||||
import org.jetbrains.kotlin.ir.ObsoleteDescriptorBasedAPI
|
||||
import org.jetbrains.kotlin.ir.IrElement
|
||||
import org.jetbrains.kotlin.ir.declarations.IrVariable
|
||||
import org.jetbrains.kotlin.ir.descriptors.WrappedVariableDescriptor
|
||||
@@ -29,6 +29,7 @@ import org.jetbrains.kotlin.ir.util.DescriptorsRemapper
|
||||
import org.jetbrains.kotlin.ir.visitors.acceptVoid
|
||||
|
||||
@Suppress("UNCHECKED_CAST")
|
||||
@OptIn(ObsoleteDescriptorBasedAPI::class)
|
||||
fun <T : IrElement> T.deepCopyWithVariables(): T {
|
||||
val descriptorsRemapper = object : DescriptorsRemapper {
|
||||
override fun remapDeclaredVariable(descriptor: VariableDescriptor) = WrappedVariableDescriptor()
|
||||
|
||||
@@ -6,6 +6,7 @@
|
||||
package org.jetbrains.kotlin.backend.common
|
||||
|
||||
import org.jetbrains.kotlin.descriptors.*
|
||||
import org.jetbrains.kotlin.ir.ObsoleteDescriptorBasedAPI
|
||||
import org.jetbrains.kotlin.ir.IrElement
|
||||
import org.jetbrains.kotlin.ir.declarations.*
|
||||
import org.jetbrains.kotlin.ir.descriptors.*
|
||||
@@ -50,6 +51,7 @@ object DescriptorsToIrRemapper : DescriptorsRemapper {
|
||||
WrappedValueParameterDescriptor(descriptor.annotations, descriptor.source)
|
||||
}
|
||||
|
||||
@OptIn(ObsoleteDescriptorBasedAPI::class)
|
||||
object WrappedDescriptorPatcher : IrElementVisitorVoid {
|
||||
override fun visitElement(element: IrElement) {
|
||||
element.acceptChildrenVoid(this)
|
||||
|
||||
@@ -16,6 +16,7 @@
|
||||
|
||||
package org.jetbrains.kotlin.backend.common
|
||||
|
||||
import org.jetbrains.kotlin.ir.ObsoleteDescriptorBasedAPI
|
||||
import org.jetbrains.kotlin.ir.IrElement
|
||||
import org.jetbrains.kotlin.ir.IrStatement
|
||||
import org.jetbrains.kotlin.ir.builders.Scope
|
||||
@@ -101,6 +102,7 @@ abstract class IrElementTransformerVoidWithContext : IrElementTransformerVoid()
|
||||
protected val allScopes get() = scopeStack
|
||||
protected val currentDeclarationParent get() = scopeStack.lastOrNull { it.irElement is IrDeclarationParent }?.irElement as? IrDeclarationParent
|
||||
|
||||
@ObsoleteDescriptorBasedAPI
|
||||
fun printScopeStack() {
|
||||
scopeStack.forEach { println(it.scope.scopeOwner) }
|
||||
}
|
||||
@@ -138,6 +140,7 @@ abstract class IrElementTransformerVoidWithContext : IrElementTransformerVoid()
|
||||
}
|
||||
}
|
||||
|
||||
@OptIn(ObsoleteDescriptorBasedAPI::class)
|
||||
abstract class IrElementVisitorVoidWithContext : IrElementVisitorVoid {
|
||||
|
||||
private val scopeStack = mutableListOf<ScopeWithIr>()
|
||||
@@ -198,6 +201,7 @@ abstract class IrElementVisitorVoidWithContext : IrElementVisitorVoid {
|
||||
protected val parentScope get() = if (scopeStack.size < 2) null else scopeStack[scopeStack.size - 2]
|
||||
protected val allScopes get() = scopeStack
|
||||
|
||||
@ObsoleteDescriptorBasedAPI
|
||||
fun printScopeStack() {
|
||||
scopeStack.forEach { println(it.scope.scopeOwner) }
|
||||
}
|
||||
|
||||
@@ -107,11 +107,11 @@ object CheckDeclarationParentsVisitor : IrElementVisitor<Unit, IrDeclarationPare
|
||||
val parent = try {
|
||||
declaration.parent
|
||||
} catch (e: Throwable) {
|
||||
error("$declaration for ${declaration.descriptor} has no parent")
|
||||
error("$declaration for ${declaration.render()} has no parent")
|
||||
}
|
||||
|
||||
if (parent != expectedParent) {
|
||||
error("$declaration for ${declaration.descriptor} has unexpected parent $parent")
|
||||
error("$declaration for ${declaration.render()} has unexpected parent $parent")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -16,6 +16,7 @@
|
||||
|
||||
package org.jetbrains.kotlin.backend.common
|
||||
|
||||
import org.jetbrains.kotlin.ir.ObsoleteDescriptorBasedAPI
|
||||
import org.jetbrains.kotlin.ir.IrElement
|
||||
import org.jetbrains.kotlin.ir.declarations.IrClass
|
||||
import org.jetbrains.kotlin.ir.declarations.IrFunction
|
||||
@@ -34,6 +35,7 @@ import org.jetbrains.kotlin.ir.visitors.IrElementVisitor
|
||||
* It is also not guaranteed that each returned call is detected as tail recursion by the frontend.
|
||||
* However any returned call can be correctly optimized as tail recursion.
|
||||
*/
|
||||
@OptIn(ObsoleteDescriptorBasedAPI::class)
|
||||
fun collectTailRecursionCalls(irFunction: IrFunction): Set<IrCall> {
|
||||
if ((irFunction as? IrSimpleFunction)?.isTailrec != true) {
|
||||
return emptySet()
|
||||
|
||||
@@ -12,6 +12,7 @@ import org.jetbrains.kotlin.descriptors.ClassDescriptor
|
||||
import org.jetbrains.kotlin.descriptors.SimpleFunctionDescriptor
|
||||
import org.jetbrains.kotlin.descriptors.findClassAcrossModuleDependencies
|
||||
import org.jetbrains.kotlin.incremental.components.NoLookupLocation
|
||||
import org.jetbrains.kotlin.ir.ObsoleteDescriptorBasedAPI
|
||||
import org.jetbrains.kotlin.ir.declarations.IrFunction
|
||||
import org.jetbrains.kotlin.ir.declarations.IrModuleFragment
|
||||
import org.jetbrains.kotlin.ir.declarations.IrPackageFragment
|
||||
@@ -109,6 +110,8 @@ open class BuiltinSymbolsBase(protected val irBuiltIns: IrBuiltIns, protected va
|
||||
val intProgression = progression("IntProgression")
|
||||
val longProgression = progression("LongProgression")
|
||||
val progressionClasses = listOfNotNull(charProgression, intProgression, longProgression, uIntProgression, uLongProgression)
|
||||
|
||||
@ObsoleteDescriptorBasedAPI
|
||||
val progressionClassesTypes = progressionClasses.map { it.descriptor.defaultType }.toSet()
|
||||
|
||||
val getProgressionLastElementByReturnType = builtInsPackage("kotlin", "internal")
|
||||
@@ -143,6 +146,8 @@ open class BuiltinSymbolsBase(protected val irBuiltIns: IrBuiltIns, protected va
|
||||
val long = symbolTable.referenceClass(builtIns.long)
|
||||
|
||||
val integerClasses = listOf(byte, short, int, long)
|
||||
|
||||
@ObsoleteDescriptorBasedAPI
|
||||
val integerClassesTypes = integerClasses.map { it.descriptor.defaultType }
|
||||
|
||||
val arrayOf = getSimpleFunction(Name.identifier("arrayOf")) {
|
||||
|
||||
@@ -6,6 +6,7 @@
|
||||
package org.jetbrains.kotlin.backend.common.ir
|
||||
|
||||
import org.jetbrains.kotlin.backend.common.lower.VariableRemapper
|
||||
import org.jetbrains.kotlin.ir.ObsoleteDescriptorBasedAPI
|
||||
import org.jetbrains.kotlin.ir.IrStatement
|
||||
import org.jetbrains.kotlin.ir.declarations.*
|
||||
import org.jetbrains.kotlin.ir.expressions.*
|
||||
@@ -86,6 +87,7 @@ private fun IrBody.move(
|
||||
|
||||
// TODO use a generic inliner (e.g. JS/Native's FunctionInlining.Inliner)
|
||||
// Inline simple function calls without type parameters, default parameters, or varargs.
|
||||
@OptIn(ObsoleteDescriptorBasedAPI::class)
|
||||
fun IrFunction.inline(target: IrDeclarationParent, arguments: List<IrValueDeclaration> = listOf()): IrReturnableBlock =
|
||||
IrReturnableBlockImpl(startOffset, endOffset, returnType, IrReturnableBlockSymbolImpl(descriptor), null, symbol).apply {
|
||||
statements += body!!.move(this@inline, target, symbol, valueParameters.zip(arguments).toMap()).statements
|
||||
|
||||
@@ -12,6 +12,7 @@ import org.jetbrains.kotlin.descriptors.Modality
|
||||
import org.jetbrains.kotlin.descriptors.Visibilities
|
||||
import org.jetbrains.kotlin.descriptors.Visibility
|
||||
import org.jetbrains.kotlin.descriptors.annotations.Annotations
|
||||
import org.jetbrains.kotlin.ir.ObsoleteDescriptorBasedAPI
|
||||
import org.jetbrains.kotlin.ir.IrElement
|
||||
import org.jetbrains.kotlin.ir.UNDEFINED_OFFSET
|
||||
import org.jetbrains.kotlin.ir.builders.Scope
|
||||
@@ -130,6 +131,7 @@ fun IrCall.getAnnotationClass(): IrClass {
|
||||
|
||||
val IrTypeParametersContainer.classIfConstructor get() = if (this is IrConstructor) parentAsClass else this
|
||||
|
||||
@OptIn(ObsoleteDescriptorBasedAPI::class)
|
||||
fun IrValueParameter.copyTo(
|
||||
irFunction: IrFunction,
|
||||
origin: IrDeclarationOrigin = this.origin,
|
||||
@@ -172,6 +174,7 @@ fun IrValueParameter.copyTo(
|
||||
}
|
||||
}
|
||||
|
||||
@OptIn(ObsoleteDescriptorBasedAPI::class)
|
||||
fun IrTypeParameter.copyToWithoutSuperTypes(
|
||||
target: IrTypeParametersContainer,
|
||||
index: Int = this.index,
|
||||
@@ -185,6 +188,7 @@ fun IrTypeParameter.copyToWithoutSuperTypes(
|
||||
}
|
||||
}
|
||||
|
||||
@OptIn(ObsoleteDescriptorBasedAPI::class)
|
||||
fun IrFunction.copyReceiverParametersFrom(from: IrFunction) {
|
||||
dispatchReceiverParameter = from.dispatchReceiverParameter?.let {
|
||||
IrValueParameterImpl(it.startOffset, it.endOffset, it.origin, it.descriptor, it.type, it.varargElementType).also {
|
||||
@@ -457,6 +461,7 @@ fun IrClass.createParameterDeclarations() {
|
||||
}
|
||||
}
|
||||
|
||||
@OptIn(ObsoleteDescriptorBasedAPI::class)
|
||||
fun IrFunction.createDispatchReceiverParameter(origin: IrDeclarationOrigin? = null) {
|
||||
assert(dispatchReceiverParameter == null)
|
||||
|
||||
@@ -479,7 +484,7 @@ val IrFunction.allParameters: List<IrValueParameter>
|
||||
get() = if (this is IrConstructor) {
|
||||
listOf(
|
||||
this.constructedClass.thisReceiver
|
||||
?: error(this.descriptor)
|
||||
?: error(this.render())
|
||||
) + explicitParameters
|
||||
} else {
|
||||
explicitParameters
|
||||
@@ -548,6 +553,7 @@ fun IrClass.addFakeOverridesViaIncorrectHeuristic(implementedMembers: List<IrSim
|
||||
}
|
||||
}
|
||||
|
||||
@OptIn(ObsoleteDescriptorBasedAPI::class)
|
||||
fun createStaticFunctionWithReceivers(
|
||||
irParent: IrDeclarationParent,
|
||||
name: Name,
|
||||
|
||||
@@ -10,6 +10,7 @@ import org.jetbrains.kotlin.backend.common.ir.*
|
||||
import org.jetbrains.kotlin.descriptors.ClassKind
|
||||
import org.jetbrains.kotlin.descriptors.Modality
|
||||
import org.jetbrains.kotlin.descriptors.Visibilities
|
||||
import org.jetbrains.kotlin.ir.ObsoleteDescriptorBasedAPI
|
||||
import org.jetbrains.kotlin.ir.IrElement
|
||||
import org.jetbrains.kotlin.ir.builders.*
|
||||
import org.jetbrains.kotlin.ir.declarations.*
|
||||
@@ -38,6 +39,7 @@ import org.jetbrains.kotlin.ir.util.*
|
||||
import org.jetbrains.kotlin.ir.visitors.*
|
||||
import org.jetbrains.kotlin.name.Name
|
||||
|
||||
@ObsoleteDescriptorBasedAPI
|
||||
abstract class AbstractSuspendFunctionsLowering<C : CommonBackendContext>(val context: C) : FileLoweringPass {
|
||||
|
||||
protected object STATEMENT_ORIGIN_COROUTINE_IMPL : IrStatementOriginImpl("COROUTINE_IMPL")
|
||||
@@ -679,8 +681,7 @@ abstract class AbstractSuspendFunctionsLowering<C : CommonBackendContext>(val co
|
||||
Visibilities.PRIVATE,
|
||||
isFinal = !isMutable,
|
||||
isExternal = false,
|
||||
isStatic = false,
|
||||
isFakeOverride = false
|
||||
isStatic = false
|
||||
).also {
|
||||
descriptor.bind(it)
|
||||
it.parent = this
|
||||
|
||||
@@ -11,6 +11,7 @@ import org.jetbrains.kotlin.backend.common.ir.*
|
||||
import org.jetbrains.kotlin.descriptors.Modality
|
||||
import org.jetbrains.kotlin.descriptors.Visibilities
|
||||
import org.jetbrains.kotlin.descriptors.Visibility
|
||||
import org.jetbrains.kotlin.ir.ObsoleteDescriptorBasedAPI
|
||||
import org.jetbrains.kotlin.ir.UNDEFINED_OFFSET
|
||||
import org.jetbrains.kotlin.ir.builders.*
|
||||
import org.jetbrains.kotlin.ir.builders.declarations.addValueParameter
|
||||
@@ -53,10 +54,15 @@ open class DefaultArgumentStubGenerator(
|
||||
}
|
||||
|
||||
private fun lower(irFunction: IrFunction): List<IrFunction>? {
|
||||
val visibility = defaultArgumentStubVisibility(irFunction)
|
||||
val newIrFunction =
|
||||
irFunction.generateDefaultsFunction(context, skipInlineMethods, skipExternalMethods, forceSetOverrideSymbols, visibility)
|
||||
?: return null
|
||||
irFunction.generateDefaultsFunction(
|
||||
context,
|
||||
skipInlineMethods,
|
||||
skipExternalMethods,
|
||||
forceSetOverrideSymbols,
|
||||
defaultArgumentStubVisibility(irFunction),
|
||||
useConstructorMarker(irFunction)
|
||||
) ?: return null
|
||||
if (newIrFunction.isFakeOverride) {
|
||||
return listOf(irFunction, newIrFunction)
|
||||
}
|
||||
@@ -185,7 +191,8 @@ open class DefaultArgumentStubGenerator(
|
||||
|
||||
protected open fun IrBlockBodyBuilder.generateSuperCallHandlerCheckIfNeeded(
|
||||
irFunction: IrFunction,
|
||||
newIrFunction: IrFunction) {
|
||||
newIrFunction: IrFunction
|
||||
) {
|
||||
//NO-OP Stub
|
||||
}
|
||||
|
||||
@@ -202,6 +209,8 @@ open class DefaultArgumentStubGenerator(
|
||||
|
||||
protected open fun defaultArgumentStubVisibility(function: IrFunction) = Visibilities.PUBLIC
|
||||
|
||||
protected open fun useConstructorMarker(function: IrFunction) = function is IrConstructor
|
||||
|
||||
private fun log(msg: () -> String) = context.log { "DEFAULT-REPLACER: ${msg()}" }
|
||||
}
|
||||
|
||||
@@ -274,7 +283,11 @@ open class DefaultParameterInjector(
|
||||
expression.transformChildrenVoid()
|
||||
return visitFunctionAccessExpression(expression) {
|
||||
with(expression) {
|
||||
IrDelegatingConstructorCallImpl(startOffset, endOffset, type, it as IrConstructorSymbol, typeArgumentsCount)
|
||||
IrDelegatingConstructorCallImpl(
|
||||
startOffset, endOffset, type, it as IrConstructorSymbol,
|
||||
typeArgumentsCount = typeArgumentsCount,
|
||||
valueArgumentsCount = it.owner.valueParameters.size
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -292,7 +305,11 @@ open class DefaultParameterInjector(
|
||||
expression.transformChildrenVoid()
|
||||
return visitFunctionAccessExpression(expression) {
|
||||
with(expression) {
|
||||
IrEnumConstructorCallImpl(startOffset, endOffset, type, it as IrConstructorSymbol)
|
||||
IrEnumConstructorCallImpl(
|
||||
startOffset, endOffset, type, it as IrConstructorSymbol,
|
||||
typeArgumentsCount = typeArgumentsCount,
|
||||
valueArgumentsCount = it.owner.valueParameters.size
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -301,7 +318,13 @@ open class DefaultParameterInjector(
|
||||
expression.transformChildrenVoid()
|
||||
return visitFunctionAccessExpression(expression) {
|
||||
with(expression) {
|
||||
IrCallImpl(startOffset, endOffset, type, it, typeArgumentsCount, DEFAULT_DISPATCH_CALL, superQualifierSymbol)
|
||||
IrCallImpl(
|
||||
startOffset, endOffset, type, it,
|
||||
typeArgumentsCount = typeArgumentsCount,
|
||||
valueArgumentsCount = it.owner.valueParameters.size,
|
||||
origin = DEFAULT_DISPATCH_CALL,
|
||||
superQualifierSymbol = superQualifierSymbol
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -310,15 +333,20 @@ open class DefaultParameterInjector(
|
||||
val startOffset = expression.startOffset
|
||||
val endOffset = expression.endOffset
|
||||
val declaration = expression.symbol.owner
|
||||
val visibility = defaultArgumentStubVisibility(declaration)
|
||||
|
||||
// We *have* to find the actual function here since on the JVM, a default stub for a function implemented
|
||||
// in an interface does not leave an abstract method after being moved to DefaultImpls (see InterfaceLowering).
|
||||
// Calling the fake override on an implementation of that interface would then result in a call to a method
|
||||
// that does not actually exist as DefaultImpls is not part of the inheritance hierarchy.
|
||||
val stubFunction = declaration.findBaseFunctionWithDefaultArguments(skipInline, skipExternalMethods)
|
||||
?.generateDefaultsFunction(context, skipInline, skipExternalMethods, forceSetOverrideSymbols, visibility)
|
||||
?: return null
|
||||
?.generateDefaultsFunction(
|
||||
context,
|
||||
skipInline,
|
||||
skipExternalMethods,
|
||||
forceSetOverrideSymbols,
|
||||
defaultArgumentStubVisibility(declaration),
|
||||
useConstructorMarker(declaration)
|
||||
) ?: return null
|
||||
|
||||
log { "$declaration -> $stubFunction" }
|
||||
|
||||
@@ -367,6 +395,8 @@ open class DefaultParameterInjector(
|
||||
|
||||
protected open fun defaultArgumentStubVisibility(function: IrFunction) = Visibilities.PUBLIC
|
||||
|
||||
protected open fun useConstructorMarker(function: IrFunction) = function is IrConstructor
|
||||
|
||||
private fun log(msg: () -> String) = context.log { "DEFAULT-INJECTOR: ${msg()}" }
|
||||
}
|
||||
|
||||
@@ -416,7 +446,8 @@ private fun IrFunction.generateDefaultsFunction(
|
||||
skipInlineMethods: Boolean,
|
||||
skipExternalMethods: Boolean,
|
||||
forceSetOverrideSymbols: Boolean,
|
||||
visibility: Visibility
|
||||
visibility: Visibility,
|
||||
useConstructorMarker: Boolean
|
||||
): IrFunction? {
|
||||
if (skipInlineMethods && isInline) return null
|
||||
if (skipExternalMethods && isExternalOrInheritedFromExternal()) return null
|
||||
@@ -425,7 +456,7 @@ private fun IrFunction.generateDefaultsFunction(
|
||||
if (this is IrSimpleFunction) {
|
||||
// If this is an override of a function with default arguments, produce a fake override of a default stub.
|
||||
if (overriddenSymbols.any { it.owner.findBaseFunctionWithDefaultArguments(skipInlineMethods, skipExternalMethods) != null })
|
||||
return generateDefaultsFunctionImpl(context, IrDeclarationOrigin.FAKE_OVERRIDE, visibility, isFakeOverride = true).also {
|
||||
return generateDefaultsFunctionImpl(context, IrDeclarationOrigin.FAKE_OVERRIDE, visibility, true, useConstructorMarker).also {
|
||||
context.mapping.defaultArgumentsDispatchFunction[this] = it
|
||||
context.mapping.defaultArgumentsOriginalFunction[it] = this
|
||||
|
||||
@@ -436,7 +467,8 @@ private fun IrFunction.generateDefaultsFunction(
|
||||
skipInlineMethods,
|
||||
skipExternalMethods,
|
||||
forceSetOverrideSymbols,
|
||||
visibility
|
||||
visibility,
|
||||
useConstructorMarker
|
||||
)?.symbol as IrSimpleFunctionSymbol?
|
||||
}
|
||||
}
|
||||
@@ -454,7 +486,7 @@ private fun IrFunction.generateDefaultsFunction(
|
||||
// binaries, it's way too late to fix it. Hence the workaround.
|
||||
if (valueParameters.any { it.defaultValue != null }) {
|
||||
return generateDefaultsFunctionImpl(
|
||||
context, IrDeclarationOrigin.FUNCTION_FOR_DEFAULT_PARAMETER, visibility, isFakeOverride = false
|
||||
context, IrDeclarationOrigin.FUNCTION_FOR_DEFAULT_PARAMETER, visibility, false, useConstructorMarker
|
||||
).also {
|
||||
context.mapping.defaultArgumentsDispatchFunction[this] = it
|
||||
context.mapping.defaultArgumentsOriginalFunction[it] = this
|
||||
@@ -463,11 +495,13 @@ private fun IrFunction.generateDefaultsFunction(
|
||||
return null
|
||||
}
|
||||
|
||||
@OptIn(ObsoleteDescriptorBasedAPI::class)
|
||||
private fun IrFunction.generateDefaultsFunctionImpl(
|
||||
context: CommonBackendContext,
|
||||
newOrigin: IrDeclarationOrigin,
|
||||
newVisibility: Visibility,
|
||||
isFakeOverride: Boolean
|
||||
isFakeOverride: Boolean,
|
||||
useConstructorMarker: Boolean
|
||||
): IrFunction {
|
||||
val newFunction = when (this) {
|
||||
is IrConstructor ->
|
||||
@@ -515,7 +549,7 @@ private fun IrFunction.generateDefaultsFunctionImpl(
|
||||
for (i in 0 until (valueParameters.size + 31) / 32) {
|
||||
newFunction.addValueParameter("mask$i".synthesizedString, context.irBuiltIns.intType, IrDeclarationOrigin.MASK_FOR_DEFAULT_FUNCTION)
|
||||
}
|
||||
if (this is IrConstructor) {
|
||||
if (useConstructorMarker) {
|
||||
val markerType = context.ir.symbols.defaultConstructorMarker.defaultType.makeNullable()
|
||||
newFunction.addValueParameter("marker".synthesizedString, markerType, IrDeclarationOrigin.DEFAULT_CONSTRUCTOR_MARKER)
|
||||
} else if (context.ir.shouldGenerateHandlerParameterForDefaultBodyFun()) {
|
||||
|
||||
@@ -102,7 +102,12 @@ open class EnumWhenLowering(protected val context: CommonBackendContext) : IrEle
|
||||
else -> return super.visitCall(expression)
|
||||
}
|
||||
val subjectOrdinal = topmostOrdinalProvider.value
|
||||
return IrCallImpl(expression.startOffset, expression.endOffset, expression.type, expression.symbol).apply {
|
||||
return IrCallImpl(
|
||||
expression.startOffset, expression.endOffset,
|
||||
expression.type, expression.symbol,
|
||||
typeArgumentsCount = 0,
|
||||
valueArgumentsCount = 2
|
||||
).apply {
|
||||
putValueArgument(0, IrGetValueImpl(lhs.startOffset, lhs.endOffset, subjectOrdinal.type, subjectOrdinal.symbol))
|
||||
putValueArgument(1, IrConstImpl.int(rhs.startOffset, rhs.endOffset, context.irBuiltIns.intType, entryOrdinal))
|
||||
}
|
||||
|
||||
@@ -17,13 +17,11 @@ import org.jetbrains.kotlin.ir.symbols.IrConstructorSymbol
|
||||
import org.jetbrains.kotlin.ir.symbols.IrValueParameterSymbol
|
||||
import org.jetbrains.kotlin.ir.symbols.IrValueSymbol
|
||||
import org.jetbrains.kotlin.ir.types.classOrNull
|
||||
import org.jetbrains.kotlin.ir.util.deepCopyWithSymbols
|
||||
import org.jetbrains.kotlin.ir.util.dump
|
||||
import org.jetbrains.kotlin.ir.util.parentAsClass
|
||||
import org.jetbrains.kotlin.ir.util.patchDeclarationParents
|
||||
import org.jetbrains.kotlin.ir.visitors.IrElementTransformerVoid
|
||||
import org.jetbrains.kotlin.ir.visitors.transformChildrenVoid
|
||||
import org.jetbrains.kotlin.utils.addToStdlib.cast
|
||||
|
||||
class InnerClassesLowering(val context: BackendContext) : DeclarationTransformer {
|
||||
|
||||
@@ -225,7 +223,9 @@ class InnerClassConstructorCallsLowering(val context: BackendContext) : BodyLowe
|
||||
|
||||
val newCallee = context.declarationFactory.getInnerClassConstructorWithOuterThisParameter(classConstructor)
|
||||
val newCall = IrDelegatingConstructorCallImpl(
|
||||
expression.startOffset, expression.endOffset, context.irBuiltIns.unitType, newCallee.symbol, expression.typeArgumentsCount
|
||||
expression.startOffset, expression.endOffset, context.irBuiltIns.unitType, newCallee.symbol,
|
||||
typeArgumentsCount = expression.typeArgumentsCount,
|
||||
valueArgumentsCount = newCallee.valueParameters.size
|
||||
).apply { copyTypeArgumentsFrom(expression) }
|
||||
|
||||
newCall.putValueArgument(0, dispatchReceiver)
|
||||
@@ -258,9 +258,10 @@ class InnerClassConstructorCallsLowering(val context: BackendContext) : BodyLowe
|
||||
endOffset,
|
||||
type,
|
||||
newCallee.symbol,
|
||||
typeArgumentsCount,
|
||||
newReflectionTarget?.symbol,
|
||||
origin
|
||||
typeArgumentsCount = typeArgumentsCount,
|
||||
valueArgumentsCount = newCallee.valueParameters.size,
|
||||
reflectionTarget = newReflectionTarget?.symbol,
|
||||
origin = origin
|
||||
)
|
||||
}
|
||||
|
||||
|
||||
@@ -12,6 +12,7 @@ import org.jetbrains.kotlin.descriptors.Modality
|
||||
import org.jetbrains.kotlin.descriptors.ReceiverParameterDescriptor
|
||||
import org.jetbrains.kotlin.descriptors.Visibilities
|
||||
import org.jetbrains.kotlin.descriptors.Visibility
|
||||
import org.jetbrains.kotlin.ir.ObsoleteDescriptorBasedAPI
|
||||
import org.jetbrains.kotlin.ir.IrElement
|
||||
import org.jetbrains.kotlin.ir.IrStatement
|
||||
import org.jetbrains.kotlin.ir.UNDEFINED_OFFSET
|
||||
@@ -47,7 +48,6 @@ import org.jetbrains.kotlin.ir.visitors.acceptChildrenVoid
|
||||
import org.jetbrains.kotlin.ir.visitors.acceptVoid
|
||||
import org.jetbrains.kotlin.ir.visitors.transformChildrenVoid
|
||||
import org.jetbrains.kotlin.name.Name
|
||||
import org.jetbrains.kotlin.utils.addToStdlib.safeAs
|
||||
import java.util.*
|
||||
|
||||
interface LocalNameProvider {
|
||||
@@ -229,6 +229,7 @@ class LocalDeclarationsLowering(
|
||||
abbreviation.annotations
|
||||
)
|
||||
|
||||
@OptIn(ObsoleteDescriptorBasedAPI::class)
|
||||
private inner class LocalDeclarationsTransformer(
|
||||
val irElement: IrElement, val container: IrDeclaration, val classesToLower: Set<IrClass>?
|
||||
) {
|
||||
@@ -358,7 +359,8 @@ class LocalDeclarationsLowering(
|
||||
expression.startOffset, expression.endOffset,
|
||||
context.irBuiltIns.unitType,
|
||||
newCallee.symbol,
|
||||
expression.typeArgumentsCount
|
||||
typeArgumentsCount = expression.typeArgumentsCount,
|
||||
valueArgumentsCount = newCallee.valueParameters.size
|
||||
).also {
|
||||
it.fillArguments2(expression, newCallee)
|
||||
it.copyTypeArgumentsFrom(expression)
|
||||
@@ -416,9 +418,10 @@ class LocalDeclarationsLowering(
|
||||
expression.startOffset, expression.endOffset,
|
||||
expression.type, // TODO functional type for transformed descriptor
|
||||
newCallee.symbol,
|
||||
newCallee.typeParameters.size,
|
||||
newReflectionTarget?.symbol,
|
||||
expression.origin
|
||||
typeArgumentsCount = newCallee.typeParameters.size,
|
||||
valueArgumentsCount = newCallee.valueParameters.size,
|
||||
reflectionTarget = newReflectionTarget?.symbol,
|
||||
origin = expression.origin
|
||||
).also {
|
||||
it.fillArguments2(expression, newCallee)
|
||||
it.setLocalTypeArguments(oldCallee)
|
||||
@@ -519,9 +522,10 @@ class LocalDeclarationsLowering(
|
||||
oldCall.startOffset, oldCall.endOffset,
|
||||
newCallee.returnType,
|
||||
newCallee.symbol,
|
||||
newCallee.typeParameters.size,
|
||||
oldCall.origin,
|
||||
oldCall.superQualifierSymbol
|
||||
typeArgumentsCount = newCallee.typeParameters.size,
|
||||
valueArgumentsCount = newCallee.valueParameters.size,
|
||||
origin = oldCall.origin,
|
||||
superQualifierSymbol = oldCall.superQualifierSymbol
|
||||
).also {
|
||||
it.setLocalTypeArguments(oldCall.symbol.owner)
|
||||
it.copyTypeArgumentsFrom(oldCall, shift = newCallee.typeParameters.size - oldCall.typeArgumentsCount)
|
||||
@@ -771,8 +775,7 @@ class LocalDeclarationsLowering(
|
||||
visibility,
|
||||
isFinal = true,
|
||||
isExternal = false,
|
||||
isStatic = false,
|
||||
isFakeOverride = false
|
||||
isStatic = false
|
||||
).also {
|
||||
descriptor.bind(it)
|
||||
it.parent = parent
|
||||
|
||||
@@ -19,6 +19,7 @@ package org.jetbrains.kotlin.backend.common.lower
|
||||
import org.jetbrains.kotlin.backend.common.BackendContext
|
||||
import org.jetbrains.kotlin.descriptors.*
|
||||
import org.jetbrains.kotlin.descriptors.impl.ValueParameterDescriptorImpl
|
||||
import org.jetbrains.kotlin.ir.ObsoleteDescriptorBasedAPI
|
||||
import org.jetbrains.kotlin.ir.IrElement
|
||||
import org.jetbrains.kotlin.ir.IrStatement
|
||||
import org.jetbrains.kotlin.ir.UNDEFINED_OFFSET
|
||||
@@ -63,6 +64,7 @@ open class VariableRemapper(val mapping: Map<IrValueParameter, IrValueDeclaratio
|
||||
mapping[value]
|
||||
}
|
||||
|
||||
@ObsoleteDescriptorBasedAPI
|
||||
class VariableRemapperDesc(val mapping: Map<ValueDescriptor, IrValueParameter>) : AbstractVariableRemapper() {
|
||||
override fun remapVariable(value: IrValueDeclaration): IrValueDeclaration? =
|
||||
mapping[value.descriptor]
|
||||
@@ -158,6 +160,7 @@ open class IrBuildingTransformer(private val context: BackendContext) : IrElemen
|
||||
}
|
||||
}
|
||||
|
||||
@OptIn(ObsoleteDescriptorBasedAPI::class)
|
||||
fun IrConstructor.callsSuper(irBuiltIns: IrBuiltIns): Boolean {
|
||||
val constructedClass = parent as IrClass
|
||||
val superClass = constructedClass.superTypes
|
||||
|
||||
@@ -42,6 +42,7 @@ class ProvisionalFunctionExpressionLowering :
|
||||
startOffset, endOffset, type,
|
||||
function.symbol,
|
||||
typeArgumentsCount = 0,
|
||||
valueArgumentsCount = function.valueParameters.size,
|
||||
reflectionTarget = null,
|
||||
origin = origin
|
||||
)
|
||||
|
||||
@@ -11,6 +11,7 @@ import org.jetbrains.kotlin.backend.common.ir.Symbols
|
||||
import org.jetbrains.kotlin.backend.common.ir.createTemporaryVariableWithWrappedDescriptor
|
||||
import org.jetbrains.kotlin.backend.common.lower.createIrBuilder
|
||||
import org.jetbrains.kotlin.config.languageVersionSettings
|
||||
import org.jetbrains.kotlin.ir.ObsoleteDescriptorBasedAPI
|
||||
import org.jetbrains.kotlin.ir.IrElement
|
||||
import org.jetbrains.kotlin.ir.IrStatement
|
||||
import org.jetbrains.kotlin.ir.UNDEFINED_OFFSET
|
||||
@@ -36,6 +37,7 @@ interface InlineFunctionResolver {
|
||||
fun getFunctionDeclaration(symbol: IrFunctionSymbol): IrFunction
|
||||
}
|
||||
|
||||
@OptIn(ObsoleteDescriptorBasedAPI::class)
|
||||
open class DefaultInlineFunctionResolver(open val context: CommonBackendContext) : InlineFunctionResolver {
|
||||
override fun getFunctionDeclaration(symbol: IrFunctionSymbol): IrFunction {
|
||||
val descriptor = symbol.descriptor.original
|
||||
@@ -56,6 +58,7 @@ open class DefaultInlineFunctionResolver(open val context: CommonBackendContext)
|
||||
}
|
||||
}
|
||||
|
||||
@OptIn(ObsoleteDescriptorBasedAPI::class)
|
||||
class FunctionInlining(
|
||||
val context: CommonBackendContext,
|
||||
val inlineFunctionResolver: InlineFunctionResolver
|
||||
@@ -164,10 +167,6 @@ class FunctionInlining(
|
||||
statements.transform { it.transform(transformer, data = null) }
|
||||
statements.addAll(0, evaluationStatements)
|
||||
|
||||
val isCoroutineIntrinsicCall = callSite.symbol.descriptor.isBuiltInSuspendCoroutineUninterceptedOrReturn(
|
||||
context.configuration.languageVersionSettings
|
||||
)
|
||||
|
||||
return IrReturnableBlockImpl(
|
||||
startOffset = callSite.startOffset,
|
||||
endOffset = callSite.endOffset,
|
||||
@@ -414,7 +413,7 @@ class FunctionInlining(
|
||||
}
|
||||
|
||||
else -> {
|
||||
val message = "Incomplete expression: call to ${callee.descriptor} " +
|
||||
val message = "Incomplete expression: call to ${callee.render()} " +
|
||||
"has no argument at index ${parameter.index}"
|
||||
throw Error(message)
|
||||
}
|
||||
|
||||
@@ -12,6 +12,7 @@ import org.jetbrains.kotlin.backend.common.lower.matchers.Quantifier
|
||||
import org.jetbrains.kotlin.backend.common.lower.matchers.SimpleCalleeMatcher
|
||||
import org.jetbrains.kotlin.backend.common.lower.matchers.createIrCallMatcher
|
||||
import org.jetbrains.kotlin.backend.common.lower.matchers.singleArgumentExtension
|
||||
import org.jetbrains.kotlin.ir.ObsoleteDescriptorBasedAPI
|
||||
import org.jetbrains.kotlin.ir.builders.*
|
||||
import org.jetbrains.kotlin.ir.declarations.IrSimpleFunction
|
||||
import org.jetbrains.kotlin.ir.declarations.IrVariable
|
||||
@@ -555,6 +556,7 @@ internal class CharSequenceIndicesHandler(context: CommonBackendContext) : Indic
|
||||
}
|
||||
|
||||
/** Builds a [HeaderInfo] for calls to reverse an iterable. */
|
||||
@OptIn(ObsoleteDescriptorBasedAPI::class)
|
||||
internal class ReversedHandler(context: CommonBackendContext, private val visitor: HeaderInfoBuilder) :
|
||||
HeaderInfoFromCallHandler<Nothing?> {
|
||||
|
||||
|
||||
@@ -10,6 +10,7 @@ package org.jetbrains.kotlin.backend.common.lower.loops
|
||||
import org.jetbrains.kotlin.backend.common.CommonBackendContext
|
||||
import org.jetbrains.kotlin.backend.common.ir.Symbols
|
||||
import org.jetbrains.kotlin.backend.common.lower.DeclarationIrBuilder
|
||||
import org.jetbrains.kotlin.ir.ObsoleteDescriptorBasedAPI
|
||||
import org.jetbrains.kotlin.ir.builders.irChar
|
||||
import org.jetbrains.kotlin.ir.builders.irInt
|
||||
import org.jetbrains.kotlin.ir.builders.irLong
|
||||
@@ -48,8 +49,12 @@ internal sealed class ProgressionType(
|
||||
it.name == numberCastFunctionName &&
|
||||
it.dispatchReceiverParameter != null && it.extensionReceiverParameter == null && it.valueParameters.isEmpty()
|
||||
}
|
||||
IrCallImpl(startOffset, endOffset, castFun.returnType, castFun.symbol)
|
||||
.apply { dispatchReceiver = this@castIfNecessary }
|
||||
IrCallImpl(
|
||||
startOffset, endOffset,
|
||||
castFun.returnType, castFun.symbol,
|
||||
typeArgumentsCount = 0,
|
||||
valueArgumentsCount = 0
|
||||
).apply { dispatchReceiver = this@castIfNecessary }
|
||||
}
|
||||
|
||||
companion object {
|
||||
@@ -139,14 +144,25 @@ internal abstract class UnsignedProgressionType(
|
||||
if (type == unsignedType) return this
|
||||
|
||||
return if (unsafeCoerceIntrinsic != null) {
|
||||
IrCallImpl(startOffset, endOffset, unsignedType, unsafeCoerceIntrinsic).apply {
|
||||
IrCallImpl(
|
||||
startOffset, endOffset,
|
||||
unsignedType,
|
||||
unsafeCoerceIntrinsic,
|
||||
typeArgumentsCount = 2,
|
||||
valueArgumentsCount = 1
|
||||
).apply {
|
||||
putTypeArgument(0, fromType)
|
||||
putTypeArgument(1, unsignedType)
|
||||
putValueArgument(0, this@asUnsigned)
|
||||
}
|
||||
} else {
|
||||
// Fallback to calling `toUInt/ULong()` extension function.
|
||||
IrCallImpl(startOffset, endOffset, unsignedConversionFunction.owner.returnType, unsignedConversionFunction).apply {
|
||||
IrCallImpl(
|
||||
startOffset, endOffset, unsignedConversionFunction.owner.returnType,
|
||||
unsignedConversionFunction,
|
||||
typeArgumentsCount = 0,
|
||||
valueArgumentsCount = 0
|
||||
).apply {
|
||||
extensionReceiver = this@asUnsigned
|
||||
}
|
||||
}
|
||||
@@ -157,7 +173,12 @@ internal abstract class UnsignedProgressionType(
|
||||
if (type == toType) return this
|
||||
|
||||
return if (unsafeCoerceIntrinsic != null) {
|
||||
IrCallImpl(startOffset, endOffset, toType, unsafeCoerceIntrinsic).apply {
|
||||
IrCallImpl(
|
||||
startOffset, endOffset, toType,
|
||||
unsafeCoerceIntrinsic,
|
||||
typeArgumentsCount = 2,
|
||||
valueArgumentsCount = 1
|
||||
).apply {
|
||||
putTypeArgument(0, unsignedType)
|
||||
putTypeArgument(1, toType)
|
||||
putValueArgument(0, this@asSigned)
|
||||
@@ -169,6 +190,7 @@ internal abstract class UnsignedProgressionType(
|
||||
}
|
||||
}
|
||||
|
||||
@OptIn(ObsoleteDescriptorBasedAPI::class)
|
||||
internal class UIntProgressionType(symbols: Symbols<CommonBackendContext>) :
|
||||
UnsignedProgressionType(
|
||||
symbols,
|
||||
@@ -186,6 +208,7 @@ internal class UIntProgressionType(symbols: Symbols<CommonBackendContext>) :
|
||||
override fun DeclarationIrBuilder.zeroStepExpression() = irInt(0)
|
||||
}
|
||||
|
||||
@OptIn(ObsoleteDescriptorBasedAPI::class)
|
||||
internal class ULongProgressionType(symbols: Symbols<CommonBackendContext>) :
|
||||
UnsignedProgressionType(
|
||||
symbols,
|
||||
|
||||
@@ -8,7 +8,6 @@ package org.jetbrains.kotlin.backend.common.lower.loops
|
||||
import org.jetbrains.kotlin.backend.common.lower.DeclarationIrBuilder
|
||||
import org.jetbrains.kotlin.ir.builders.createTmpVariable
|
||||
import org.jetbrains.kotlin.ir.builders.irGet
|
||||
import org.jetbrains.kotlin.ir.declarations.IrValueDeclaration
|
||||
import org.jetbrains.kotlin.ir.declarations.IrVariable
|
||||
import org.jetbrains.kotlin.ir.expressions.IrConst
|
||||
import org.jetbrains.kotlin.ir.expressions.IrConstKind
|
||||
@@ -16,7 +15,6 @@ import org.jetbrains.kotlin.ir.expressions.IrExpression
|
||||
import org.jetbrains.kotlin.ir.expressions.IrGetValue
|
||||
import org.jetbrains.kotlin.ir.expressions.impl.IrCallImpl
|
||||
import org.jetbrains.kotlin.ir.expressions.impl.IrConstImpl
|
||||
import org.jetbrains.kotlin.ir.symbols.IrVariableSymbol
|
||||
import org.jetbrains.kotlin.ir.types.IrType
|
||||
import org.jetbrains.kotlin.ir.types.getClass
|
||||
import org.jetbrains.kotlin.ir.types.isNothing
|
||||
@@ -36,7 +34,12 @@ internal fun IrExpression.negate(): IrExpression {
|
||||
it.name == OperatorNameConventions.UNARY_MINUS &&
|
||||
it.valueParameters.isEmpty()
|
||||
}
|
||||
IrCallImpl(startOffset, endOffset, type, unaryMinusFun.symbol).apply {
|
||||
IrCallImpl(
|
||||
startOffset, endOffset, type,
|
||||
unaryMinusFun.symbol,
|
||||
valueArgumentsCount = 0,
|
||||
typeArgumentsCount = 0
|
||||
).apply {
|
||||
dispatchReceiver = this@negate
|
||||
}
|
||||
}
|
||||
@@ -54,7 +57,12 @@ internal fun IrExpression.decrement(): IrExpression {
|
||||
it.name == OperatorNameConventions.DEC &&
|
||||
it.valueParameters.isEmpty()
|
||||
}
|
||||
IrCallImpl(startOffset, endOffset, type, decFun.symbol).apply {
|
||||
IrCallImpl(
|
||||
startOffset, endOffset, type,
|
||||
decFun.symbol,
|
||||
valueArgumentsCount = 0,
|
||||
typeArgumentsCount = 0
|
||||
).apply {
|
||||
dispatchReceiver = this@decrement
|
||||
}
|
||||
}
|
||||
|
||||
@@ -5,6 +5,7 @@
|
||||
|
||||
package org.jetbrains.kotlin.backend.common.lower.matchers
|
||||
|
||||
import org.jetbrains.kotlin.ir.ObsoleteDescriptorBasedAPI
|
||||
import org.jetbrains.kotlin.ir.declarations.IrFunction
|
||||
import org.jetbrains.kotlin.ir.declarations.IrValueParameter
|
||||
import org.jetbrains.kotlin.ir.types.IrType
|
||||
@@ -51,6 +52,7 @@ internal class ParameterCountMatcher(
|
||||
}
|
||||
}
|
||||
|
||||
@OptIn(ObsoleteDescriptorBasedAPI::class)
|
||||
internal class FqNameMatcher(
|
||||
val restriction: (FqName) -> Boolean
|
||||
) : IrFunctionMatcher {
|
||||
|
||||
@@ -44,7 +44,7 @@ fun IrFieldBuilder.buildField(): IrField {
|
||||
return IrFieldImpl(
|
||||
startOffset, endOffset, origin,
|
||||
IrFieldSymbolImpl(wrappedDescriptor),
|
||||
name, type, visibility, isFinal, isExternal, isStatic, isFakeOverride
|
||||
name, type, visibility, isFinal, isExternal, isStatic,
|
||||
).also {
|
||||
it.metadata = metadata
|
||||
wrappedDescriptor.bind(it)
|
||||
|
||||
@@ -12,6 +12,7 @@ import org.jetbrains.kotlin.backend.common.ir.copyTypeParametersFrom
|
||||
import org.jetbrains.kotlin.descriptors.ClassKind
|
||||
import org.jetbrains.kotlin.descriptors.Visibilities
|
||||
import org.jetbrains.kotlin.descriptors.Visibility
|
||||
import org.jetbrains.kotlin.ir.ObsoleteDescriptorBasedAPI
|
||||
import org.jetbrains.kotlin.ir.UNDEFINED_OFFSET
|
||||
import org.jetbrains.kotlin.ir.backend.js.JsMapping
|
||||
import org.jetbrains.kotlin.ir.backend.js.ir.JsIrBuilder
|
||||
@@ -66,8 +67,7 @@ class JsDeclarationFactory(mapping: JsMapping) : DeclarationFactory {
|
||||
visibility,
|
||||
isFinal = true,
|
||||
isExternal = false,
|
||||
isStatic = false,
|
||||
isFakeOverride = false
|
||||
isStatic = false
|
||||
).also {
|
||||
descriptor.bind(it)
|
||||
it.parent = parent
|
||||
@@ -94,6 +94,7 @@ class JsDeclarationFactory(mapping: JsMapping) : DeclarationFactory {
|
||||
return originalInnerClassPrimaryConstructorByClass[innerClass]
|
||||
}
|
||||
|
||||
@OptIn(ObsoleteDescriptorBasedAPI::class)
|
||||
private fun createInnerClassConstructorWithOuterThisParameter(oldConstructor: IrConstructor): IrConstructor {
|
||||
val irClass = oldConstructor.parent as IrClass
|
||||
val outerThisType = (irClass.parent as IrClass).defaultType
|
||||
|
||||
@@ -14,10 +14,7 @@ import org.jetbrains.kotlin.config.CompilerConfiguration
|
||||
import org.jetbrains.kotlin.descriptors.*
|
||||
import org.jetbrains.kotlin.descriptors.impl.EmptyPackageFragmentDescriptor
|
||||
import org.jetbrains.kotlin.incremental.components.NoLookupLocation
|
||||
import org.jetbrains.kotlin.ir.IrElement
|
||||
import org.jetbrains.kotlin.ir.SourceManager
|
||||
import org.jetbrains.kotlin.ir.SourceRangeInfo
|
||||
import org.jetbrains.kotlin.ir.UNDEFINED_OFFSET
|
||||
import org.jetbrains.kotlin.ir.*
|
||||
import org.jetbrains.kotlin.ir.backend.js.ir.JsIrBuilder
|
||||
import org.jetbrains.kotlin.ir.backend.js.utils.OperatorNames
|
||||
import org.jetbrains.kotlin.ir.declarations.*
|
||||
@@ -60,6 +57,8 @@ class JsIrBackendContext(
|
||||
|
||||
val externalPackageFragment = mutableMapOf<IrFileSymbol, IrFile>()
|
||||
val externalDeclarations = hashSetOf<IrDeclaration>()
|
||||
|
||||
@OptIn(ObsoleteDescriptorBasedAPI::class)
|
||||
val bodilessBuiltInsPackageFragment: IrPackageFragment = run {
|
||||
|
||||
class DescriptorlessExternalPackageFragmentSymbol : IrExternalPackageFragmentSymbol {
|
||||
|
||||
@@ -45,10 +45,15 @@ class JsSharedVariablesManager(val builtIns: IrBuiltIns, val implicitDeclaration
|
||||
val constructorSymbol = closureBoxConstructorDeclaration.symbol
|
||||
|
||||
val irCall =
|
||||
IrConstructorCallImpl.fromSymbolDescriptor(initializer.startOffset, initializer.endOffset, closureBoxType, constructorSymbol)
|
||||
.apply {
|
||||
putValueArgument(0, initializer)
|
||||
}
|
||||
IrConstructorCallImpl(
|
||||
initializer.startOffset, initializer.endOffset,
|
||||
closureBoxType, constructorSymbol,
|
||||
valueArgumentsCount = 1,
|
||||
typeArgumentsCount = 0,
|
||||
constructorTypeArgumentsCount = 0
|
||||
).apply {
|
||||
putValueArgument(0, initializer)
|
||||
}
|
||||
|
||||
val descriptor = WrappedVariableDescriptor()
|
||||
return IrVariableImpl(
|
||||
@@ -155,8 +160,7 @@ class JsSharedVariablesManager(val builtIns: IrBuiltIns, val implicitDeclaration
|
||||
Visibilities.PUBLIC,
|
||||
isFinal = false,
|
||||
isExternal = false,
|
||||
isStatic = false,
|
||||
isFakeOverride = false
|
||||
isStatic = false
|
||||
).also {
|
||||
descriptor.bind(it)
|
||||
it.parent = closureBoxClassDeclaration
|
||||
|
||||
@@ -26,20 +26,23 @@ object JsIrBuilder {
|
||||
object SYNTHESIZED_STATEMENT : IrStatementOriginImpl("SYNTHESIZED_STATEMENT")
|
||||
object SYNTHESIZED_DECLARATION : IrDeclarationOriginImpl("SYNTHESIZED_DECLARATION")
|
||||
|
||||
fun buildCall(target: IrFunctionSymbol, type: IrType? = null, typeArguments: List<IrType>? = null): IrCall =
|
||||
IrCallImpl(
|
||||
fun buildCall(target: IrFunctionSymbol, type: IrType? = null, typeArguments: List<IrType>? = null): IrCall {
|
||||
val owner = target.owner
|
||||
return IrCallImpl(
|
||||
UNDEFINED_OFFSET,
|
||||
UNDEFINED_OFFSET,
|
||||
type ?: target.owner.returnType,
|
||||
type ?: owner.returnType,
|
||||
target,
|
||||
target.owner.typeParameters.size,
|
||||
SYNTHESIZED_STATEMENT
|
||||
typeArgumentsCount = owner.typeParameters.size,
|
||||
valueArgumentsCount = owner.valueParameters.size,
|
||||
origin = SYNTHESIZED_STATEMENT
|
||||
).apply {
|
||||
typeArguments?.let {
|
||||
assert(typeArguments.size == typeArgumentsCount)
|
||||
it.withIndex().forEach { (i, t) -> putTypeArgument(i, t) }
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fun buildReturn(targetSymbol: IrFunctionSymbol, value: IrExpression, type: IrType) =
|
||||
IrReturnImpl(UNDEFINED_OFFSET, UNDEFINED_OFFSET, type, targetSymbol, value)
|
||||
@@ -191,9 +194,6 @@ object JsIrBuilder {
|
||||
fun buildComposite(type: IrType, statements: List<IrStatement> = emptyList()) =
|
||||
IrCompositeImpl(UNDEFINED_OFFSET, UNDEFINED_OFFSET, type, SYNTHESIZED_STATEMENT, statements)
|
||||
|
||||
fun buildFunctionReference(type: IrType, symbol: IrFunctionSymbol, reflectionTarget: IrFunctionSymbol? = symbol) =
|
||||
IrFunctionReferenceImpl(UNDEFINED_OFFSET, UNDEFINED_OFFSET, type, symbol, 0, reflectionTarget, null)
|
||||
|
||||
fun buildFunctionExpression(type: IrType, function: IrSimpleFunction) =
|
||||
IrFunctionExpressionImpl(UNDEFINED_OFFSET, UNDEFINED_OFFSET, type, function, SYNTHESIZED_STATEMENT)
|
||||
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user