mirror of
https://github.com/jlengrand/kotlin.git
synced 2026-04-05 00:21:31 +00:00
Compare commits
64 Commits
build-1.4.
...
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 |
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>
|
||||
|
||||
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>
|
||||
@@ -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.*;
|
||||
|
||||
@@ -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> =
|
||||
|
||||
@@ -594,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
|
||||
@@ -642,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 {
|
||||
@@ -658,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
|
||||
|
||||
@@ -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)
|
||||
}
|
||||
}
|
||||
@@ -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");
|
||||
|
||||
@@ -651,7 +651,6 @@ class Fir2IrDeclarationStorage(
|
||||
name: Name,
|
||||
isFinal: Boolean,
|
||||
firInitializerExpression: FirExpression?,
|
||||
thisReceiverOwner: IrClass?,
|
||||
type: IrType? = null
|
||||
): IrField {
|
||||
val inferredType = type ?: firInitializerExpression!!.typeRef.toIrType()
|
||||
@@ -664,12 +663,8 @@ class Fir2IrDeclarationStorage(
|
||||
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)
|
||||
@@ -738,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
|
||||
@@ -749,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) {
|
||||
@@ -803,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)
|
||||
@@ -1028,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
|
||||
|
||||
@@ -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");
|
||||
|
||||
@@ -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
|
||||
*/
|
||||
|
||||
@@ -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
|
||||
|
||||
|
||||
@@ -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(
|
||||
@@ -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>
|
||||
|
||||
@@ -681,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
|
||||
|
||||
@@ -775,8 +775,7 @@ class LocalDeclarationsLowering(
|
||||
visibility,
|
||||
isFinal = true,
|
||||
isExternal = false,
|
||||
isStatic = false,
|
||||
isFakeOverride = false
|
||||
isStatic = false
|
||||
).also {
|
||||
descriptor.bind(it)
|
||||
it.parent = parent
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -67,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
|
||||
|
||||
@@ -160,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
|
||||
|
||||
@@ -6,7 +6,6 @@
|
||||
package org.jetbrains.kotlin.ir.backend.js.lower
|
||||
|
||||
import org.jetbrains.kotlin.backend.common.BodyLoweringPass
|
||||
import org.jetbrains.kotlin.backend.common.CommonBackendContext
|
||||
import org.jetbrains.kotlin.backend.common.DeclarationTransformer
|
||||
import org.jetbrains.kotlin.backend.common.getOrPut
|
||||
import org.jetbrains.kotlin.backend.common.ir.copyParameterDeclarationsFrom
|
||||
@@ -70,8 +69,7 @@ class EnumUsageLowering(val context: JsIrBackendContext) : BodyLoweringPass {
|
||||
return entry.run {
|
||||
IrFieldImpl(
|
||||
startOffset, endOffset, origin, symbol, name, irClass.defaultType, Visibilities.PUBLIC,
|
||||
isFinal = false, isExternal = true, isStatic = true,
|
||||
isFakeOverride = entry.isFakeOverride
|
||||
isFinal = false, isExternal = true, isStatic = true
|
||||
).also {
|
||||
descriptor.bind(it)
|
||||
it.parent = irClass
|
||||
|
||||
@@ -557,8 +557,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
|
||||
|
||||
@@ -18,6 +18,9 @@ interface JvmLoweredDeclarationOrigin : IrDeclarationOrigin {
|
||||
object LAMBDA_IMPL : IrDeclarationOriginImpl("LAMBDA_IMPL")
|
||||
object FUNCTION_REFERENCE_IMPL : IrDeclarationOriginImpl("FUNCTION_REFERENCE_IMPL", isSynthetic = true)
|
||||
object SYNTHETIC_ACCESSOR : IrDeclarationOriginImpl("SYNTHETIC_ACCESSOR", isSynthetic = true)
|
||||
object SYNTHETIC_ACCESSOR_FOR_HIDDEN_CONSTRUCTOR :
|
||||
IrDeclarationOriginImpl("SYNTHETIC_ACCESSOR_FOR_HIDDEN_CONSTRUCTOR", isSynthetic = true)
|
||||
object SYNTHETIC_MARKER_PARAMETER : IrDeclarationOriginImpl("SYNTHETIC_MARKER_PARAMETER", isSynthetic = true)
|
||||
object TO_ARRAY : IrDeclarationOriginImpl("TO_ARRAY")
|
||||
object JVM_STATIC_WRAPPER : IrDeclarationOriginImpl("JVM_STATIC_WRAPPER")
|
||||
object JVM_OVERLOADS_WRAPPER : IrDeclarationOriginImpl("JVM_OVERLOADS_WRAPPER")
|
||||
|
||||
@@ -277,12 +277,15 @@ abstract class AnnotationCodegen(
|
||||
|
||||
companion object {
|
||||
private fun isInvisibleFromTheOutside(declaration: IrDeclaration?): Boolean {
|
||||
if (declaration is IrSimpleFunction && declaration.origin === JvmLoweredDeclarationOrigin.SYNTHETIC_ACCESSOR) {
|
||||
if (declaration is IrSimpleFunction && declaration.origin.isSynthetic) {
|
||||
return true
|
||||
}
|
||||
if (declaration is IrDeclarationWithVisibility) {
|
||||
return !declaration.visibility.isVisibleOutside()
|
||||
}
|
||||
if (declaration is IrValueParameter && (declaration.parent as IrDeclaration).origin.isSynthetic) {
|
||||
return true
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
|
||||
@@ -229,8 +229,6 @@ abstract class ClassCodegen protected constructor(
|
||||
protected abstract fun bindFieldMetadata(field: IrField, fieldType: Type, fieldName: String)
|
||||
|
||||
private fun generateField(field: IrField) {
|
||||
if (field.isFakeOverride) return
|
||||
|
||||
val fieldType = typeMapper.mapType(field)
|
||||
val fieldSignature =
|
||||
if (field.origin == IrDeclarationOrigin.PROPERTY_DELEGATE) null
|
||||
|
||||
@@ -130,6 +130,7 @@ internal fun IrFunction.shouldContainSuspendMarkers(): Boolean = !isInvokeSuspen
|
||||
origin != JvmLoweredDeclarationOrigin.JVM_OVERLOADS_WRAPPER &&
|
||||
origin != JvmLoweredDeclarationOrigin.MULTIFILE_BRIDGE &&
|
||||
origin != JvmLoweredDeclarationOrigin.SYNTHETIC_ACCESSOR &&
|
||||
origin != JvmLoweredDeclarationOrigin.SYNTHETIC_ACCESSOR_FOR_HIDDEN_CONSTRUCTOR &&
|
||||
origin != JvmLoweredDeclarationOrigin.DEFAULT_IMPLS_BRIDGE &&
|
||||
origin != JvmLoweredDeclarationOrigin.DEFAULT_IMPLS_BRIDGE_TO_SYNTHETIC &&
|
||||
origin != IrDeclarationOrigin.BRIDGE &&
|
||||
|
||||
@@ -535,16 +535,27 @@ class ExpressionCodegen(
|
||||
assert(callee.constantValue() == null) { "access of const val: ${expression.dump()}" }
|
||||
}
|
||||
|
||||
val realField = callee.resolveFakeOverride()!!
|
||||
val fieldType = typeMapper.mapType(realField.type)
|
||||
val fieldName = realField.name.asString()
|
||||
val fieldType = typeMapper.mapType(callee.type)
|
||||
val fieldName = callee.name.asString()
|
||||
val isStatic = expression.receiver == null
|
||||
expression.markLineNumber(startOffset = true)
|
||||
val ownerName = expression.receiver?.let { receiver ->
|
||||
val ownerType = typeMapper.mapTypeAsDeclaration(receiver.type)
|
||||
|
||||
val ownerType = when {
|
||||
expression.superQualifierSymbol != null -> {
|
||||
typeMapper.mapClass(expression.superQualifierSymbol!!.owner)
|
||||
}
|
||||
expression.receiver != null -> {
|
||||
typeMapper.mapTypeAsDeclaration(expression.receiver!!.type)
|
||||
}
|
||||
else -> typeMapper.mapClass(callee.parentAsClass)
|
||||
}
|
||||
|
||||
val ownerName = ownerType.internalName
|
||||
|
||||
expression.receiver?.let { receiver ->
|
||||
receiver.accept(this, data).materializeAt(ownerType, receiver.type)
|
||||
ownerType.internalName
|
||||
} ?: typeMapper.mapClass(callee.parentAsClass).internalName
|
||||
}
|
||||
|
||||
return if (expression is IrSetField) {
|
||||
val value = expression.value.accept(this, data)
|
||||
|
||||
|
||||
@@ -12,7 +12,10 @@ import org.jetbrains.kotlin.backend.jvm.JvmBackendContext
|
||||
import org.jetbrains.kotlin.backend.jvm.JvmLoweredDeclarationOrigin
|
||||
import org.jetbrains.kotlin.backend.jvm.lower.suspendFunctionOriginal
|
||||
import org.jetbrains.kotlin.codegen.AsmUtil
|
||||
import org.jetbrains.kotlin.codegen.inline.*
|
||||
import org.jetbrains.kotlin.codegen.inline.MethodBodyVisitor
|
||||
import org.jetbrains.kotlin.codegen.inline.SMAP
|
||||
import org.jetbrains.kotlin.codegen.inline.SMAPAndMethodNode
|
||||
import org.jetbrains.kotlin.codegen.inline.wrapWithMaxLocalCalc
|
||||
import org.jetbrains.kotlin.codegen.mangleNameIfNeeded
|
||||
import org.jetbrains.kotlin.codegen.state.GenerationState
|
||||
import org.jetbrains.kotlin.codegen.visitAnnotableParameterCount
|
||||
@@ -23,7 +26,6 @@ import org.jetbrains.kotlin.ir.declarations.*
|
||||
import org.jetbrains.kotlin.ir.expressions.*
|
||||
import org.jetbrains.kotlin.ir.util.*
|
||||
import org.jetbrains.kotlin.load.java.JavaVisibilities
|
||||
import org.jetbrains.kotlin.name.FqName
|
||||
import org.jetbrains.kotlin.name.Name
|
||||
import org.jetbrains.kotlin.resolve.annotations.JVM_THROWS_ANNOTATION_FQ_NAME
|
||||
import org.jetbrains.kotlin.resolve.jvm.annotations.JVM_SYNTHETIC_ANNOTATION_FQ_NAME
|
||||
@@ -67,7 +69,9 @@ class FunctionCodegen(
|
||||
generateParameterNames(irFunction, methodVisitor, signature, context.state)
|
||||
}
|
||||
|
||||
if (irFunction.origin != IrDeclarationOrigin.FUNCTION_FOR_DEFAULT_PARAMETER) {
|
||||
if (irFunction.origin != IrDeclarationOrigin.FUNCTION_FOR_DEFAULT_PARAMETER &&
|
||||
irFunction.origin != JvmLoweredDeclarationOrigin.SYNTHETIC_ACCESSOR
|
||||
) {
|
||||
object : AnnotationCodegen(classCodegen, context) {
|
||||
override fun visitAnnotation(descr: String?, visible: Boolean): AnnotationVisitor {
|
||||
return methodVisitor.visitAnnotation(descr, visible)
|
||||
@@ -237,7 +241,7 @@ private fun generateParameterAnnotations(
|
||||
else -> iterator.next()
|
||||
}
|
||||
|
||||
if (!kind.isSkippedInGenericSignature) {
|
||||
if (annotated != null && !kind.isSkippedInGenericSignature && !annotated.isSyntheticMarkerParameter()) {
|
||||
object : AnnotationCodegen(innerClassConsumer, context) {
|
||||
override fun visitAnnotation(descr: String?, visible: Boolean): AnnotationVisitor {
|
||||
return mv.visitParameterAnnotation(
|
||||
@@ -253,11 +257,15 @@ private fun generateParameterAnnotations(
|
||||
path, descr, visible
|
||||
)
|
||||
}
|
||||
}.genAnnotations(annotated, parameterSignature.asmType, annotated?.type)
|
||||
}.genAnnotations(annotated, parameterSignature.asmType, annotated.type)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun IrValueParameter.isSyntheticMarkerParameter(): Boolean =
|
||||
origin == IrDeclarationOrigin.DEFAULT_CONSTRUCTOR_MARKER ||
|
||||
origin == JvmLoweredDeclarationOrigin.SYNTHETIC_MARKER_PARAMETER
|
||||
|
||||
private fun generateParameterNames(irFunction: IrFunction, mv: MethodVisitor, jvmSignature: JvmMethodSignature, state: GenerationState) {
|
||||
val iterator = irFunction.valueParameters.iterator()
|
||||
for (parameterSignature in jvmSignature.valueParameters) {
|
||||
|
||||
@@ -339,7 +339,7 @@ fun IrProperty.needsAccessor(accessor: IrSimpleFunction): Boolean = when {
|
||||
// Properties in annotation classes become abstract methods named after the property.
|
||||
(parent as? IrClass)?.kind == ClassKind.ANNOTATION_CLASS -> true
|
||||
// @JvmField properties have no getters/setters
|
||||
backingField?.hasAnnotation(JvmAbi.JVM_FIELD_ANNOTATION_FQ_NAME) == true -> false
|
||||
resolveFakeOverride()?.backingField?.hasAnnotation(JvmAbi.JVM_FIELD_ANNOTATION_FQ_NAME) == true -> false
|
||||
// We do not produce default accessors for private fields
|
||||
else -> accessor.origin != IrDeclarationOrigin.DEFAULT_PROPERTY_ACCESSOR || !Visibilities.isPrivate(accessor.visibility)
|
||||
}
|
||||
|
||||
@@ -191,17 +191,7 @@ internal class FunctionReferenceLowering(private val context: JvmBackendContext)
|
||||
}
|
||||
}
|
||||
|
||||
private val receiverFieldFromSuper = context.ir.symbols.functionReferenceReceiverField.owner
|
||||
|
||||
val fakeOverrideReceiverField = functionReferenceClass.addField {
|
||||
name = receiverFieldFromSuper.name
|
||||
isFakeOverride = true
|
||||
origin = IrDeclarationOrigin.FAKE_OVERRIDE
|
||||
type = receiverFieldFromSuper.type
|
||||
isFinal = receiverFieldFromSuper.isFinal
|
||||
isStatic = receiverFieldFromSuper.isStatic
|
||||
visibility = receiverFieldFromSuper.visibility
|
||||
}
|
||||
private val receiverField = context.ir.symbols.functionReferenceReceiverField.owner
|
||||
|
||||
fun build(): IrExpression = context.createJvmIrBuilder(currentScope!!.scope.scopeOwnerSymbol).run {
|
||||
irBlock(irFunctionReference.startOffset, irFunctionReference.endOffset) {
|
||||
@@ -418,7 +408,9 @@ internal class FunctionReferenceLowering(private val context: JvmBackendContext)
|
||||
// will put it into a field.
|
||||
if (samSuperType == null)
|
||||
irImplicitCast(
|
||||
irGetField(irGet(dispatchReceiverParameter!!), fakeOverrideReceiverField),
|
||||
irGetField(irGet(dispatchReceiverParameter!!),
|
||||
this@FunctionReferenceBuilder.receiverField
|
||||
),
|
||||
boundReceiver.second.type
|
||||
)
|
||||
else
|
||||
|
||||
@@ -29,10 +29,7 @@ import org.jetbrains.kotlin.ir.expressions.impl.IrBlockBodyImpl
|
||||
import org.jetbrains.kotlin.ir.types.classifierOrFail
|
||||
import org.jetbrains.kotlin.ir.types.makeNotNull
|
||||
import org.jetbrains.kotlin.ir.types.typeWith
|
||||
import org.jetbrains.kotlin.ir.util.coerceToUnit
|
||||
import org.jetbrains.kotlin.ir.util.hasAnnotation
|
||||
import org.jetbrains.kotlin.ir.util.render
|
||||
import org.jetbrains.kotlin.ir.util.transformDeclarationsFlat
|
||||
import org.jetbrains.kotlin.ir.util.*
|
||||
import org.jetbrains.kotlin.ir.visitors.transformChildrenVoid
|
||||
import org.jetbrains.kotlin.load.java.JvmAbi
|
||||
import org.jetbrains.kotlin.name.Name
|
||||
@@ -69,10 +66,10 @@ class JvmPropertiesLowering(private val backendContext: JvmBackendContext) : IrE
|
||||
}
|
||||
|
||||
private fun IrBuilderWithScope.substituteSetter(irProperty: IrProperty, expression: IrCall): IrExpression =
|
||||
patchReceiver(irSetField(expression.dispatchReceiver, irProperty.backingField!!, expression.getValueArgument(0)!!))
|
||||
patchReceiver(irSetField(expression.dispatchReceiver, irProperty.resolveFakeOverride()!!.backingField!!, expression.getValueArgument(0)!!))
|
||||
|
||||
private fun IrBuilderWithScope.substituteGetter(irProperty: IrProperty, expression: IrCall): IrExpression {
|
||||
val backingField = irProperty.backingField!!
|
||||
val backingField = irProperty.resolveFakeOverride()!!.backingField!!
|
||||
val value = irGetField(expression.dispatchReceiver, backingField)
|
||||
return if (irProperty.isLateinit) {
|
||||
irBlock {
|
||||
|
||||
@@ -299,17 +299,7 @@ internal class PropertyReferenceLowering(val context: JvmBackendContext) : Class
|
||||
referenceClass.addOverride(getSignature) { computeSignatureString(expression) }
|
||||
}
|
||||
|
||||
val receiverField = referenceClass.addField {
|
||||
val backingFieldFromSuper = superClass.properties.single { it.name.asString() == "receiver" }.backingField!!
|
||||
name = backingFieldFromSuper.name
|
||||
isFakeOverride = true
|
||||
origin = IrDeclarationOrigin.FAKE_OVERRIDE
|
||||
type = backingFieldFromSuper.type
|
||||
isFinal = backingFieldFromSuper.isFinal
|
||||
isStatic = backingFieldFromSuper.isStatic
|
||||
visibility = backingFieldFromSuper.visibility
|
||||
}
|
||||
|
||||
val backingField = superClass.properties.single { it.name.asString() == "receiver" }.backingField!!
|
||||
val get = superClass.functions.find { it.name.asString() == "get" }
|
||||
val set = superClass.functions.find { it.name.asString() == "set" }
|
||||
val invoke = superClass.functions.find { it.name.asString() == "invoke" }
|
||||
@@ -321,13 +311,13 @@ internal class PropertyReferenceLowering(val context: JvmBackendContext) : Class
|
||||
call.copyTypeArgumentsFrom(expression)
|
||||
call.dispatchReceiver = call.symbol.owner.dispatchReceiverParameter?.let {
|
||||
if (expression.dispatchReceiver != null)
|
||||
irImplicitCast(irGetField(irGet(arguments[0]), receiverField), it.type)
|
||||
irImplicitCast(irGetField(irGet(arguments[0]), backingField), it.type)
|
||||
else
|
||||
irImplicitCast(irGet(arguments[index++]), it.type)
|
||||
}
|
||||
call.extensionReceiver = call.symbol.owner.extensionReceiverParameter?.let {
|
||||
if (expression.extensionReceiver != null)
|
||||
irImplicitCast(irGetField(irGet(arguments[0]), receiverField), it.type)
|
||||
irImplicitCast(irGetField(irGet(arguments[0]), backingField), it.type)
|
||||
else
|
||||
irImplicitCast(irGet(arguments[index++]), it.type)
|
||||
}
|
||||
@@ -354,7 +344,7 @@ internal class PropertyReferenceLowering(val context: JvmBackendContext) : Class
|
||||
field.isStatic ->
|
||||
null
|
||||
expression.dispatchReceiver != null ->
|
||||
irImplicitCast(irGetField(irGet(arguments[0]), receiverField), field.parentAsClass.defaultType)
|
||||
irImplicitCast(irGetField(irGet(arguments[0]), backingField), field.parentAsClass.defaultType)
|
||||
else ->
|
||||
irImplicitCast(irGet(arguments[1]), field.parentAsClass.defaultType)
|
||||
}
|
||||
|
||||
@@ -96,9 +96,7 @@ private class FieldNameCollector : IrElementVisitorVoid {
|
||||
}
|
||||
|
||||
override fun visitField(declaration: IrField) {
|
||||
if (!declaration.isFakeOverride) {
|
||||
nameToField.getOrPut(declaration.parent to declaration.name) { mutableListOf() }.add(declaration)
|
||||
}
|
||||
nameToField.getOrPut(declaration.parent to declaration.name) { mutableListOf() }.add(declaration)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -113,7 +111,6 @@ private class FieldRenamer(private val newNames: Map<IrField, Name>) : IrElement
|
||||
return IrFieldImpl(
|
||||
declaration.startOffset, declaration.endOffset, declaration.origin, symbol, newName,
|
||||
declaration.type, declaration.visibility, declaration.isFinal, declaration.isExternal, declaration.isStatic,
|
||||
isFakeOverride = declaration.isFakeOverride
|
||||
).also {
|
||||
descriptor.bind(it)
|
||||
it.parent = declaration.parent
|
||||
|
||||
@@ -160,10 +160,9 @@ internal class SyntheticAccessorLowering(val context: JvmBackendContext) : IrEle
|
||||
val symbol = expression.symbol
|
||||
val parent =
|
||||
symbol.owner.accessorParent(dispatchReceiverType?.classOrNull?.owner ?: symbol.owner.parent) as IrClass
|
||||
val symbolToAccess = symbol.owner.findDescendantIn(parent)?.symbol ?: symbol
|
||||
modifyGetterExpression(
|
||||
expression,
|
||||
getterMap.getOrPut(Pair(symbolToAccess, parent)) { makeGetterAccessorSymbol(symbolToAccess, parent) }
|
||||
getterMap.getOrPut(Pair(symbol, parent)) { makeGetterAccessorSymbol(symbol, parent) }
|
||||
)
|
||||
} else {
|
||||
expression
|
||||
@@ -178,10 +177,9 @@ internal class SyntheticAccessorLowering(val context: JvmBackendContext) : IrEle
|
||||
val symbol = expression.symbol
|
||||
val parent =
|
||||
symbol.owner.accessorParent(dispatchReceiverType?.classOrNull?.owner ?: symbol.owner.parent) as IrClass
|
||||
val symbolToAccess = symbol.owner.findDescendantIn(parent)?.symbol ?: symbol
|
||||
modifySetterExpression(
|
||||
expression,
|
||||
setterMap.getOrPut(Pair(symbolToAccess, parent)) { makeSetterAccessorSymbol(symbolToAccess, parent) }
|
||||
setterMap.getOrPut(Pair(symbol, parent)) { makeSetterAccessorSymbol(symbol, parent) }
|
||||
)
|
||||
} else {
|
||||
expression
|
||||
@@ -189,11 +187,6 @@ internal class SyntheticAccessorLowering(val context: JvmBackendContext) : IrEle
|
||||
)
|
||||
}
|
||||
|
||||
private fun IrField.findDescendantIn(derivedClass: IrClass): IrField? =
|
||||
derivedClass.fields.singleOrNull { candidate ->
|
||||
candidate.name == this.name && candidate.overrides(this)
|
||||
}
|
||||
|
||||
override fun visitConstructor(declaration: IrConstructor): IrStatement {
|
||||
if (declaration.isOrShouldBeHidden) {
|
||||
pendingAccessorsToAdd.add(handleHiddenConstructor(declaration))
|
||||
@@ -224,12 +217,13 @@ internal class SyntheticAccessorLowering(val context: JvmBackendContext) : IrEle
|
||||
get() = this in context.hiddenConstructors || (
|
||||
!Visibilities.isPrivate(visibility) && !constructedClass.isInline && hasMangledParameters &&
|
||||
origin != IrDeclarationOrigin.FUNCTION_FOR_DEFAULT_PARAMETER &&
|
||||
origin != JvmLoweredDeclarationOrigin.SYNTHETIC_ACCESSOR)
|
||||
origin != JvmLoweredDeclarationOrigin.SYNTHETIC_ACCESSOR &&
|
||||
origin != JvmLoweredDeclarationOrigin.SYNTHETIC_ACCESSOR_FOR_HIDDEN_CONSTRUCTOR)
|
||||
|
||||
private fun handleHiddenConstructor(declaration: IrConstructor): IrConstructorImpl {
|
||||
require(declaration.isOrShouldBeHidden, declaration::render)
|
||||
return context.hiddenConstructors.getOrPut(declaration) {
|
||||
declaration.makeConstructorAccessor().also { accessor ->
|
||||
declaration.makeConstructorAccessor(JvmLoweredDeclarationOrigin.SYNTHETIC_ACCESSOR_FOR_HIDDEN_CONSTRUCTOR).also { accessor ->
|
||||
// There's a special case in the JVM backend for serializing the metadata of hidden
|
||||
// constructors - we serialize the descriptor of the original constructor, but the
|
||||
// signature of the accessor. We implement this special case in the JVM IR backend by
|
||||
@@ -256,11 +250,14 @@ internal class SyntheticAccessorLowering(val context: JvmBackendContext) : IrEle
|
||||
candidates.lastOrNull { parent is IrClass && it.isSubclassOf(parent) } ?: classes.last()
|
||||
} else parent
|
||||
|
||||
private fun IrConstructor.makeConstructorAccessor(): IrConstructorImpl {
|
||||
private fun IrConstructor.makeConstructorAccessor(
|
||||
originForConstructorAccessor: IrDeclarationOrigin =
|
||||
JvmLoweredDeclarationOrigin.SYNTHETIC_ACCESSOR
|
||||
): IrConstructorImpl {
|
||||
val source = this
|
||||
|
||||
return buildConstructor {
|
||||
origin = JvmLoweredDeclarationOrigin.SYNTHETIC_ACCESSOR
|
||||
origin = originForConstructorAccessor
|
||||
name = source.name
|
||||
visibility = Visibilities.PUBLIC
|
||||
}.also { accessor ->
|
||||
@@ -272,8 +269,8 @@ internal class SyntheticAccessorLowering(val context: JvmBackendContext) : IrEle
|
||||
|
||||
accessor.addValueParameter(
|
||||
"constructor_marker".synthesizedString,
|
||||
context.ir.symbols.defaultConstructorMarker.defaultType,
|
||||
JvmLoweredDeclarationOrigin.SYNTHETIC_ACCESSOR
|
||||
context.ir.symbols.defaultConstructorMarker.defaultType.makeNullable(),
|
||||
JvmLoweredDeclarationOrigin.SYNTHETIC_MARKER_PARAMETER
|
||||
)
|
||||
|
||||
accessor.body = IrExpressionBodyImpl(
|
||||
@@ -326,7 +323,7 @@ internal class SyntheticAccessorLowering(val context: JvmBackendContext) : IrEle
|
||||
copyAllParamsToArgs(it, accessor)
|
||||
}
|
||||
|
||||
private fun makeGetterAccessorSymbol(fieldSymbol: IrFieldSymbol, parent: IrDeclarationParent): IrSimpleFunctionSymbol =
|
||||
private fun makeGetterAccessorSymbol(fieldSymbol: IrFieldSymbol, parent: IrClass): IrSimpleFunctionSymbol =
|
||||
buildFun {
|
||||
origin = JvmLoweredDeclarationOrigin.SYNTHETIC_ACCESSOR
|
||||
name = fieldSymbol.owner.accessorNameForGetter()
|
||||
@@ -338,8 +335,9 @@ internal class SyntheticAccessorLowering(val context: JvmBackendContext) : IrEle
|
||||
pendingAccessorsToAdd.add(accessor)
|
||||
|
||||
if (!fieldSymbol.owner.isStatic) {
|
||||
// Accessors are always to one's own fields.
|
||||
accessor.addValueParameter(
|
||||
"\$this", fieldSymbol.owner.parentAsClass.defaultType, JvmLoweredDeclarationOrigin.SYNTHETIC_ACCESSOR
|
||||
"\$this", parent.defaultType, JvmLoweredDeclarationOrigin.SYNTHETIC_ACCESSOR
|
||||
)
|
||||
}
|
||||
|
||||
@@ -347,22 +345,21 @@ internal class SyntheticAccessorLowering(val context: JvmBackendContext) : IrEle
|
||||
}.symbol
|
||||
|
||||
private fun createAccessorBodyForGetter(targetField: IrField, accessor: IrSimpleFunction): IrBody {
|
||||
val resolvedTargetField = targetField.resolveFakeOverride()!!
|
||||
val maybeDispatchReceiver =
|
||||
if (resolvedTargetField.isStatic) null
|
||||
if (targetField.isStatic) null
|
||||
else IrGetValueImpl(UNDEFINED_OFFSET, UNDEFINED_OFFSET, accessor.valueParameters[0].symbol)
|
||||
return IrExpressionBodyImpl(
|
||||
UNDEFINED_OFFSET, UNDEFINED_OFFSET,
|
||||
IrGetFieldImpl(
|
||||
UNDEFINED_OFFSET, UNDEFINED_OFFSET,
|
||||
resolvedTargetField.symbol,
|
||||
resolvedTargetField.type,
|
||||
targetField.symbol,
|
||||
targetField.type,
|
||||
maybeDispatchReceiver
|
||||
)
|
||||
)
|
||||
}
|
||||
|
||||
private fun makeSetterAccessorSymbol(fieldSymbol: IrFieldSymbol, parent: IrDeclarationParent): IrSimpleFunctionSymbol =
|
||||
private fun makeSetterAccessorSymbol(fieldSymbol: IrFieldSymbol, parent: IrClass): IrSimpleFunctionSymbol =
|
||||
buildFun {
|
||||
origin = JvmLoweredDeclarationOrigin.SYNTHETIC_ACCESSOR
|
||||
name = fieldSymbol.owner.accessorNameForSetter()
|
||||
@@ -374,8 +371,9 @@ internal class SyntheticAccessorLowering(val context: JvmBackendContext) : IrEle
|
||||
pendingAccessorsToAdd.add(accessor)
|
||||
|
||||
if (!fieldSymbol.owner.isStatic) {
|
||||
// Accessors are always to one's own fields.
|
||||
accessor.addValueParameter(
|
||||
"\$this", fieldSymbol.owner.parentAsClass.defaultType, JvmLoweredDeclarationOrigin.SYNTHETIC_ACCESSOR
|
||||
"\$this", parent.defaultType, JvmLoweredDeclarationOrigin.SYNTHETIC_ACCESSOR
|
||||
)
|
||||
}
|
||||
|
||||
@@ -385,19 +383,18 @@ internal class SyntheticAccessorLowering(val context: JvmBackendContext) : IrEle
|
||||
}.symbol
|
||||
|
||||
private fun createAccessorBodyForSetter(targetField: IrField, accessor: IrSimpleFunction): IrBody {
|
||||
val resolvedTargetField = targetField.resolveFakeOverride()!!
|
||||
val maybeDispatchReceiver =
|
||||
if (resolvedTargetField.isStatic) null
|
||||
if (targetField.isStatic) null
|
||||
else IrGetValueImpl(UNDEFINED_OFFSET, UNDEFINED_OFFSET, accessor.valueParameters[0].symbol)
|
||||
val value = IrGetValueImpl(
|
||||
UNDEFINED_OFFSET, UNDEFINED_OFFSET,
|
||||
accessor.valueParameters[if (resolvedTargetField.isStatic) 0 else 1].symbol
|
||||
accessor.valueParameters[if (targetField.isStatic) 0 else 1].symbol
|
||||
)
|
||||
return IrExpressionBodyImpl(
|
||||
UNDEFINED_OFFSET, UNDEFINED_OFFSET,
|
||||
IrSetFieldImpl(
|
||||
UNDEFINED_OFFSET, UNDEFINED_OFFSET,
|
||||
resolvedTargetField.symbol,
|
||||
targetField.symbol,
|
||||
maybeDispatchReceiver,
|
||||
value,
|
||||
context.irBuiltIns.unitType
|
||||
@@ -574,8 +571,7 @@ internal class SyntheticAccessorLowering(val context: JvmBackendContext) : IrEle
|
||||
val symbolOwner = owner
|
||||
val declarationRaw = symbolOwner as IrDeclarationWithVisibility
|
||||
val declaration =
|
||||
(declarationRaw as? IrSimpleFunction)?.resolveFakeOverride()
|
||||
?: (declarationRaw as? IrField)?.resolveFakeOverride() ?: declarationRaw
|
||||
(declarationRaw as? IrSimpleFunction)?.resolveFakeOverride() ?: declarationRaw
|
||||
|
||||
// There is never a problem with visibility of inline functions, as those don't end up as Java entities
|
||||
if (declaration is IrFunction && declaration.isInline) return true
|
||||
|
||||
@@ -77,6 +77,18 @@ val PropertyDescriptor.unwrappedGetMethod: FunctionDescriptor?
|
||||
val PropertyDescriptor.unwrappedSetMethod: FunctionDescriptor?
|
||||
get() = if (this is SyntheticPropertyDescriptor) this.setMethod else setter
|
||||
|
||||
// Only works for descriptors of Java fields.
|
||||
internal fun PropertyDescriptor.resolveFakeOverride(): PropertyDescriptor {
|
||||
assert(getter == null)
|
||||
// Fields can only be inherited from objects, so there will be at most one overridden descriptor at each step.
|
||||
var current = this
|
||||
while (current.kind == CallableMemberDescriptor.Kind.FAKE_OVERRIDE) {
|
||||
current = current.overriddenDescriptors.singleOrNull()
|
||||
?: error("Descriptor of Java field $current should have exactly one overridden descriptor, have ${current.overriddenDescriptors}")
|
||||
}
|
||||
return current
|
||||
}
|
||||
|
||||
val KtPureElement?.pureStartOffsetOrUndefined get() = this?.psiOrParent?.startOffsetSkippingComments ?: UNDEFINED_OFFSET
|
||||
val KtPureElement?.pureEndOffsetOrUndefined get() = this?.psiOrParent?.endOffset ?: UNDEFINED_OFFSET
|
||||
|
||||
|
||||
@@ -31,6 +31,7 @@ import org.jetbrains.kotlin.psi.*
|
||||
import org.jetbrains.kotlin.psi.psiUtil.endOffset
|
||||
import org.jetbrains.kotlin.psi.psiUtil.startOffsetSkippingComments
|
||||
import org.jetbrains.kotlin.psi2ir.intermediate.*
|
||||
import org.jetbrains.kotlin.psi2ir.resolveFakeOverride
|
||||
import org.jetbrains.kotlin.psi2ir.unwrappedGetMethod
|
||||
import org.jetbrains.kotlin.psi2ir.unwrappedSetMethod
|
||||
import org.jetbrains.kotlin.resolve.BindingContext
|
||||
@@ -309,7 +310,6 @@ class AssignmentGenerator(statementGenerator: StatementGenerator) : StatementGen
|
||||
origin: IrStatementOrigin?,
|
||||
superQualifier: ClassDescriptor?
|
||||
): PropertyLValueBase {
|
||||
val superQualifierSymbol = superQualifier?.let { context.symbolTable.referenceClass(it) }
|
||||
|
||||
val unwrappedPropertyDescriptor = descriptor.unwrapPropertyDescriptor()
|
||||
val getterDescriptor = unwrappedPropertyDescriptor.unwrappedGetMethod
|
||||
@@ -320,6 +320,7 @@ class AssignmentGenerator(statementGenerator: StatementGenerator) : StatementGen
|
||||
|
||||
val propertyIrType = descriptor.type.toIrType()
|
||||
return if (getterSymbol != null || setterSymbol != null) {
|
||||
val superQualifierSymbol = superQualifier?.let { context.symbolTable.referenceClass(it) }
|
||||
val typeArgumentsList =
|
||||
typeArgumentsMap?.let { typeArguments ->
|
||||
descriptor.original.typeParameters.map { typeArguments[it]!!.toIrType() }
|
||||
@@ -341,17 +342,20 @@ class AssignmentGenerator(statementGenerator: StatementGenerator) : StatementGen
|
||||
propertyReceiver,
|
||||
superQualifierSymbol
|
||||
)
|
||||
} else
|
||||
} else {
|
||||
val superQualifierSymbol = (superQualifier
|
||||
?: unwrappedPropertyDescriptor.containingDeclaration as? ClassDescriptor)?.let { context.symbolTable.referenceClass(it) }
|
||||
FieldPropertyLValue(
|
||||
context,
|
||||
scope,
|
||||
ktExpression.startOffsetSkippingComments, ktExpression.endOffset, origin,
|
||||
context.symbolTable.referenceField(unwrappedPropertyDescriptor.original),
|
||||
context.symbolTable.referenceField(unwrappedPropertyDescriptor.resolveFakeOverride().original),
|
||||
unwrappedPropertyDescriptor,
|
||||
propertyIrType,
|
||||
propertyReceiver,
|
||||
superQualifierSymbol
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
private fun generateArrayAccessAssignmentReceiver(
|
||||
|
||||
@@ -29,6 +29,7 @@ import org.jetbrains.kotlin.psi.KtElement
|
||||
import org.jetbrains.kotlin.psi.psiUtil.endOffset
|
||||
import org.jetbrains.kotlin.psi.psiUtil.startOffsetSkippingComments
|
||||
import org.jetbrains.kotlin.psi2ir.intermediate.*
|
||||
import org.jetbrains.kotlin.psi2ir.resolveFakeOverride
|
||||
import org.jetbrains.kotlin.psi2ir.unwrappedGetMethod
|
||||
import org.jetbrains.kotlin.resolve.calls.model.ResolvedCall
|
||||
import org.jetbrains.kotlin.resolve.calls.model.ResolvedValueArgument
|
||||
@@ -174,12 +175,14 @@ class CallGenerator(statementGenerator: StatementGenerator) : StatementGenerator
|
||||
call: CallBuilder
|
||||
): IrExpression {
|
||||
val getMethodDescriptor = descriptor.unwrappedGetMethod
|
||||
val superQualifierSymbol = call.superQualifier?.let { context.symbolTable.referenceClass(it) }
|
||||
val irType = descriptor.type.toIrType()
|
||||
|
||||
return if (getMethodDescriptor == null) {
|
||||
call.callReceiver.call { dispatchReceiverValue, _ ->
|
||||
val fieldSymbol = context.symbolTable.referenceField(descriptor.original)
|
||||
val superQualifierSymbol = (call.superQualifier ?: descriptor.containingDeclaration as? ClassDescriptor)?.let {
|
||||
context.symbolTable.referenceClass(it)
|
||||
}
|
||||
val fieldSymbol = context.symbolTable.referenceField(descriptor.resolveFakeOverride().original)
|
||||
IrGetFieldImpl(
|
||||
startOffset, endOffset,
|
||||
fieldSymbol,
|
||||
@@ -190,6 +193,7 @@ class CallGenerator(statementGenerator: StatementGenerator) : StatementGenerator
|
||||
).also { context.callToSubstitutedDescriptorMap[it] = descriptor }
|
||||
}
|
||||
} else {
|
||||
val superQualifierSymbol = call.superQualifier?.let { context.symbolTable.referenceClass(it) }
|
||||
call.callReceiver.adjustForCallee(getMethodDescriptor).call { dispatchReceiverValue, extensionReceiverValue ->
|
||||
if (descriptor.isDynamic()) {
|
||||
val dispatchReceiver = getDynamicExpressionReceiver(dispatchReceiverValue, extensionReceiverValue, descriptor)
|
||||
|
||||
@@ -24,7 +24,6 @@ import org.jetbrains.kotlin.ir.expressions.IrExpressionBody
|
||||
import org.jetbrains.kotlin.ir.expressions.IrStatementOrigin
|
||||
import org.jetbrains.kotlin.ir.expressions.impl.IrExpressionBodyImpl
|
||||
import org.jetbrains.kotlin.ir.expressions.impl.IrGetValueImpl
|
||||
import org.jetbrains.kotlin.ir.util.declareFieldWithOverrides
|
||||
import org.jetbrains.kotlin.psi.*
|
||||
import org.jetbrains.kotlin.psi.psiUtil.endOffset
|
||||
import org.jetbrains.kotlin.psi.psiUtil.startOffsetSkippingComments
|
||||
@@ -145,17 +144,7 @@ class PropertyGenerator(declarationGenerator: DeclarationGenerator) : Declaratio
|
||||
val startOffset = ktElement.pureStartOffsetOrUndefined
|
||||
val endOffset = ktElement.pureEndOffsetOrUndefined
|
||||
|
||||
val backingField =
|
||||
if (propertyDescriptor.actuallyHasBackingField(context.bindingContext) && propertyDescriptor.fieldVisibility.admitsFakeOverride)
|
||||
context.symbolTable.declareFieldWithOverrides(
|
||||
startOffset, endOffset, IrDeclarationOrigin.FAKE_OVERRIDE,
|
||||
propertyDescriptor, propertyDescriptor.type.toIrType()
|
||||
) { it.actuallyHasBackingField(context.bindingContext) }
|
||||
else
|
||||
null
|
||||
|
||||
return context.symbolTable.declareProperty(startOffset, endOffset, IrDeclarationOrigin.FAKE_OVERRIDE, propertyDescriptor).apply {
|
||||
this.backingField = backingField
|
||||
this.getter = propertyDescriptor.getter?.let {
|
||||
FunctionGenerator(declarationGenerator).generateFakeOverrideFunction(it, ktElement)
|
||||
}
|
||||
|
||||
@@ -16,7 +16,6 @@ class IrFieldBuilder : IrDeclarationBuilder() {
|
||||
var isFinal: Boolean = false
|
||||
var isExternal: Boolean = false
|
||||
var isStatic: Boolean = false
|
||||
var isFakeOverride: Boolean = false
|
||||
var metadata: MetadataSource? = null
|
||||
|
||||
fun updateFrom(from: IrField) {
|
||||
@@ -26,7 +25,6 @@ class IrFieldBuilder : IrDeclarationBuilder() {
|
||||
isFinal = from.isFinal
|
||||
isExternal = from.isExternal
|
||||
isStatic = from.isStatic
|
||||
isFakeOverride = from.isFakeOverride
|
||||
metadata = from.metadata
|
||||
}
|
||||
}
|
||||
|
||||
@@ -13,7 +13,7 @@ import org.jetbrains.kotlin.ir.symbols.IrPropertySymbol
|
||||
import org.jetbrains.kotlin.ir.types.IrType
|
||||
|
||||
interface IrField :
|
||||
IrSymbolDeclaration<IrFieldSymbol>, IrOverridableDeclaration<IrFieldSymbol>,
|
||||
IrSymbolDeclaration<IrFieldSymbol>,
|
||||
IrDeclarationWithName, IrDeclarationWithVisibility, IrDeclarationParent {
|
||||
|
||||
@ObsoleteDescriptorBasedAPI
|
||||
@@ -23,7 +23,6 @@ interface IrField :
|
||||
val isFinal: Boolean
|
||||
val isExternal: Boolean
|
||||
val isStatic: Boolean
|
||||
val isFakeOverride: Boolean
|
||||
|
||||
var initializer: IrExpressionBody?
|
||||
|
||||
|
||||
@@ -42,8 +42,7 @@ class IrFieldImpl(
|
||||
override val visibility: Visibility,
|
||||
override val isFinal: Boolean,
|
||||
override val isExternal: Boolean,
|
||||
override val isStatic: Boolean,
|
||||
override val isFakeOverride: Boolean = origin == IrDeclarationOrigin.FAKE_OVERRIDE
|
||||
override val isStatic: Boolean
|
||||
) : IrDeclarationBase<FieldCarrier>(startOffset, endOffset, origin),
|
||||
IrField,
|
||||
FieldCarrier {
|
||||
@@ -96,16 +95,6 @@ class IrFieldImpl(
|
||||
}
|
||||
}
|
||||
|
||||
override var overridenSymbolsField: List<IrFieldSymbol> = emptyList()
|
||||
|
||||
override var overriddenSymbols: List<IrFieldSymbol>
|
||||
get() = getCarrier().overridenSymbolsField
|
||||
set(v) {
|
||||
if (overriddenSymbols !== v) {
|
||||
setCarrier().overridenSymbolsField = v
|
||||
}
|
||||
}
|
||||
|
||||
override var metadataField: MetadataSource? = null
|
||||
|
||||
override var metadata: MetadataSource?
|
||||
|
||||
@@ -10,14 +10,12 @@ import org.jetbrains.kotlin.ir.declarations.IrDeclarationParent
|
||||
import org.jetbrains.kotlin.ir.declarations.MetadataSource
|
||||
import org.jetbrains.kotlin.ir.expressions.IrConstructorCall
|
||||
import org.jetbrains.kotlin.ir.expressions.IrExpressionBody
|
||||
import org.jetbrains.kotlin.ir.symbols.IrFieldSymbol
|
||||
import org.jetbrains.kotlin.ir.symbols.IrPropertySymbol
|
||||
|
||||
interface FieldCarrier : DeclarationCarrier<FieldCarrier> {
|
||||
var initializerField: IrExpressionBody?
|
||||
var correspondingPropertySymbolField: IrPropertySymbol?
|
||||
var metadataField: MetadataSource?
|
||||
var overridenSymbolsField: List<IrFieldSymbol>
|
||||
|
||||
override fun clone(): FieldCarrier {
|
||||
return FieldCarrierImpl(
|
||||
@@ -27,8 +25,7 @@ interface FieldCarrier : DeclarationCarrier<FieldCarrier> {
|
||||
annotationsField,
|
||||
initializerField,
|
||||
correspondingPropertySymbolField,
|
||||
metadataField,
|
||||
overridenSymbolsField
|
||||
metadataField
|
||||
)
|
||||
}
|
||||
}
|
||||
@@ -40,6 +37,5 @@ class FieldCarrierImpl(
|
||||
override var annotationsField: List<IrConstructorCall>,
|
||||
override var initializerField: IrExpressionBody?,
|
||||
override var correspondingPropertySymbolField: IrPropertySymbol?,
|
||||
override var metadataField: MetadataSource?,
|
||||
override var overridenSymbolsField: List<IrFieldSymbol>
|
||||
override var metadataField: MetadataSource?
|
||||
): FieldCarrier
|
||||
@@ -35,7 +35,6 @@ class IrLazyField(
|
||||
override val isFinal: Boolean,
|
||||
override val isExternal: Boolean,
|
||||
override val isStatic: Boolean,
|
||||
override val isFakeOverride: Boolean,
|
||||
stubGenerator: DeclarationStubGenerator,
|
||||
typeTranslator: TypeTranslator
|
||||
) : IrLazyDeclarationBase(startOffset, endOffset, origin, stubGenerator, typeTranslator),
|
||||
@@ -51,12 +50,6 @@ class IrLazyField(
|
||||
?: mutableListOf()
|
||||
}
|
||||
|
||||
override var overriddenSymbols: List<IrFieldSymbol> by lazyVar {
|
||||
symbol.descriptor.overriddenDescriptors.map {
|
||||
stubGenerator.generateFieldStub(it.original).symbol
|
||||
}.toMutableList()
|
||||
}
|
||||
|
||||
override var type: IrType by lazyVar {
|
||||
descriptor.type.toIrType()
|
||||
}
|
||||
|
||||
@@ -991,8 +991,7 @@ open class WrappedFieldDescriptor(
|
||||
|
||||
override fun hasSynthesizedParameterNames() = false
|
||||
|
||||
override fun getOverriddenDescriptors(): MutableCollection<out PropertyDescriptor> =
|
||||
owner.overriddenSymbols.map { it.descriptor }.toMutableList()
|
||||
override fun getOverriddenDescriptors(): MutableCollection<out PropertyDescriptor> = mutableListOf()
|
||||
|
||||
override fun copy(
|
||||
newOwner: DeclarationDescriptor?,
|
||||
|
||||
@@ -112,7 +112,7 @@ interface IrTypeSystemContext : TypeSystemContext, TypeSystemCommonSuperTypesCon
|
||||
private fun getTypeParameters(typeConstructor: TypeConstructorMarker): List<IrTypeParameter> {
|
||||
return when (typeConstructor) {
|
||||
is IrTypeParameterSymbol -> emptyList()
|
||||
is IrClassSymbol -> typeConstructor.owner.typeParameters
|
||||
is IrClassSymbol -> extractTypeParameters(typeConstructor.owner)
|
||||
else -> error("unsupported type constructor")
|
||||
}
|
||||
}
|
||||
|
||||
@@ -78,18 +78,6 @@ fun IrSimpleFunction.overrides(other: IrSimpleFunction): Boolean {
|
||||
return false
|
||||
}
|
||||
|
||||
fun IrField.overrides(other: IrField): Boolean {
|
||||
if (this == other) return true
|
||||
|
||||
this.overriddenSymbols.forEach {
|
||||
if (it.owner.overrides(other)) {
|
||||
return true
|
||||
}
|
||||
}
|
||||
|
||||
return false
|
||||
}
|
||||
|
||||
private val IrConstructorCall.annotationClass
|
||||
get() = this.symbol.owner.constructedClass
|
||||
|
||||
|
||||
@@ -173,20 +173,14 @@ class DeclarationStubGenerator(
|
||||
return referenced.owner
|
||||
}
|
||||
|
||||
val origin =
|
||||
if (descriptor.kind == CallableMemberDescriptor.Kind.FAKE_OVERRIDE)
|
||||
IrDeclarationOrigin.FAKE_OVERRIDE
|
||||
else computeOrigin(descriptor)
|
||||
|
||||
return symbolTable.declareField(UNDEFINED_OFFSET, UNDEFINED_OFFSET, origin, descriptor.original, descriptor.type.toIrType()) {
|
||||
return symbolTable.declareField(UNDEFINED_OFFSET, UNDEFINED_OFFSET, computeOrigin(descriptor), descriptor.original, descriptor.type.toIrType()) {
|
||||
IrLazyField(
|
||||
UNDEFINED_OFFSET, UNDEFINED_OFFSET, origin,
|
||||
UNDEFINED_OFFSET, UNDEFINED_OFFSET, computeOrigin(descriptor),
|
||||
it, descriptor,
|
||||
descriptor.name, descriptor.visibility,
|
||||
isFinal = !descriptor.isVar,
|
||||
isExternal = descriptor.isEffectivelyExternal(),
|
||||
isStatic = (descriptor.dispatchReceiverParameter == null),
|
||||
isFakeOverride = (origin == IrDeclarationOrigin.FAKE_OVERRIDE),
|
||||
stubGenerator = this, typeTranslator = typeTranslator
|
||||
)
|
||||
}
|
||||
|
||||
@@ -245,12 +245,8 @@ open class DeepCopyIrTreeWithSymbols(
|
||||
isFinal = declaration.isFinal,
|
||||
isExternal = declaration.isExternal,
|
||||
isStatic = declaration.isStatic,
|
||||
isFakeOverride = declaration.isFakeOverride
|
||||
).apply {
|
||||
transformAnnotations(declaration)
|
||||
overriddenSymbols = declaration.overriddenSymbols.map {
|
||||
symbolRemapper.getReferencedField(it)
|
||||
}
|
||||
initializer = declaration.initializer?.transform()
|
||||
}
|
||||
|
||||
|
||||
@@ -145,9 +145,6 @@ class DumpIrTreeVisitor(
|
||||
override fun visitField(declaration: IrField, data: String) {
|
||||
declaration.dumpLabeledElementWith(data) {
|
||||
dumpAnnotations(declaration)
|
||||
declaration.overriddenSymbols.dumpItems("overridden") {
|
||||
it.dump()
|
||||
}
|
||||
declaration.initializer?.accept(this, "")
|
||||
}
|
||||
}
|
||||
|
||||
@@ -15,7 +15,6 @@ val IrDeclaration.isFakeOverride: Boolean
|
||||
get() = when (this) {
|
||||
is IrSimpleFunction -> isFakeOverride
|
||||
is IrProperty -> isFakeOverride
|
||||
is IrField -> isFakeOverride
|
||||
else -> false
|
||||
}
|
||||
|
||||
@@ -31,15 +30,6 @@ val IrFunction.target: IrFunction get() = when (this) {
|
||||
else -> error(this)
|
||||
}
|
||||
|
||||
fun IrField.resolveFakeOverride(): IrField? {
|
||||
var toVisit = setOf(this)
|
||||
val nonOverridden = mutableSetOf<IrField>()
|
||||
while (toVisit.isNotEmpty()) {
|
||||
nonOverridden += toVisit.filter { it.overriddenSymbols.isEmpty() }
|
||||
toVisit = toVisit.flatMap { it.overriddenSymbols }.map { it.owner }.toSet()
|
||||
}
|
||||
return nonOverridden.singleOrNull()
|
||||
}
|
||||
fun IrSimpleFunction.collectRealOverrides(toSkip: (IrSimpleFunction) -> Boolean = { false }): Set<IrSimpleFunction> {
|
||||
if (isReal && !toSkip(this)) return setOf(this)
|
||||
|
||||
|
||||
@@ -265,6 +265,8 @@ fun IrSimpleFunction.findInterfaceImplementation(): IrSimpleFunction? {
|
||||
return resolveFakeOverride()?.run { if (parentAsClass.isInterface) this else null }
|
||||
}
|
||||
|
||||
fun IrProperty.resolveFakeOverride(): IrProperty? = getter?.resolveFakeOverride()?.correspondingPropertySymbol?.owner
|
||||
|
||||
val IrClass.isAnnotationClass get() = kind == ClassKind.ANNOTATION_CLASS
|
||||
val IrClass.isEnumClass get() = kind == ClassKind.ENUM_CLASS
|
||||
val IrClass.isEnumEntry get() = kind == ClassKind.ENUM_ENTRY
|
||||
|
||||
@@ -445,7 +445,6 @@ class RenderIrElementVisitor(private val normalizeNames: Boolean = false) : IrEl
|
||||
"final".takeIf { isFinal },
|
||||
"external".takeIf { isExternal },
|
||||
"static".takeIf { isStatic },
|
||||
"fake_override".takeIf { isFakeOverride }
|
||||
)
|
||||
|
||||
override fun visitClass(declaration: IrClass, data: Nothing?): String =
|
||||
|
||||
@@ -45,29 +45,3 @@ fun generateOverriddenFunctionSymbols(
|
||||
symbolTable.referenceSimpleFunction(it.original)
|
||||
}
|
||||
}
|
||||
|
||||
@ObsoleteDescriptorBasedAPI
|
||||
fun SymbolTable.declareFieldWithOverrides(
|
||||
startOffset: Int,
|
||||
endOffset: Int,
|
||||
origin: IrDeclarationOrigin,
|
||||
descriptor: PropertyDescriptor,
|
||||
type: IrType,
|
||||
hasBackingField: (PropertyDescriptor) -> Boolean
|
||||
) =
|
||||
declareField(startOffset, endOffset, origin, descriptor, type).also { declaration ->
|
||||
generateOverriddenFieldSymbols(declaration, this, hasBackingField)
|
||||
}
|
||||
|
||||
@ObsoleteDescriptorBasedAPI
|
||||
fun generateOverriddenFieldSymbols(
|
||||
declaration: IrField,
|
||||
symbolTable: SymbolTable,
|
||||
hasBackingField: (PropertyDescriptor) -> Boolean
|
||||
) {
|
||||
declaration.overriddenSymbols = declaration.descriptor.overriddenDescriptors.mapNotNull {
|
||||
if (hasBackingField(it)) {
|
||||
symbolTable.referenceField(it.original)
|
||||
} else null
|
||||
}
|
||||
}
|
||||
@@ -1234,7 +1234,6 @@ abstract class IrFileDeserializer(val logger: LoggingContext, val builtIns: IrBu
|
||||
flags.isFinal,
|
||||
flags.isExternal,
|
||||
flags.isStatic,
|
||||
flags.isFakeOverride
|
||||
)
|
||||
}.usingParent {
|
||||
if (proto.hasInitializer())
|
||||
|
||||
@@ -69,15 +69,13 @@ public class IrFlags extends Flags {
|
||||
ProtoBuf.Visibility visibility,
|
||||
boolean isFinal,
|
||||
boolean isExternal,
|
||||
boolean isStatic,
|
||||
boolean isFakeOverride
|
||||
boolean isStatic
|
||||
) {
|
||||
return HAS_ANNOTATIONS.toFlags(hasAnnotations)
|
||||
| VISIBILITY.toFlags(visibility)
|
||||
| IS_FINAL.toFlags(isFinal)
|
||||
| IS_EXTERNAL_FIELD.toFlags(isExternal)
|
||||
| IS_STATIC.toFlags(isStatic)
|
||||
| IS_FAKE_OVERRIDE.toFlags(isFakeOverride)
|
||||
;
|
||||
}
|
||||
|
||||
|
||||
@@ -191,13 +191,12 @@ inline class FieldFlags(val flags: Long) {
|
||||
val isFinal: Boolean get() = IrFlags.IS_FINAL.get(flags.toInt())
|
||||
val isExternal: Boolean get() = IrFlags.IS_EXTERNAL_FIELD.get(flags.toInt())
|
||||
val isStatic: Boolean get() = IrFlags.IS_STATIC.get(flags.toInt())
|
||||
val isFakeOverride: Boolean get() = IrFlags.IS_FAKE_OVERRIDE.get(flags.toInt())
|
||||
|
||||
companion object {
|
||||
fun encode(field: IrField): Long {
|
||||
return field.run {
|
||||
val visibility = ProtoEnumFlags.visibility(visibility)
|
||||
IrFlags.getFieldFlags(annotations.isNotEmpty(), visibility, isFinal, isExternal, isStatic, isFakeOverride).toLong()
|
||||
IrFlags.getFieldFlags(annotations.isNotEmpty(), visibility, isFinal, isExternal, isStatic).toLong()
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -28,6 +28,7 @@ import org.jetbrains.kotlin.types.model.typeConstructor
|
||||
import org.jetbrains.kotlin.types.typeUtil.contains
|
||||
import org.jetbrains.kotlin.types.typeUtil.makeNotNullable
|
||||
import org.jetbrains.kotlin.types.typeUtil.makeNullable
|
||||
import org.jetbrains.kotlin.utils.SmartList
|
||||
import org.jetbrains.kotlin.utils.addToStdlib.safeAs
|
||||
|
||||
internal object CheckVisibility : ResolutionPart() {
|
||||
@@ -314,27 +315,28 @@ internal object CollectionTypeVariableUsagesInfo : ResolutionPart() {
|
||||
dependentTypeParametersSeen: List<Pair<TypeConstructorMarker, KotlinTypeMarker?>> = listOf()
|
||||
): List<Pair<TypeConstructorMarker, KotlinTypeMarker?>> {
|
||||
val context = asConstraintSystemCompleterContext()
|
||||
val dependentTypeParameters = getBuilder().currentStorage().notFixedTypeVariables.mapNotNull { (typeConstructor, constraints) ->
|
||||
val upperBounds = constraints.constraints.filter {
|
||||
it.position.from is DeclaredUpperBoundConstraintPosition && it.kind == ConstraintKind.UPPER
|
||||
}
|
||||
val dependentTypeParameters = getBuilder().currentStorage().notFixedTypeVariables.asSequence()
|
||||
.flatMap { (typeConstructor, constraints) ->
|
||||
val upperBounds = constraints.constraints.filter {
|
||||
it.position.from is DeclaredUpperBoundConstraintPosition && it.kind == ConstraintKind.UPPER
|
||||
}
|
||||
|
||||
upperBounds.mapNotNull { constraint ->
|
||||
if (constraint.type.typeConstructor(context) != variable) {
|
||||
val suitableUpperBound = upperBounds.find { upperBound ->
|
||||
with(context) { upperBound.type.contains { it.typeConstructor() == variable } }
|
||||
}?.type
|
||||
upperBounds.mapNotNull { constraint ->
|
||||
if (constraint.type.typeConstructor(context) != variable) {
|
||||
val suitableUpperBound = upperBounds.find { upperBound ->
|
||||
with(context) { upperBound.type.contains { it.typeConstructor() == variable } }
|
||||
}?.type
|
||||
|
||||
if (suitableUpperBound != null) typeConstructor to suitableUpperBound else null
|
||||
} else typeConstructor to null
|
||||
}
|
||||
}.flatten().filter { it !in dependentTypeParametersSeen && it.first != variable }
|
||||
if (suitableUpperBound != null) typeConstructor to suitableUpperBound else null
|
||||
} else typeConstructor to null
|
||||
}
|
||||
}.filter { it !in dependentTypeParametersSeen && it.first != variable }.toList()
|
||||
|
||||
return dependentTypeParameters + dependentTypeParameters.mapNotNull { (typeConstructor, _) ->
|
||||
return dependentTypeParameters + dependentTypeParameters.flatMapTo(SmartList()) { (typeConstructor, _) ->
|
||||
if (typeConstructor != variable) {
|
||||
getDependentTypeParameters(typeConstructor, dependentTypeParameters + dependentTypeParametersSeen)
|
||||
} else null
|
||||
}.flatten()
|
||||
} else emptyList()
|
||||
}
|
||||
}
|
||||
|
||||
private fun NewConstraintSystem.isContainedInInvariantOrContravariantPositionsAmongUpperBound(
|
||||
|
||||
@@ -9,6 +9,7 @@ import org.jetbrains.kotlin.resolve.calls.components.CreateFreshVariablesSubstit
|
||||
import org.jetbrains.kotlin.resolve.calls.inference.model.*
|
||||
import org.jetbrains.kotlin.types.*
|
||||
import org.jetbrains.kotlin.types.model.*
|
||||
import org.jetbrains.kotlin.utils.SmartList
|
||||
import org.jetbrains.kotlin.utils.SmartSet
|
||||
import org.jetbrains.kotlin.utils.addIfNotNull
|
||||
import org.jetbrains.kotlin.utils.addToStdlib.safeAs
|
||||
@@ -98,7 +99,7 @@ class ConstraintIncorporator(
|
||||
|
||||
for (otherTypeVariable in otherInMyConstraint) {
|
||||
// to avoid ConcurrentModificationException
|
||||
val otherConstraints = ArrayList(this.getConstraintsForVariable(otherTypeVariable))
|
||||
val otherConstraints = SmartList(this.getConstraintsForVariable(otherTypeVariable))
|
||||
for (otherConstraint in otherConstraints) {
|
||||
generateNewConstraint(typeVariable, constraint, otherTypeVariable, otherConstraint)
|
||||
}
|
||||
@@ -230,7 +231,7 @@ class ConstraintIncorporator(
|
||||
)
|
||||
) return
|
||||
|
||||
val derivedFrom = (baseConstraint.derivedFrom + otherConstraint.derivedFrom).toMutableSet()
|
||||
val derivedFrom = SmartSet.create(baseConstraint.derivedFrom).also { it.addAll(otherConstraint.derivedFrom) }
|
||||
if (otherVariable in derivedFrom) return
|
||||
|
||||
derivedFrom.add(otherVariable)
|
||||
@@ -273,7 +274,7 @@ class ConstraintIncorporator(
|
||||
}
|
||||
|
||||
fun Context.getNestedTypeVariables(type: KotlinTypeMarker): List<TypeVariableMarker> =
|
||||
getNestedArguments(type).mapNotNull { getTypeVariable(it.getType().typeConstructor()) }
|
||||
getNestedArguments(type).mapNotNullTo(SmartList()) { getTypeVariable(it.getType().typeConstructor()) }
|
||||
|
||||
|
||||
private fun KotlinTypeMarker.substitute(c: Context, typeVariable: TypeVariableMarker, value: KotlinTypeMarker): KotlinTypeMarker {
|
||||
@@ -288,7 +289,7 @@ class ConstraintIncorporator(
|
||||
}
|
||||
|
||||
private fun TypeSystemInferenceExtensionContext.getNestedArguments(type: KotlinTypeMarker): List<TypeArgumentMarker> {
|
||||
val result = ArrayList<TypeArgumentMarker>()
|
||||
val result = SmartList<TypeArgumentMarker>()
|
||||
val stack = ArrayDeque<TypeArgumentMarker>()
|
||||
|
||||
when (type) {
|
||||
|
||||
@@ -13,6 +13,7 @@ import org.jetbrains.kotlin.types.*
|
||||
import org.jetbrains.kotlin.types.typeUtil.asTypeProjection
|
||||
import org.jetbrains.kotlin.types.typeUtil.builtIns
|
||||
import org.jetbrains.kotlin.descriptors.annotations.Annotations
|
||||
import org.jetbrains.kotlin.utils.SmartSet
|
||||
import org.jetbrains.kotlin.utils.addToStdlib.safeAs
|
||||
|
||||
class PostponedArgumentInputTypesResolver(
|
||||
@@ -21,7 +22,7 @@ class PostponedArgumentInputTypesResolver(
|
||||
) {
|
||||
interface Context : KotlinConstraintSystemCompleter.Context
|
||||
|
||||
data class ParameterTypesInfo(
|
||||
private class ParameterTypesInfo(
|
||||
val parametersFromDeclaration: List<UnwrappedType?>?,
|
||||
val parametersFromDeclarationOfRelatedLambdas: Set<List<UnwrappedType?>>?,
|
||||
val parametersFromConstraints: Set<List<TypeWithKind>>?,
|
||||
@@ -48,11 +49,11 @@ class PostponedArgumentInputTypesResolver(
|
||||
val dependentVariables =
|
||||
variableDependencyProvider.getShallowlyDependentVariables(typeVariableTypeConstructor).orEmpty() + typeVariableTypeConstructor
|
||||
|
||||
return dependentVariables.mapNotNull { type ->
|
||||
val constraints = notFixedTypeVariables[type]?.constraints ?: return@mapNotNull null
|
||||
return dependentVariables.flatMap { type ->
|
||||
val constraints = notFixedTypeVariables[type]?.constraints ?: return@flatMap emptyList()
|
||||
val constraintsWithFunctionalType = constraints.filter { (it.type as? KotlinType)?.isBuiltinFunctionalTypeOrSubtype == true }
|
||||
constraintsWithFunctionalType.extractFunctionalTypes()
|
||||
}.flatten()
|
||||
}
|
||||
}
|
||||
|
||||
private fun extractParameterTypesFromDeclaration(atom: ResolutionAtom) =
|
||||
@@ -81,32 +82,42 @@ class PostponedArgumentInputTypesResolver(
|
||||
val parameterTypesFromDeclaration =
|
||||
if (argument is LambdaWithTypeVariableAsExpectedTypeAtom) argument.parameterTypesFromDeclaration else null
|
||||
|
||||
val parameterTypesFromConstraints = functionalTypesFromConstraints?.map { typeWithKind ->
|
||||
val parameterTypesFromConstraints = functionalTypesFromConstraints?.mapTo(SmartSet.create()) { typeWithKind ->
|
||||
typeWithKind.type.getPureArgumentsForFunctionalTypeOrSubtype().map {
|
||||
// We should use opposite kind as lambda's parameters are contravariant
|
||||
TypeWithKind(it, typeWithKind.direction.opposite())
|
||||
}
|
||||
}?.toSet()
|
||||
}
|
||||
|
||||
// An extension function flag can only come from a declaration of anonymous function: `select({ this + it }, fun Int.(x: Int) = 10)`
|
||||
val (parameterTypesFromDeclarationOfRelatedLambdas, isThereExtensionFunctionAmongRelatedLambdas) =
|
||||
getDeclaredParametersFromRelatedLambdas(argument, postponedArguments, variableDependencyProvider)
|
||||
|
||||
val annotationsFromConstraints = functionalTypesFromConstraints?.run {
|
||||
Annotations.create(map { it.type.annotations }.flatten())
|
||||
Annotations.create(flatMap { it.type.annotations })
|
||||
} ?: Annotations.EMPTY
|
||||
|
||||
val annotations = if (isThereExtensionFunctionAmongRelatedLambdas) {
|
||||
annotationsFromConstraints.withExtensionFunctionAnnotation(expectedType.builtIns)
|
||||
} else annotationsFromConstraints
|
||||
|
||||
var isSuspend = false
|
||||
var isNullable = false
|
||||
if (!functionalTypesFromConstraints.isNullOrEmpty()) {
|
||||
isNullable = true
|
||||
for (funType in functionalTypesFromConstraints) {
|
||||
if (!isSuspend && funType.type.isSuspendFunctionTypeOrSubtype) isSuspend = true
|
||||
if (isNullable && !funType.type.isMarkedNullable) isNullable = false
|
||||
if (isSuspend && !isNullable) break
|
||||
}
|
||||
}
|
||||
return ParameterTypesInfo(
|
||||
parameterTypesFromDeclaration,
|
||||
parameterTypesFromDeclarationOfRelatedLambdas,
|
||||
parameterTypesFromConstraints,
|
||||
annotations,
|
||||
isSuspend = !functionalTypesFromConstraints.isNullOrEmpty() && functionalTypesFromConstraints.any { it.type.isSuspendFunctionTypeOrSubtype },
|
||||
isNullable = !functionalTypesFromConstraints.isNullOrEmpty() && functionalTypesFromConstraints.all { it.type.isMarkedNullable }
|
||||
isSuspend = isSuspend,
|
||||
isNullable = isNullable
|
||||
)
|
||||
}
|
||||
|
||||
@@ -116,24 +127,28 @@ class PostponedArgumentInputTypesResolver(
|
||||
dependencyProvider: TypeVariableDependencyInformationProvider
|
||||
): Pair<Set<List<UnwrappedType?>>?, Boolean> {
|
||||
val parameterTypesFromDeclarationOfRelatedLambdas = postponedArguments
|
||||
.filterIsInstance<LambdaWithTypeVariableAsExpectedTypeAtom>()
|
||||
.filter { it.parameterTypesFromDeclaration != null && it != argument }
|
||||
.mapNotNull { anotherArgument ->
|
||||
val argumentExpectedTypeConstructor = argument.expectedType?.typeConstructor() ?: return@mapNotNull null
|
||||
val anotherArgumentExpectedTypeConstructor = anotherArgument.expectedType.typeConstructor()
|
||||
val areTypeVariablesRelated = dependencyProvider.areVariablesDependentShallowly(
|
||||
argumentExpectedTypeConstructor, anotherArgumentExpectedTypeConstructor
|
||||
)
|
||||
val anotherAtom = anotherArgument.atom
|
||||
val isAnonymousExtensionFunction = anotherAtom is FunctionExpression && anotherAtom.receiverType != null
|
||||
val parameterTypesFromDeclarationOfRelatedLambda = anotherArgument.parameterTypesFromDeclaration
|
||||
when {
|
||||
anotherArgument !is LambdaWithTypeVariableAsExpectedTypeAtom -> null
|
||||
anotherArgument.parameterTypesFromDeclaration == null || anotherArgument == argument -> null
|
||||
else -> {
|
||||
val argumentExpectedTypeConstructor = argument.expectedType?.typeConstructor() ?: return@mapNotNull null
|
||||
val anotherArgumentExpectedTypeConstructor = anotherArgument.expectedType.typeConstructor()
|
||||
val areTypeVariablesRelated = dependencyProvider.areVariablesDependentShallowly(
|
||||
argumentExpectedTypeConstructor, anotherArgumentExpectedTypeConstructor
|
||||
)
|
||||
val anotherAtom = anotherArgument.atom
|
||||
val isAnonymousExtensionFunction = anotherAtom is FunctionExpression && anotherAtom.receiverType != null
|
||||
val parameterTypesFromDeclarationOfRelatedLambda = anotherArgument.parameterTypesFromDeclaration
|
||||
|
||||
if (areTypeVariablesRelated && parameterTypesFromDeclarationOfRelatedLambda != null) {
|
||||
parameterTypesFromDeclarationOfRelatedLambda to isAnonymousExtensionFunction
|
||||
} else null
|
||||
if (areTypeVariablesRelated && parameterTypesFromDeclarationOfRelatedLambda != null) {
|
||||
parameterTypesFromDeclarationOfRelatedLambda to isAnonymousExtensionFunction
|
||||
} else null
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return parameterTypesFromDeclarationOfRelatedLambdas.run { map { it.first }.toSet() to any { it.second } }
|
||||
return parameterTypesFromDeclarationOfRelatedLambdas.run { mapTo(SmartSet.create()) { it.first } to any { it.second } }
|
||||
}
|
||||
|
||||
private fun Context.createTypeVariableForReturnType(argument: PostponedAtomWithRevisableExpectedType): NewTypeVariable {
|
||||
@@ -186,7 +201,8 @@ class PostponedArgumentInputTypesResolver(
|
||||
return allGroupedParameterTypes.mapIndexed { index, types ->
|
||||
val parameterTypeVariable = createTypeVariableForParameterType(argument, index)
|
||||
|
||||
for (typeWithKind in types.filterNotNull()) {
|
||||
for (typeWithKind in types) {
|
||||
if (typeWithKind == null) continue
|
||||
when (typeWithKind.direction) {
|
||||
ConstraintKind.EQUALITY -> csBuilder.addEqualityConstraint(
|
||||
parameterTypeVariable.defaultType, typeWithKind.type, ArgumentConstraintPosition(atom)
|
||||
@@ -327,29 +343,23 @@ class PostponedArgumentInputTypesResolver(
|
||||
dependencyProvider: TypeVariableDependencyInformationProvider
|
||||
): Boolean {
|
||||
// We can collect parameter types from declaration in any mode, they can't change during completion.
|
||||
val postponedArgumentsToCollectTypesFromDeclaredParameters = postponedArguments
|
||||
.filterIsInstance<LambdaWithTypeVariableAsExpectedTypeAtom>()
|
||||
.filter { it.parameterTypesFromDeclaration == null }
|
||||
|
||||
for (argument in postponedArgumentsToCollectTypesFromDeclaredParameters) {
|
||||
for (argument in postponedArguments) {
|
||||
if (argument !is LambdaWithTypeVariableAsExpectedTypeAtom) continue
|
||||
if (argument.parameterTypesFromDeclaration != null) continue
|
||||
argument.parameterTypesFromDeclaration = extractParameterTypesFromDeclaration(argument.atom)
|
||||
}
|
||||
|
||||
/*
|
||||
* We can build new functional expected types in partial mode only for anonymous functions,
|
||||
* because more exact type can't appear from constraints in full mode (anonymous functions have fully explicit declaration).
|
||||
* It can be so for lambdas: for instance, an extension function type can appear in full mode (it may not be known in partial mode).
|
||||
*
|
||||
* TODO: investigate why we can't do it for anonymous functions in full mode always (see `diagnostics/tests/resolve/resolveWithSpecifiedFunctionLiteralWithId.kt`)
|
||||
*/
|
||||
val postponedArgumentsToCollectParameterTypesAndBuildNewExpectedType =
|
||||
if (completionMode == KotlinConstraintSystemCompleter.ConstraintSystemCompletionMode.PARTIAL) {
|
||||
postponedArguments.filter(::isAnonymousFunction)
|
||||
} else {
|
||||
postponedArguments
|
||||
}
|
||||
|
||||
return postponedArgumentsToCollectParameterTypesAndBuildNewExpectedType.filter { it.revisedExpectedType == null }.any { argument ->
|
||||
return postponedArguments.any { argument ->
|
||||
/*
|
||||
* We can build new functional expected types in partial mode only for anonymous functions,
|
||||
* because more exact type can't appear from constraints in full mode (anonymous functions have fully explicit declaration).
|
||||
* It can be so for lambdas: for instance, an extension function type can appear in full mode (it may not be known in partial mode).
|
||||
*
|
||||
* TODO: investigate why we can't do it for anonymous functions in full mode always (see `diagnostics/tests/resolve/resolveWithSpecifiedFunctionLiteralWithId.kt`)
|
||||
*/
|
||||
if (completionMode == KotlinConstraintSystemCompleter.ConstraintSystemCompletionMode.PARTIAL && !isAnonymousFunction(argument))
|
||||
return@any false
|
||||
if (argument.revisedExpectedType != null) return@any false
|
||||
val parameterTypesInfo =
|
||||
c.extractParameterTypesInfo(argument, postponedArguments, dependencyProvider) ?: return@any false
|
||||
val newExpectedType =
|
||||
@@ -393,26 +403,28 @@ class PostponedArgumentInputTypesResolver(
|
||||
listOf(typeConstructor) + relatedVariables.filterIsInstance<TypeVariableTypeConstructor>()
|
||||
}
|
||||
type.arguments.isNotEmpty() -> {
|
||||
type.arguments.map { getAllDeeplyRelatedTypeVariables(it.type, variableDependencyProvider) }.flatten()
|
||||
type.arguments.flatMap { getAllDeeplyRelatedTypeVariables(it.type, variableDependencyProvider) }
|
||||
}
|
||||
else -> listOf()
|
||||
else -> emptyList()
|
||||
}
|
||||
}
|
||||
|
||||
private fun getDeclaredParametersConsideringExtensionFunctionsPresence(parameterTypesInfo: ParameterTypesInfo): List<UnwrappedType?>? {
|
||||
val (parametersFromDeclaration, _, parametersFromConstraints, annotations) = parameterTypesInfo
|
||||
private fun getDeclaredParametersConsideringExtensionFunctionsPresence(parameterTypesInfo: ParameterTypesInfo): List<UnwrappedType?>? =
|
||||
with (parameterTypesInfo) {
|
||||
|
||||
if (parametersFromConstraints.isNullOrEmpty() || parametersFromDeclaration.isNullOrEmpty())
|
||||
return parametersFromDeclaration
|
||||
if (parametersFromConstraints.isNullOrEmpty() || parametersFromDeclaration.isNullOrEmpty())
|
||||
parametersFromDeclaration
|
||||
else {
|
||||
val oneLessParameterInDeclarationThanInConstraints =
|
||||
parametersFromConstraints.first().size == parametersFromDeclaration.size + 1
|
||||
|
||||
val oneLessParameterInDeclarationThanInConstraints = parametersFromConstraints.first().size == parametersFromDeclaration.size + 1
|
||||
|
||||
return if (oneLessParameterInDeclarationThanInConstraints && annotations.hasExtensionFunctionAnnotation()) {
|
||||
listOf(null) + parametersFromDeclaration
|
||||
} else {
|
||||
parametersFromDeclaration
|
||||
if (oneLessParameterInDeclarationThanInConstraints && annotations.hasExtensionFunctionAnnotation()) {
|
||||
listOf(null) + parametersFromDeclaration
|
||||
} else {
|
||||
parametersFromDeclaration
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fun fixNextReadyVariableForParameterTypeIfNeeded(
|
||||
c: Context,
|
||||
@@ -443,7 +455,7 @@ class PostponedArgumentInputTypesResolver(
|
||||
dependencyProvider: TypeVariableDependencyInformationProvider
|
||||
): Boolean {
|
||||
val relatedVariables = type.getPureArgumentsForFunctionalTypeOrSubtype()
|
||||
.map { getAllDeeplyRelatedTypeVariables(it, dependencyProvider) }.flatten()
|
||||
.flatMap { getAllDeeplyRelatedTypeVariables(it, dependencyProvider) }
|
||||
val variableForFixation = variableFixationFinder.findFirstVariableForFixation(
|
||||
this, relatedVariables, postponedArguments, KotlinConstraintSystemCompleter.ConstraintSystemCompletionMode.FULL, topLevelType
|
||||
)
|
||||
|
||||
@@ -14,6 +14,7 @@ import org.jetbrains.kotlin.types.model.KotlinTypeMarker
|
||||
import org.jetbrains.kotlin.types.model.TypeConstructorMarker
|
||||
import org.jetbrains.kotlin.types.model.TypeVariableMarker
|
||||
import org.jetbrains.kotlin.types.typeUtil.unCapture
|
||||
import org.jetbrains.kotlin.utils.SmartList
|
||||
|
||||
|
||||
class MutableVariableWithConstraints private constructor(
|
||||
@@ -36,12 +37,15 @@ class MutableVariableWithConstraints private constructor(
|
||||
// see @OnlyInputTypes annotation
|
||||
val projectedInputCallTypes: Collection<UnwrappedType>
|
||||
get() = mutableConstraints
|
||||
.filter { it.position.from is OnlyInputTypeConstraintPosition || it.inputTypePositionBeforeIncorporation != null }
|
||||
.map { (it.type as KotlinType).unCapture().unwrap() }
|
||||
.mapNotNullTo(SmartList()) {
|
||||
if (it.position.from is OnlyInputTypeConstraintPosition || it.inputTypePositionBeforeIncorporation != null)
|
||||
(it.type as KotlinType).unCapture().unwrap()
|
||||
else null
|
||||
}
|
||||
|
||||
private val mutableConstraints = if (constraints == null) ArrayList() else ArrayList(constraints)
|
||||
private val mutableConstraints = if (constraints == null) SmartList() else SmartList(constraints)
|
||||
|
||||
private var simplifiedConstraints: ArrayList<Constraint>? = mutableConstraints
|
||||
private var simplifiedConstraints: SmartList<Constraint>? = mutableConstraints
|
||||
|
||||
// return new actual constraint, if this constraint is new
|
||||
fun addConstraint(constraint: Constraint): Constraint? {
|
||||
@@ -110,13 +114,13 @@ class MutableVariableWithConstraints private constructor(
|
||||
}
|
||||
}
|
||||
|
||||
private fun ArrayList<Constraint>.simplifyConstraints(): ArrayList<Constraint> {
|
||||
private fun SmartList<Constraint>.simplifyConstraints(): SmartList<Constraint> {
|
||||
val equalityConstraints =
|
||||
filter { it.kind == ConstraintKind.EQUALITY }
|
||||
.groupBy { it.typeHashCode }
|
||||
return when {
|
||||
equalityConstraints.isEmpty() -> this
|
||||
else -> filterTo(ArrayList()) { isUsefulConstraint(it, equalityConstraints) }
|
||||
else -> filterTo(SmartList()) { isUsefulConstraint(it, equalityConstraints) }
|
||||
}
|
||||
}
|
||||
|
||||
@@ -134,10 +138,10 @@ class MutableVariableWithConstraints private constructor(
|
||||
internal class MutableConstraintStorage : ConstraintStorage {
|
||||
override val allTypeVariables: MutableMap<TypeConstructorMarker, TypeVariableMarker> = LinkedHashMap()
|
||||
override val notFixedTypeVariables: MutableMap<TypeConstructorMarker, MutableVariableWithConstraints> = LinkedHashMap()
|
||||
override val initialConstraints: MutableList<InitialConstraint> = ArrayList()
|
||||
override val initialConstraints: MutableList<InitialConstraint> = SmartList()
|
||||
override var maxTypeDepthFromInitialConstraints: Int = 1
|
||||
override val errors: MutableList<KotlinCallDiagnostic> = ArrayList()
|
||||
override val errors: MutableList<KotlinCallDiagnostic> = SmartList()
|
||||
override val hasContradiction: Boolean get() = errors.any { !it.candidateApplicability.isSuccess }
|
||||
override val fixedTypeVariables: MutableMap<TypeConstructorMarker, KotlinTypeMarker> = LinkedHashMap()
|
||||
override val postponedTypeVariables: ArrayList<TypeVariableMarker> = ArrayList()
|
||||
override val postponedTypeVariables: MutableList<TypeVariableMarker> = SmartList()
|
||||
}
|
||||
|
||||
@@ -91,10 +91,6 @@ class LexicalChainedScope private constructor(
|
||||
p.println("}")
|
||||
}
|
||||
|
||||
override fun definitelyDoesNotContainName(name: Name): Boolean {
|
||||
return memberScopes.all { it.definitelyDoesNotContainName(name) }
|
||||
}
|
||||
|
||||
companion object {
|
||||
|
||||
@JvmOverloads
|
||||
|
||||
@@ -3,7 +3,7 @@ data class Data(val x: String, val y: Int, val z: Int = 0)
|
||||
|
||||
suspend fun test() {
|
||||
foo(Data("A", 1)) { str, (x, _, z), i ->
|
||||
|
||||
println(str + x + z + i + this)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
// WITH_RUNTIME
|
||||
// KJS_WITH_FULL_RUNTIME
|
||||
// SKIP_DCE_DRIVEN
|
||||
|
||||
fun sort(list: MutableList<String>, comparator: (String, String) -> Int) {
|
||||
list.sortWith(Comparator(comparator))
|
||||
|
||||
@@ -1,34 +0,0 @@
|
||||
// WITH_RUNTIME
|
||||
// WITH_COROUTINES
|
||||
// FULL_RUNTIME
|
||||
// KJS_WITH_FULL_RUNTIME
|
||||
|
||||
class JarFile {
|
||||
fun entries() = listOf<String>()
|
||||
}
|
||||
|
||||
private fun scriptTemplatesDiscoverySequence(): Sequence<String> {
|
||||
return sequence<String> {
|
||||
for (dep in listOf<String>()) {
|
||||
try {
|
||||
val jar = JarFile()
|
||||
try {
|
||||
jar.entries().map { it }
|
||||
val (loadedDefinitions, notFoundClasses) = listOf<String>() to listOf<String>()
|
||||
listOf<String>().forEach {
|
||||
yield(it)
|
||||
}
|
||||
} catch (e: Throwable) {
|
||||
e.message
|
||||
}
|
||||
} catch (e: Exception) {
|
||||
e.message
|
||||
}
|
||||
}
|
||||
yield("OK")
|
||||
}
|
||||
}
|
||||
|
||||
fun box(): String {
|
||||
return scriptTemplatesDiscoverySequence().first()
|
||||
}
|
||||
@@ -42,7 +42,7 @@ public final class Override5Kt$inlineMe$1$generic$2 {
|
||||
inner class Override5Kt$inlineMe$1$generic$2
|
||||
static method <clinit>(): void
|
||||
public method <init>(): void
|
||||
public synthetic bridge @org.jetbrains.annotations.Nullable method invoke(): java.lang.Object
|
||||
public synthetic bridge method invoke(): java.lang.Object
|
||||
public final method invoke(): void
|
||||
}
|
||||
|
||||
|
||||
@@ -1,29 +0,0 @@
|
||||
// KJS_WITH_FULL_RUNTIME
|
||||
// WITH_RUNTIME
|
||||
// WITH_COROUTINES
|
||||
// COMMON_COROUTINES_TEST
|
||||
import helpers.*
|
||||
import COROUTINES_PACKAGE.*
|
||||
import COROUTINES_PACKAGE.intrinsics.*
|
||||
|
||||
fun foo() {
|
||||
bar {
|
||||
val p = false
|
||||
baz(p, "".ifEmpty { "OK" })
|
||||
}
|
||||
}
|
||||
|
||||
var res = "FAIL"
|
||||
|
||||
fun bar(f: suspend () -> Unit) {
|
||||
f.startCoroutine(EmptyContinuation)
|
||||
}
|
||||
|
||||
fun baz(p: Boolean, s: String?) {
|
||||
res = s!!
|
||||
}
|
||||
|
||||
fun box(): String {
|
||||
foo()
|
||||
return res
|
||||
}
|
||||
@@ -1,6 +1,7 @@
|
||||
// !LANGUAGE: +NewInference
|
||||
// KJS_WITH_FULL_RUNTIME
|
||||
// WITH_RUNTIME
|
||||
// SKIP_DCE_DRIVEN
|
||||
|
||||
class Foo<C : Any> {
|
||||
fun test(candidates: Collection<C>): List<C> {
|
||||
|
||||
11
compiler/testData/codegen/box/innerNested/innerImplicitParameter.kt
vendored
Normal file
11
compiler/testData/codegen/box/innerNested/innerImplicitParameter.kt
vendored
Normal file
@@ -0,0 +1,11 @@
|
||||
open class C<T> {
|
||||
inner class A<U>(val x: T?, val y: U)
|
||||
|
||||
class D : C<Nothing>() {
|
||||
fun f() = A<String>(null, "OK")
|
||||
}
|
||||
}
|
||||
|
||||
fun box(): String {
|
||||
return C.D().f().y
|
||||
}
|
||||
@@ -1,5 +1,4 @@
|
||||
// TARGET_BACKEND: JVM
|
||||
// IGNORE_BACKEND_FIR: JVM_IR
|
||||
// FILE: ProtectedField.java
|
||||
|
||||
public abstract class ProtectedField {
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
// !LANGUAGE: -ProhibitProtectedCallFromInline
|
||||
// IGNORE_BACKEND_FIR: JVM_IR
|
||||
// TARGET_BACKEND: JVM
|
||||
|
||||
// FILE: JavaClass.java
|
||||
|
||||
21
compiler/testData/codegen/box/reflection/mapping/types/allSupertypes.kt
vendored
Normal file
21
compiler/testData/codegen/box/reflection/mapping/types/allSupertypes.kt
vendored
Normal file
@@ -0,0 +1,21 @@
|
||||
// TARGET_BACKEND: JVM
|
||||
// WITH_REFLECT
|
||||
|
||||
package test
|
||||
|
||||
import kotlin.reflect.full.allSupertypes
|
||||
import kotlin.reflect.jvm.javaType
|
||||
import kotlin.test.assertEquals
|
||||
|
||||
interface I<T>
|
||||
|
||||
abstract class A<X> : Map<I<out CharSequence>, Array<List<Int>>>
|
||||
|
||||
fun box(): String {
|
||||
assertEquals(
|
||||
"java.util.Map<test.I<? extends java.lang.CharSequence>, java.util.List<? extends java.lang.Integer>[]>",
|
||||
A::class.allSupertypes.single { it.classifier == Map::class }.javaType.toString()
|
||||
)
|
||||
|
||||
return "OK"
|
||||
}
|
||||
27
compiler/testData/codegen/box/reflection/mapping/types/createType.kt
vendored
Normal file
27
compiler/testData/codegen/box/reflection/mapping/types/createType.kt
vendored
Normal file
@@ -0,0 +1,27 @@
|
||||
// TARGET_BACKEND: JVM
|
||||
// WITH_REFLECT
|
||||
|
||||
package test
|
||||
|
||||
import kotlin.reflect.KTypeProjection
|
||||
import kotlin.reflect.full.createType
|
||||
import kotlin.reflect.jvm.javaType
|
||||
import kotlin.test.assertEquals
|
||||
|
||||
class A<X>
|
||||
|
||||
fun box(): String {
|
||||
val nullableAOfInString = A::class.createType(listOf(
|
||||
KTypeProjection.contravariant(String::class.createType())
|
||||
), true)
|
||||
assertEquals("test.A<? super java.lang.String>", nullableAOfInString.javaType.toString())
|
||||
|
||||
val arrayOfListOfInteger = Array::class.createType(listOf(
|
||||
KTypeProjection.invariant(List::class.createType(listOf(
|
||||
KTypeProjection.invariant(Int::class.createType())
|
||||
)))
|
||||
))
|
||||
assertEquals("java.util.List<java.lang.Integer>[]", arrayOfListOfInteger.javaType.toString())
|
||||
|
||||
return "OK"
|
||||
}
|
||||
@@ -7,7 +7,7 @@ import java.lang.reflect.TypeVariable
|
||||
import kotlin.reflect.jvm.*
|
||||
import kotlin.test.assertEquals
|
||||
|
||||
class A<T> {
|
||||
class A<T : CharSequence> {
|
||||
fun foo(t: T) {}
|
||||
}
|
||||
|
||||
@@ -19,5 +19,8 @@ fun box(): String {
|
||||
assertEquals("T", t.name)
|
||||
assertEquals(A::class.java, (t.genericDeclaration as Class<*>))
|
||||
|
||||
val tp = A::class.typeParameters
|
||||
assertEquals(CharSequence::class.java, tp.single().upperBounds.single().javaType)
|
||||
|
||||
return "OK"
|
||||
}
|
||||
|
||||
@@ -1,4 +1,3 @@
|
||||
// IGNORE_BACKEND_FIR: JVM_IR
|
||||
// TARGET_BACKEND: JVM
|
||||
|
||||
// WITH_RUNTIME
|
||||
|
||||
@@ -1,4 +1,3 @@
|
||||
// IGNORE_BACKEND_FIR: JVM_IR
|
||||
// TARGET_BACKEND: JVM
|
||||
|
||||
// WITH_RUNTIME
|
||||
|
||||
@@ -1,4 +1,3 @@
|
||||
// IGNORE_BACKEND_FIR: JVM_IR
|
||||
// TARGET_BACKEND: JVM
|
||||
|
||||
// WITH_RUNTIME
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
// WITH_RUNTIME
|
||||
// KJS_WITH_FULL_RUNTIME
|
||||
// SKIP_DCE_DRIVEN
|
||||
|
||||
fun box(): String {
|
||||
val list = mutableListOf(3, 2, 4, 8, 1, 5)
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
// WITH_RUNTIME
|
||||
// KJS_WITH_FULL_RUNTIME
|
||||
// SKIP_DCE_DRIVEN
|
||||
|
||||
fun box(): String {
|
||||
val list = mutableListOf(3, 2, 4, 8, 1, 5)
|
||||
|
||||
@@ -1,49 +0,0 @@
|
||||
// FILE: test.kt
|
||||
// COMMON_COROUTINES_TEST
|
||||
// WITH_RUNTIME
|
||||
// WITH_COROUTINES
|
||||
// WITH_REFLECT
|
||||
|
||||
import COROUTINES_PACKAGE.*
|
||||
import helpers.*
|
||||
import kotlin.reflect.KProperty
|
||||
|
||||
class Delegate {
|
||||
operator fun getValue(thisRef: Any?, property: KProperty<*>): String {
|
||||
return "OK"
|
||||
}
|
||||
}
|
||||
|
||||
interface SuspendRunnable {
|
||||
suspend fun run(): String
|
||||
}
|
||||
|
||||
suspend inline fun test(crossinline c: suspend (String) -> String): String {
|
||||
val sr = object : SuspendRunnable {
|
||||
val ok by Delegate()
|
||||
override suspend fun run(): String {
|
||||
return c(ok)
|
||||
}
|
||||
}
|
||||
return sr.run()
|
||||
}
|
||||
|
||||
// FILE: box.kt
|
||||
// COMMON_COROUTINES_TEST
|
||||
|
||||
import COROUTINES_PACKAGE.*
|
||||
import helpers.*
|
||||
|
||||
fun builder(c: suspend () -> Unit) {
|
||||
c.startCoroutine(EmptyContinuation)
|
||||
}
|
||||
|
||||
suspend fun dummy() {}
|
||||
|
||||
fun box(): String {
|
||||
var res: String = "FAIL"
|
||||
builder {
|
||||
res = test { it }
|
||||
}
|
||||
return res
|
||||
}
|
||||
@@ -1,4 +1,3 @@
|
||||
// IGNORE_BACKEND: JVM_IR
|
||||
annotation class Ann
|
||||
|
||||
class Foo private @Ann constructor(@Ann s: String) {
|
||||
|
||||
22
compiler/testData/codegen/bytecodeListing/annotations/noAnnotationsInSyntheticAccessors_ir.txt
vendored
Normal file
22
compiler/testData/codegen/bytecodeListing/annotations/noAnnotationsInSyntheticAccessors_ir.txt
vendored
Normal file
@@ -0,0 +1,22 @@
|
||||
@java.lang.annotation.Retention
|
||||
@kotlin.Metadata
|
||||
public annotation class Ann
|
||||
|
||||
@kotlin.Metadata
|
||||
public final class Foo$Companion {
|
||||
inner class Foo$Companion
|
||||
private method <init>(): void
|
||||
public synthetic method <init>(p0: kotlin.jvm.internal.DefaultConstructorMarker): void
|
||||
public final method foo(): void
|
||||
}
|
||||
|
||||
@kotlin.Metadata
|
||||
public final class Foo {
|
||||
public final static @org.jetbrains.annotations.NotNull field Companion: Foo$Companion
|
||||
inner class Foo$Companion
|
||||
static method <clinit>(): void
|
||||
private @Ann method <init>(@Ann p0: java.lang.String): void
|
||||
public synthetic method <init>(p0: java.lang.String, p1: kotlin.jvm.internal.DefaultConstructorMarker): void
|
||||
public synthetic final static method access$foo(p0: Foo, p1: java.lang.String): void
|
||||
private final @Ann method foo(@Ann p0: java.lang.String): void
|
||||
}
|
||||
20
compiler/testData/codegen/bytecodeListing/coroutines/spilling/component1.kt
vendored
Normal file
20
compiler/testData/codegen/bytecodeListing/coroutines/spilling/component1.kt
vendored
Normal file
@@ -0,0 +1,20 @@
|
||||
// WITH_RUNTIME
|
||||
// IGNORE_BACKEND: JVM_IR
|
||||
|
||||
interface Result
|
||||
|
||||
interface Foo {
|
||||
suspend operator fun Result.component1(): Any = TODO()
|
||||
}
|
||||
|
||||
fun use(c: suspend Foo.() -> Unit) {}
|
||||
|
||||
fun generate(): Result = TODO()
|
||||
|
||||
fun test() {
|
||||
use {
|
||||
// This component1 accesses both dispatch and extension receivers,
|
||||
// So, there should be p$
|
||||
val (value) = generate()
|
||||
}
|
||||
}
|
||||
35
compiler/testData/codegen/bytecodeListing/coroutines/spilling/component1.txt
vendored
Normal file
35
compiler/testData/codegen/bytecodeListing/coroutines/spilling/component1.txt
vendored
Normal file
@@ -0,0 +1,35 @@
|
||||
@kotlin.coroutines.jvm.internal.DebugMetadata
|
||||
@kotlin.Metadata
|
||||
final class Component1Kt$test$1 {
|
||||
field L$0: java.lang.Object
|
||||
field label: int
|
||||
private field p$: Foo
|
||||
inner class Component1Kt$test$1
|
||||
method <init>(p0: kotlin.coroutines.Continuation): void
|
||||
public final @org.jetbrains.annotations.NotNull method create(@org.jetbrains.annotations.Nullable p0: java.lang.Object, @org.jetbrains.annotations.NotNull p1: kotlin.coroutines.Continuation): kotlin.coroutines.Continuation
|
||||
public final method invoke(p0: java.lang.Object, p1: java.lang.Object): java.lang.Object
|
||||
public final @org.jetbrains.annotations.Nullable method invokeSuspend(@org.jetbrains.annotations.NotNull p0: java.lang.Object): java.lang.Object
|
||||
}
|
||||
|
||||
@kotlin.Metadata
|
||||
public final class Component1Kt {
|
||||
inner class Component1Kt$test$1
|
||||
public final static @org.jetbrains.annotations.NotNull method generate(): Result
|
||||
public final static method test(): void
|
||||
public final static method use(@org.jetbrains.annotations.NotNull p0: kotlin.jvm.functions.Function2): void
|
||||
}
|
||||
|
||||
@kotlin.Metadata
|
||||
public final class Foo$DefaultImpls {
|
||||
inner class Foo$DefaultImpls
|
||||
public static @org.jetbrains.annotations.Nullable method component1(p0: Foo, @org.jetbrains.annotations.NotNull p1: Result, @org.jetbrains.annotations.NotNull p2: kotlin.coroutines.Continuation): java.lang.Object
|
||||
}
|
||||
|
||||
@kotlin.Metadata
|
||||
public interface Foo {
|
||||
inner class Foo$DefaultImpls
|
||||
public abstract @org.jetbrains.annotations.Nullable method component1(@org.jetbrains.annotations.NotNull p0: Result, @org.jetbrains.annotations.NotNull p1: kotlin.coroutines.Continuation): java.lang.Object
|
||||
}
|
||||
|
||||
@kotlin.Metadata
|
||||
public interface Result
|
||||
20
compiler/testData/codegen/bytecodeListing/coroutines/spilling/destructured.kt
vendored
Normal file
20
compiler/testData/codegen/bytecodeListing/coroutines/spilling/destructured.kt
vendored
Normal file
@@ -0,0 +1,20 @@
|
||||
// WITH_RUNTIME
|
||||
// IGNORE_BACKEND: JVM_IR
|
||||
|
||||
fun use(c: suspend (Pair<Int, Int>) -> Unit) {}
|
||||
|
||||
fun blackhole(a: Any) {}
|
||||
|
||||
fun test() {
|
||||
use { (a, b) ->
|
||||
}
|
||||
use { (a, b) ->
|
||||
blackhole(a)
|
||||
}
|
||||
use { (a, b) ->
|
||||
blackhole(b)
|
||||
}
|
||||
use {
|
||||
blackhole(it)
|
||||
}
|
||||
}
|
||||
57
compiler/testData/codegen/bytecodeListing/coroutines/spilling/destructured.txt
vendored
Normal file
57
compiler/testData/codegen/bytecodeListing/coroutines/spilling/destructured.txt
vendored
Normal file
@@ -0,0 +1,57 @@
|
||||
@kotlin.coroutines.jvm.internal.DebugMetadata
|
||||
@kotlin.Metadata
|
||||
final class DestructuredKt$test$1 {
|
||||
field label: int
|
||||
inner class DestructuredKt$test$1
|
||||
method <init>(p0: kotlin.coroutines.Continuation): void
|
||||
public final @org.jetbrains.annotations.NotNull method create(@org.jetbrains.annotations.Nullable p0: java.lang.Object, @org.jetbrains.annotations.NotNull p1: kotlin.coroutines.Continuation): kotlin.coroutines.Continuation
|
||||
public final method invoke(p0: java.lang.Object, p1: java.lang.Object): java.lang.Object
|
||||
public final @org.jetbrains.annotations.Nullable method invokeSuspend(@org.jetbrains.annotations.NotNull p0: java.lang.Object): java.lang.Object
|
||||
}
|
||||
|
||||
@kotlin.coroutines.jvm.internal.DebugMetadata
|
||||
@kotlin.Metadata
|
||||
final class DestructuredKt$test$2 {
|
||||
field label: int
|
||||
private field p$0: kotlin.Pair
|
||||
inner class DestructuredKt$test$2
|
||||
method <init>(p0: kotlin.coroutines.Continuation): void
|
||||
public final @org.jetbrains.annotations.NotNull method create(@org.jetbrains.annotations.Nullable p0: java.lang.Object, @org.jetbrains.annotations.NotNull p1: kotlin.coroutines.Continuation): kotlin.coroutines.Continuation
|
||||
public final method invoke(p0: java.lang.Object, p1: java.lang.Object): java.lang.Object
|
||||
public final @org.jetbrains.annotations.Nullable method invokeSuspend(@org.jetbrains.annotations.NotNull p0: java.lang.Object): java.lang.Object
|
||||
}
|
||||
|
||||
@kotlin.coroutines.jvm.internal.DebugMetadata
|
||||
@kotlin.Metadata
|
||||
final class DestructuredKt$test$3 {
|
||||
field label: int
|
||||
private field p$0: kotlin.Pair
|
||||
inner class DestructuredKt$test$3
|
||||
method <init>(p0: kotlin.coroutines.Continuation): void
|
||||
public final @org.jetbrains.annotations.NotNull method create(@org.jetbrains.annotations.Nullable p0: java.lang.Object, @org.jetbrains.annotations.NotNull p1: kotlin.coroutines.Continuation): kotlin.coroutines.Continuation
|
||||
public final method invoke(p0: java.lang.Object, p1: java.lang.Object): java.lang.Object
|
||||
public final @org.jetbrains.annotations.Nullable method invokeSuspend(@org.jetbrains.annotations.NotNull p0: java.lang.Object): java.lang.Object
|
||||
}
|
||||
|
||||
@kotlin.coroutines.jvm.internal.DebugMetadata
|
||||
@kotlin.Metadata
|
||||
final class DestructuredKt$test$4 {
|
||||
field label: int
|
||||
private field p$0: kotlin.Pair
|
||||
inner class DestructuredKt$test$4
|
||||
method <init>(p0: kotlin.coroutines.Continuation): void
|
||||
public final @org.jetbrains.annotations.NotNull method create(@org.jetbrains.annotations.Nullable p0: java.lang.Object, @org.jetbrains.annotations.NotNull p1: kotlin.coroutines.Continuation): kotlin.coroutines.Continuation
|
||||
public final method invoke(p0: java.lang.Object, p1: java.lang.Object): java.lang.Object
|
||||
public final @org.jetbrains.annotations.Nullable method invokeSuspend(@org.jetbrains.annotations.NotNull p0: java.lang.Object): java.lang.Object
|
||||
}
|
||||
|
||||
@kotlin.Metadata
|
||||
public final class DestructuredKt {
|
||||
inner class DestructuredKt$test$1
|
||||
inner class DestructuredKt$test$2
|
||||
inner class DestructuredKt$test$3
|
||||
inner class DestructuredKt$test$4
|
||||
public final static method blackhole(@org.jetbrains.annotations.NotNull p0: java.lang.Object): void
|
||||
public final static method test(): void
|
||||
public final static method use(@org.jetbrains.annotations.NotNull p0: kotlin.jvm.functions.Function2): void
|
||||
}
|
||||
19
compiler/testData/codegen/bytecodeListing/coroutines/spilling/field.kt
vendored
Normal file
19
compiler/testData/codegen/bytecodeListing/coroutines/spilling/field.kt
vendored
Normal file
@@ -0,0 +1,19 @@
|
||||
// WITH_RUNTIME
|
||||
// IGNORE_BACKEND: JVM_IR
|
||||
|
||||
interface Result
|
||||
|
||||
interface Foo {
|
||||
val Result.value: Any
|
||||
get() = TODO()
|
||||
}
|
||||
|
||||
fun use(c: suspend Foo.() -> Unit) {}
|
||||
|
||||
fun generate(): Result = TODO()
|
||||
|
||||
fun test() {
|
||||
use {
|
||||
val value = generate().value
|
||||
}
|
||||
}
|
||||
34
compiler/testData/codegen/bytecodeListing/coroutines/spilling/field.txt
vendored
Normal file
34
compiler/testData/codegen/bytecodeListing/coroutines/spilling/field.txt
vendored
Normal file
@@ -0,0 +1,34 @@
|
||||
@kotlin.coroutines.jvm.internal.DebugMetadata
|
||||
@kotlin.Metadata
|
||||
final class FieldKt$test$1 {
|
||||
field label: int
|
||||
private field p$: Foo
|
||||
inner class FieldKt$test$1
|
||||
method <init>(p0: kotlin.coroutines.Continuation): void
|
||||
public final @org.jetbrains.annotations.NotNull method create(@org.jetbrains.annotations.Nullable p0: java.lang.Object, @org.jetbrains.annotations.NotNull p1: kotlin.coroutines.Continuation): kotlin.coroutines.Continuation
|
||||
public final method invoke(p0: java.lang.Object, p1: java.lang.Object): java.lang.Object
|
||||
public final @org.jetbrains.annotations.Nullable method invokeSuspend(@org.jetbrains.annotations.NotNull p0: java.lang.Object): java.lang.Object
|
||||
}
|
||||
|
||||
@kotlin.Metadata
|
||||
public final class FieldKt {
|
||||
inner class FieldKt$test$1
|
||||
public final static @org.jetbrains.annotations.NotNull method generate(): Result
|
||||
public final static method test(): void
|
||||
public final static method use(@org.jetbrains.annotations.NotNull p0: kotlin.jvm.functions.Function2): void
|
||||
}
|
||||
|
||||
@kotlin.Metadata
|
||||
public final class Foo$DefaultImpls {
|
||||
inner class Foo$DefaultImpls
|
||||
public static @org.jetbrains.annotations.NotNull method getValue(p0: Foo, @org.jetbrains.annotations.NotNull p1: Result): java.lang.Object
|
||||
}
|
||||
|
||||
@kotlin.Metadata
|
||||
public interface Foo {
|
||||
inner class Foo$DefaultImpls
|
||||
public abstract @org.jetbrains.annotations.NotNull method getValue(@org.jetbrains.annotations.NotNull p0: Result): java.lang.Object
|
||||
}
|
||||
|
||||
@kotlin.Metadata
|
||||
public interface Result
|
||||
74
compiler/testData/codegen/bytecodeListing/coroutines/spilling/lambda.kt
vendored
Normal file
74
compiler/testData/codegen/bytecodeListing/coroutines/spilling/lambda.kt
vendored
Normal file
@@ -0,0 +1,74 @@
|
||||
// WITH_RUNTIME
|
||||
// IGNORE_BACKEND: JVM_IR
|
||||
|
||||
fun use2(c: suspend Long.(Double, String) -> Unit) {}
|
||||
fun use(c: suspend Long.(String) -> Unit) {}
|
||||
|
||||
fun blackhole(a: Any) {}
|
||||
|
||||
fun test() {
|
||||
// test$1: p$0, p$1
|
||||
use2 { a, b ->
|
||||
blackhole(b + a)
|
||||
}
|
||||
// test$2: p$0
|
||||
use2 { a, b ->
|
||||
blackhole(a)
|
||||
}
|
||||
// test$3: p$1
|
||||
use2 { a, b ->
|
||||
blackhole(b)
|
||||
}
|
||||
// test$4: p$0
|
||||
use2 { a, _ ->
|
||||
blackhole(a)
|
||||
}
|
||||
// test$5: p$1
|
||||
use2 { _, b ->
|
||||
blackhole(b)
|
||||
}
|
||||
// test$6: p$, p$0, p$1
|
||||
use2 { a, b ->
|
||||
blackhole(b + a + this)
|
||||
}
|
||||
// test$7: p$, p$0
|
||||
use2 { a, b ->
|
||||
blackhole(a + this.toDouble())
|
||||
}
|
||||
// test$8: p$, p$1
|
||||
use2 { a, b ->
|
||||
blackhole(b + this)
|
||||
}
|
||||
// test$9: p$, p$0
|
||||
use2 { a, _ ->
|
||||
blackhole(a + this.toDouble())
|
||||
}
|
||||
// test$10: p$, p$1
|
||||
use2 { _, b ->
|
||||
blackhole(b + this)
|
||||
}
|
||||
// test$11: p$
|
||||
use2 { _, _ ->
|
||||
blackhole(this)
|
||||
}
|
||||
// test$12:
|
||||
use2 { _, _ -> }
|
||||
// test$13: p$, p$0
|
||||
use {
|
||||
blackhole(it + this)
|
||||
}
|
||||
// test$14: p$
|
||||
use {
|
||||
blackhole(this)
|
||||
}
|
||||
// test$15: p$0
|
||||
use {
|
||||
blackhole(it)
|
||||
}
|
||||
// test$16:
|
||||
use {}
|
||||
// test$17: p$
|
||||
use {
|
||||
blackhole(toString())
|
||||
}
|
||||
}
|
||||
234
compiler/testData/codegen/bytecodeListing/coroutines/spilling/lambda.txt
vendored
Normal file
234
compiler/testData/codegen/bytecodeListing/coroutines/spilling/lambda.txt
vendored
Normal file
@@ -0,0 +1,234 @@
|
||||
@kotlin.coroutines.jvm.internal.DebugMetadata
|
||||
@kotlin.Metadata
|
||||
final class LambdaKt$test$1 {
|
||||
field label: int
|
||||
private field p$0: double
|
||||
private field p$1: java.lang.String
|
||||
inner class LambdaKt$test$1
|
||||
method <init>(p0: kotlin.coroutines.Continuation): void
|
||||
public final @org.jetbrains.annotations.NotNull method create(p0: long, p1: double, @org.jetbrains.annotations.NotNull p2: java.lang.String, @org.jetbrains.annotations.NotNull p3: kotlin.coroutines.Continuation): kotlin.coroutines.Continuation
|
||||
public final method invoke(p0: java.lang.Object, p1: java.lang.Object, p2: java.lang.Object, p3: java.lang.Object): java.lang.Object
|
||||
public final @org.jetbrains.annotations.Nullable method invokeSuspend(@org.jetbrains.annotations.NotNull p0: java.lang.Object): java.lang.Object
|
||||
}
|
||||
|
||||
@kotlin.coroutines.jvm.internal.DebugMetadata
|
||||
@kotlin.Metadata
|
||||
final class LambdaKt$test$10 {
|
||||
field label: int
|
||||
private field p$1: java.lang.String
|
||||
private field p$: long
|
||||
inner class LambdaKt$test$10
|
||||
method <init>(p0: kotlin.coroutines.Continuation): void
|
||||
public final @org.jetbrains.annotations.NotNull method create(p0: long, p1: double, @org.jetbrains.annotations.NotNull p2: java.lang.String, @org.jetbrains.annotations.NotNull p3: kotlin.coroutines.Continuation): kotlin.coroutines.Continuation
|
||||
public final method invoke(p0: java.lang.Object, p1: java.lang.Object, p2: java.lang.Object, p3: java.lang.Object): java.lang.Object
|
||||
public final @org.jetbrains.annotations.Nullable method invokeSuspend(@org.jetbrains.annotations.NotNull p0: java.lang.Object): java.lang.Object
|
||||
}
|
||||
|
||||
@kotlin.coroutines.jvm.internal.DebugMetadata
|
||||
@kotlin.Metadata
|
||||
final class LambdaKt$test$11 {
|
||||
field label: int
|
||||
private field p$: long
|
||||
inner class LambdaKt$test$11
|
||||
method <init>(p0: kotlin.coroutines.Continuation): void
|
||||
public final @org.jetbrains.annotations.NotNull method create(p0: long, p1: double, @org.jetbrains.annotations.NotNull p2: java.lang.String, @org.jetbrains.annotations.NotNull p3: kotlin.coroutines.Continuation): kotlin.coroutines.Continuation
|
||||
public final method invoke(p0: java.lang.Object, p1: java.lang.Object, p2: java.lang.Object, p3: java.lang.Object): java.lang.Object
|
||||
public final @org.jetbrains.annotations.Nullable method invokeSuspend(@org.jetbrains.annotations.NotNull p0: java.lang.Object): java.lang.Object
|
||||
}
|
||||
|
||||
@kotlin.coroutines.jvm.internal.DebugMetadata
|
||||
@kotlin.Metadata
|
||||
final class LambdaKt$test$12 {
|
||||
field label: int
|
||||
inner class LambdaKt$test$12
|
||||
method <init>(p0: kotlin.coroutines.Continuation): void
|
||||
public final @org.jetbrains.annotations.NotNull method create(p0: long, p1: double, @org.jetbrains.annotations.NotNull p2: java.lang.String, @org.jetbrains.annotations.NotNull p3: kotlin.coroutines.Continuation): kotlin.coroutines.Continuation
|
||||
public final method invoke(p0: java.lang.Object, p1: java.lang.Object, p2: java.lang.Object, p3: java.lang.Object): java.lang.Object
|
||||
public final @org.jetbrains.annotations.Nullable method invokeSuspend(@org.jetbrains.annotations.NotNull p0: java.lang.Object): java.lang.Object
|
||||
}
|
||||
|
||||
@kotlin.coroutines.jvm.internal.DebugMetadata
|
||||
@kotlin.Metadata
|
||||
final class LambdaKt$test$13 {
|
||||
field label: int
|
||||
private field p$0: java.lang.String
|
||||
private field p$: long
|
||||
inner class LambdaKt$test$13
|
||||
method <init>(p0: kotlin.coroutines.Continuation): void
|
||||
public final @org.jetbrains.annotations.NotNull method create(p0: long, @org.jetbrains.annotations.NotNull p1: java.lang.String, @org.jetbrains.annotations.NotNull p2: kotlin.coroutines.Continuation): kotlin.coroutines.Continuation
|
||||
public final method invoke(p0: java.lang.Object, p1: java.lang.Object, p2: java.lang.Object): java.lang.Object
|
||||
public final @org.jetbrains.annotations.Nullable method invokeSuspend(@org.jetbrains.annotations.NotNull p0: java.lang.Object): java.lang.Object
|
||||
}
|
||||
|
||||
@kotlin.coroutines.jvm.internal.DebugMetadata
|
||||
@kotlin.Metadata
|
||||
final class LambdaKt$test$14 {
|
||||
field label: int
|
||||
private field p$: long
|
||||
inner class LambdaKt$test$14
|
||||
method <init>(p0: kotlin.coroutines.Continuation): void
|
||||
public final @org.jetbrains.annotations.NotNull method create(p0: long, @org.jetbrains.annotations.NotNull p1: java.lang.String, @org.jetbrains.annotations.NotNull p2: kotlin.coroutines.Continuation): kotlin.coroutines.Continuation
|
||||
public final method invoke(p0: java.lang.Object, p1: java.lang.Object, p2: java.lang.Object): java.lang.Object
|
||||
public final @org.jetbrains.annotations.Nullable method invokeSuspend(@org.jetbrains.annotations.NotNull p0: java.lang.Object): java.lang.Object
|
||||
}
|
||||
|
||||
@kotlin.coroutines.jvm.internal.DebugMetadata
|
||||
@kotlin.Metadata
|
||||
final class LambdaKt$test$15 {
|
||||
field label: int
|
||||
private field p$0: java.lang.String
|
||||
inner class LambdaKt$test$15
|
||||
method <init>(p0: kotlin.coroutines.Continuation): void
|
||||
public final @org.jetbrains.annotations.NotNull method create(p0: long, @org.jetbrains.annotations.NotNull p1: java.lang.String, @org.jetbrains.annotations.NotNull p2: kotlin.coroutines.Continuation): kotlin.coroutines.Continuation
|
||||
public final method invoke(p0: java.lang.Object, p1: java.lang.Object, p2: java.lang.Object): java.lang.Object
|
||||
public final @org.jetbrains.annotations.Nullable method invokeSuspend(@org.jetbrains.annotations.NotNull p0: java.lang.Object): java.lang.Object
|
||||
}
|
||||
|
||||
@kotlin.coroutines.jvm.internal.DebugMetadata
|
||||
@kotlin.Metadata
|
||||
final class LambdaKt$test$16 {
|
||||
field label: int
|
||||
inner class LambdaKt$test$16
|
||||
method <init>(p0: kotlin.coroutines.Continuation): void
|
||||
public final @org.jetbrains.annotations.NotNull method create(p0: long, @org.jetbrains.annotations.NotNull p1: java.lang.String, @org.jetbrains.annotations.NotNull p2: kotlin.coroutines.Continuation): kotlin.coroutines.Continuation
|
||||
public final method invoke(p0: java.lang.Object, p1: java.lang.Object, p2: java.lang.Object): java.lang.Object
|
||||
public final @org.jetbrains.annotations.Nullable method invokeSuspend(@org.jetbrains.annotations.NotNull p0: java.lang.Object): java.lang.Object
|
||||
}
|
||||
|
||||
@kotlin.coroutines.jvm.internal.DebugMetadata
|
||||
@kotlin.Metadata
|
||||
final class LambdaKt$test$17 {
|
||||
field label: int
|
||||
private field p$: long
|
||||
inner class LambdaKt$test$17
|
||||
method <init>(p0: kotlin.coroutines.Continuation): void
|
||||
public final @org.jetbrains.annotations.NotNull method create(p0: long, @org.jetbrains.annotations.NotNull p1: java.lang.String, @org.jetbrains.annotations.NotNull p2: kotlin.coroutines.Continuation): kotlin.coroutines.Continuation
|
||||
public final method invoke(p0: java.lang.Object, p1: java.lang.Object, p2: java.lang.Object): java.lang.Object
|
||||
public final @org.jetbrains.annotations.Nullable method invokeSuspend(@org.jetbrains.annotations.NotNull p0: java.lang.Object): java.lang.Object
|
||||
}
|
||||
|
||||
@kotlin.coroutines.jvm.internal.DebugMetadata
|
||||
@kotlin.Metadata
|
||||
final class LambdaKt$test$2 {
|
||||
field label: int
|
||||
private field p$0: double
|
||||
inner class LambdaKt$test$2
|
||||
method <init>(p0: kotlin.coroutines.Continuation): void
|
||||
public final @org.jetbrains.annotations.NotNull method create(p0: long, p1: double, @org.jetbrains.annotations.NotNull p2: java.lang.String, @org.jetbrains.annotations.NotNull p3: kotlin.coroutines.Continuation): kotlin.coroutines.Continuation
|
||||
public final method invoke(p0: java.lang.Object, p1: java.lang.Object, p2: java.lang.Object, p3: java.lang.Object): java.lang.Object
|
||||
public final @org.jetbrains.annotations.Nullable method invokeSuspend(@org.jetbrains.annotations.NotNull p0: java.lang.Object): java.lang.Object
|
||||
}
|
||||
|
||||
@kotlin.coroutines.jvm.internal.DebugMetadata
|
||||
@kotlin.Metadata
|
||||
final class LambdaKt$test$3 {
|
||||
field label: int
|
||||
private field p$1: java.lang.String
|
||||
inner class LambdaKt$test$3
|
||||
method <init>(p0: kotlin.coroutines.Continuation): void
|
||||
public final @org.jetbrains.annotations.NotNull method create(p0: long, p1: double, @org.jetbrains.annotations.NotNull p2: java.lang.String, @org.jetbrains.annotations.NotNull p3: kotlin.coroutines.Continuation): kotlin.coroutines.Continuation
|
||||
public final method invoke(p0: java.lang.Object, p1: java.lang.Object, p2: java.lang.Object, p3: java.lang.Object): java.lang.Object
|
||||
public final @org.jetbrains.annotations.Nullable method invokeSuspend(@org.jetbrains.annotations.NotNull p0: java.lang.Object): java.lang.Object
|
||||
}
|
||||
|
||||
@kotlin.coroutines.jvm.internal.DebugMetadata
|
||||
@kotlin.Metadata
|
||||
final class LambdaKt$test$4 {
|
||||
field label: int
|
||||
private field p$0: double
|
||||
inner class LambdaKt$test$4
|
||||
method <init>(p0: kotlin.coroutines.Continuation): void
|
||||
public final @org.jetbrains.annotations.NotNull method create(p0: long, p1: double, @org.jetbrains.annotations.NotNull p2: java.lang.String, @org.jetbrains.annotations.NotNull p3: kotlin.coroutines.Continuation): kotlin.coroutines.Continuation
|
||||
public final method invoke(p0: java.lang.Object, p1: java.lang.Object, p2: java.lang.Object, p3: java.lang.Object): java.lang.Object
|
||||
public final @org.jetbrains.annotations.Nullable method invokeSuspend(@org.jetbrains.annotations.NotNull p0: java.lang.Object): java.lang.Object
|
||||
}
|
||||
|
||||
@kotlin.coroutines.jvm.internal.DebugMetadata
|
||||
@kotlin.Metadata
|
||||
final class LambdaKt$test$5 {
|
||||
field label: int
|
||||
private field p$1: java.lang.String
|
||||
inner class LambdaKt$test$5
|
||||
method <init>(p0: kotlin.coroutines.Continuation): void
|
||||
public final @org.jetbrains.annotations.NotNull method create(p0: long, p1: double, @org.jetbrains.annotations.NotNull p2: java.lang.String, @org.jetbrains.annotations.NotNull p3: kotlin.coroutines.Continuation): kotlin.coroutines.Continuation
|
||||
public final method invoke(p0: java.lang.Object, p1: java.lang.Object, p2: java.lang.Object, p3: java.lang.Object): java.lang.Object
|
||||
public final @org.jetbrains.annotations.Nullable method invokeSuspend(@org.jetbrains.annotations.NotNull p0: java.lang.Object): java.lang.Object
|
||||
}
|
||||
|
||||
@kotlin.coroutines.jvm.internal.DebugMetadata
|
||||
@kotlin.Metadata
|
||||
final class LambdaKt$test$6 {
|
||||
field label: int
|
||||
private field p$0: double
|
||||
private field p$1: java.lang.String
|
||||
private field p$: long
|
||||
inner class LambdaKt$test$6
|
||||
method <init>(p0: kotlin.coroutines.Continuation): void
|
||||
public final @org.jetbrains.annotations.NotNull method create(p0: long, p1: double, @org.jetbrains.annotations.NotNull p2: java.lang.String, @org.jetbrains.annotations.NotNull p3: kotlin.coroutines.Continuation): kotlin.coroutines.Continuation
|
||||
public final method invoke(p0: java.lang.Object, p1: java.lang.Object, p2: java.lang.Object, p3: java.lang.Object): java.lang.Object
|
||||
public final @org.jetbrains.annotations.Nullable method invokeSuspend(@org.jetbrains.annotations.NotNull p0: java.lang.Object): java.lang.Object
|
||||
}
|
||||
|
||||
@kotlin.coroutines.jvm.internal.DebugMetadata
|
||||
@kotlin.Metadata
|
||||
final class LambdaKt$test$7 {
|
||||
field label: int
|
||||
private field p$0: double
|
||||
private field p$: long
|
||||
inner class LambdaKt$test$7
|
||||
method <init>(p0: kotlin.coroutines.Continuation): void
|
||||
public final @org.jetbrains.annotations.NotNull method create(p0: long, p1: double, @org.jetbrains.annotations.NotNull p2: java.lang.String, @org.jetbrains.annotations.NotNull p3: kotlin.coroutines.Continuation): kotlin.coroutines.Continuation
|
||||
public final method invoke(p0: java.lang.Object, p1: java.lang.Object, p2: java.lang.Object, p3: java.lang.Object): java.lang.Object
|
||||
public final @org.jetbrains.annotations.Nullable method invokeSuspend(@org.jetbrains.annotations.NotNull p0: java.lang.Object): java.lang.Object
|
||||
}
|
||||
|
||||
@kotlin.coroutines.jvm.internal.DebugMetadata
|
||||
@kotlin.Metadata
|
||||
final class LambdaKt$test$8 {
|
||||
field label: int
|
||||
private field p$1: java.lang.String
|
||||
private field p$: long
|
||||
inner class LambdaKt$test$8
|
||||
method <init>(p0: kotlin.coroutines.Continuation): void
|
||||
public final @org.jetbrains.annotations.NotNull method create(p0: long, p1: double, @org.jetbrains.annotations.NotNull p2: java.lang.String, @org.jetbrains.annotations.NotNull p3: kotlin.coroutines.Continuation): kotlin.coroutines.Continuation
|
||||
public final method invoke(p0: java.lang.Object, p1: java.lang.Object, p2: java.lang.Object, p3: java.lang.Object): java.lang.Object
|
||||
public final @org.jetbrains.annotations.Nullable method invokeSuspend(@org.jetbrains.annotations.NotNull p0: java.lang.Object): java.lang.Object
|
||||
}
|
||||
|
||||
@kotlin.coroutines.jvm.internal.DebugMetadata
|
||||
@kotlin.Metadata
|
||||
final class LambdaKt$test$9 {
|
||||
field label: int
|
||||
private field p$0: double
|
||||
private field p$: long
|
||||
inner class LambdaKt$test$9
|
||||
method <init>(p0: kotlin.coroutines.Continuation): void
|
||||
public final @org.jetbrains.annotations.NotNull method create(p0: long, p1: double, @org.jetbrains.annotations.NotNull p2: java.lang.String, @org.jetbrains.annotations.NotNull p3: kotlin.coroutines.Continuation): kotlin.coroutines.Continuation
|
||||
public final method invoke(p0: java.lang.Object, p1: java.lang.Object, p2: java.lang.Object, p3: java.lang.Object): java.lang.Object
|
||||
public final @org.jetbrains.annotations.Nullable method invokeSuspend(@org.jetbrains.annotations.NotNull p0: java.lang.Object): java.lang.Object
|
||||
}
|
||||
|
||||
@kotlin.Metadata
|
||||
public final class LambdaKt {
|
||||
inner class LambdaKt$test$1
|
||||
inner class LambdaKt$test$10
|
||||
inner class LambdaKt$test$11
|
||||
inner class LambdaKt$test$12
|
||||
inner class LambdaKt$test$13
|
||||
inner class LambdaKt$test$14
|
||||
inner class LambdaKt$test$15
|
||||
inner class LambdaKt$test$16
|
||||
inner class LambdaKt$test$17
|
||||
inner class LambdaKt$test$2
|
||||
inner class LambdaKt$test$3
|
||||
inner class LambdaKt$test$4
|
||||
inner class LambdaKt$test$5
|
||||
inner class LambdaKt$test$6
|
||||
inner class LambdaKt$test$7
|
||||
inner class LambdaKt$test$8
|
||||
inner class LambdaKt$test$9
|
||||
public final static method blackhole(@org.jetbrains.annotations.NotNull p0: java.lang.Object): void
|
||||
public final static method test(): void
|
||||
public final static method use(@org.jetbrains.annotations.NotNull p0: kotlin.jvm.functions.Function3): void
|
||||
public final static method use2(@org.jetbrains.annotations.NotNull p0: kotlin.jvm.functions.Function4): void
|
||||
}
|
||||
34
compiler/testData/codegen/bytecodeListing/coroutines/spilling/select.kt
vendored
Normal file
34
compiler/testData/codegen/bytecodeListing/coroutines/spilling/select.kt
vendored
Normal file
@@ -0,0 +1,34 @@
|
||||
// WITH_RUNTIME
|
||||
// IGNORE_BACKEND: JVM_IR
|
||||
|
||||
import kotlin.coroutines.*
|
||||
import kotlin.experimental.*
|
||||
|
||||
interface CoroutineScope
|
||||
|
||||
@OptIn(ExperimentalTypeInference::class)
|
||||
public fun <E> CoroutineScope.produce(
|
||||
@BuilderInference block: suspend ProducerScope<E>.() -> Unit
|
||||
): ReceiveChannel<E> = TODO()
|
||||
|
||||
interface ProducerScope<in E> : CoroutineScope, SendChannel<E> {
|
||||
public val channel: SendChannel<E>
|
||||
}
|
||||
|
||||
interface ReceiveChannel<out E>
|
||||
interface SelectBuilder<in R> {
|
||||
operator fun <P, Q> SelectClause2<P, Q>.invoke(param: P, block: suspend (Q) -> R)
|
||||
}
|
||||
interface SelectClause2<in P, out Q>
|
||||
interface SendChannel<in E> {
|
||||
val onSend: SelectClause2<E, SendChannel<E>>
|
||||
}
|
||||
suspend inline fun <R> select(crossinline builder: SelectBuilder<R>.() -> Unit): R {
|
||||
TODO()
|
||||
}
|
||||
|
||||
fun CoroutineScope.produceNumbers(side: SendChannel<Int>) = produce<Int> {
|
||||
select<Unit> {
|
||||
onSend(1) {}
|
||||
}
|
||||
}
|
||||
55
compiler/testData/codegen/bytecodeListing/coroutines/spilling/select.txt
vendored
Normal file
55
compiler/testData/codegen/bytecodeListing/coroutines/spilling/select.txt
vendored
Normal file
@@ -0,0 +1,55 @@
|
||||
@kotlin.Metadata
|
||||
public interface CoroutineScope
|
||||
|
||||
@kotlin.Metadata
|
||||
public interface ProducerScope {
|
||||
public abstract @org.jetbrains.annotations.NotNull method getChannel(): SendChannel
|
||||
}
|
||||
|
||||
@kotlin.Metadata
|
||||
public interface ReceiveChannel
|
||||
|
||||
@kotlin.Metadata
|
||||
public interface SelectBuilder {
|
||||
public abstract method invoke(@org.jetbrains.annotations.NotNull p0: SelectClause2, p1: java.lang.Object, @org.jetbrains.annotations.NotNull p2: kotlin.jvm.functions.Function2): void
|
||||
}
|
||||
|
||||
@kotlin.Metadata
|
||||
public interface SelectClause2
|
||||
|
||||
@kotlin.coroutines.jvm.internal.DebugMetadata
|
||||
@kotlin.Metadata
|
||||
final class SelectKt$produceNumbers$1$1$1 {
|
||||
field label: int
|
||||
inner class SelectKt$produceNumbers$1$1$1
|
||||
method <init>(p0: kotlin.coroutines.Continuation): void
|
||||
public final @org.jetbrains.annotations.NotNull method create(@org.jetbrains.annotations.Nullable p0: java.lang.Object, @org.jetbrains.annotations.NotNull p1: kotlin.coroutines.Continuation): kotlin.coroutines.Continuation
|
||||
public final method invoke(p0: java.lang.Object, p1: java.lang.Object): java.lang.Object
|
||||
public final @org.jetbrains.annotations.Nullable method invokeSuspend(@org.jetbrains.annotations.NotNull p0: java.lang.Object): java.lang.Object
|
||||
}
|
||||
|
||||
@kotlin.coroutines.jvm.internal.DebugMetadata
|
||||
@kotlin.Metadata
|
||||
final class SelectKt$produceNumbers$1 {
|
||||
field label: int
|
||||
private field p$: ProducerScope
|
||||
inner class SelectKt$produceNumbers$1
|
||||
method <init>(p0: kotlin.coroutines.Continuation): void
|
||||
public final @org.jetbrains.annotations.NotNull method create(@org.jetbrains.annotations.Nullable p0: java.lang.Object, @org.jetbrains.annotations.NotNull p1: kotlin.coroutines.Continuation): kotlin.coroutines.Continuation
|
||||
public final method invoke(p0: java.lang.Object, p1: java.lang.Object): java.lang.Object
|
||||
public final @org.jetbrains.annotations.Nullable method invokeSuspend(@org.jetbrains.annotations.NotNull p0: java.lang.Object): java.lang.Object
|
||||
}
|
||||
|
||||
@kotlin.Metadata
|
||||
public final class SelectKt {
|
||||
inner class SelectKt$produceNumbers$1
|
||||
public final static @org.jetbrains.annotations.NotNull method produce(@org.jetbrains.annotations.NotNull p0: CoroutineScope, @kotlin.BuilderInference @org.jetbrains.annotations.NotNull p1: kotlin.jvm.functions.Function2): ReceiveChannel
|
||||
public final static @org.jetbrains.annotations.NotNull method produceNumbers(@org.jetbrains.annotations.NotNull p0: CoroutineScope, @org.jetbrains.annotations.NotNull p1: SendChannel): ReceiveChannel
|
||||
private final static @org.jetbrains.annotations.Nullable method select$$forInline(@org.jetbrains.annotations.NotNull p0: kotlin.jvm.functions.Function1, @org.jetbrains.annotations.NotNull p1: kotlin.coroutines.Continuation): java.lang.Object
|
||||
public final static @org.jetbrains.annotations.Nullable method select(@org.jetbrains.annotations.NotNull p0: kotlin.jvm.functions.Function1, @org.jetbrains.annotations.NotNull p1: kotlin.coroutines.Continuation): java.lang.Object
|
||||
}
|
||||
|
||||
@kotlin.Metadata
|
||||
public interface SendChannel {
|
||||
public abstract @org.jetbrains.annotations.NotNull method getOnSend(): SelectClause2
|
||||
}
|
||||
11
compiler/testData/codegen/bytecodeListing/coroutines/spilling/unreachable.kt
vendored
Normal file
11
compiler/testData/codegen/bytecodeListing/coroutines/spilling/unreachable.kt
vendored
Normal file
@@ -0,0 +1,11 @@
|
||||
// WITH_RUNTIME
|
||||
// IGNORE_BACKEND: JVM_IR
|
||||
|
||||
fun use(c: suspend (String) -> Unit) {}
|
||||
|
||||
fun test() {
|
||||
use {
|
||||
throw IllegalStateException("")
|
||||
it + ""
|
||||
}
|
||||
}
|
||||
18
compiler/testData/codegen/bytecodeListing/coroutines/spilling/unreachable.txt
vendored
Normal file
18
compiler/testData/codegen/bytecodeListing/coroutines/spilling/unreachable.txt
vendored
Normal file
@@ -0,0 +1,18 @@
|
||||
@kotlin.coroutines.jvm.internal.DebugMetadata
|
||||
@kotlin.Metadata
|
||||
final class UnreachableKt$test$1 {
|
||||
field label: int
|
||||
private field p$0: java.lang.String
|
||||
inner class UnreachableKt$test$1
|
||||
method <init>(p0: kotlin.coroutines.Continuation): void
|
||||
public final @org.jetbrains.annotations.NotNull method create(@org.jetbrains.annotations.Nullable p0: java.lang.Object, @org.jetbrains.annotations.NotNull p1: kotlin.coroutines.Continuation): kotlin.coroutines.Continuation
|
||||
public final method invoke(p0: java.lang.Object, p1: java.lang.Object): java.lang.Object
|
||||
public final @org.jetbrains.annotations.Nullable method invokeSuspend(@org.jetbrains.annotations.NotNull p0: java.lang.Object): java.lang.Object
|
||||
}
|
||||
|
||||
@kotlin.Metadata
|
||||
public final class UnreachableKt {
|
||||
inner class UnreachableKt$test$1
|
||||
public final static method test(): void
|
||||
public final static method use(@org.jetbrains.annotations.NotNull p0: kotlin.jvm.functions.Function2): void
|
||||
}
|
||||
@@ -1,5 +1,4 @@
|
||||
// !LANGUAGE: +InlineClasses
|
||||
// IGNORE_BACKEND: JVM_IR
|
||||
|
||||
annotation class Ann
|
||||
|
||||
|
||||
69
compiler/testData/codegen/bytecodeListing/inlineClasses/annotationsOnHiddenConstructor_ir.txt
vendored
Normal file
69
compiler/testData/codegen/bytecodeListing/inlineClasses/annotationsOnHiddenConstructor_ir.txt
vendored
Normal file
@@ -0,0 +1,69 @@
|
||||
@java.lang.annotation.Retention
|
||||
@kotlin.Metadata
|
||||
public annotation class Ann
|
||||
|
||||
@kotlin.Metadata
|
||||
public final class Sealed$Derived {
|
||||
inner class Sealed$Derived
|
||||
private method <init>(p0: int): void
|
||||
public synthetic @Ann method <init>(p0: int, p1: kotlin.jvm.internal.DefaultConstructorMarker): void
|
||||
}
|
||||
|
||||
@kotlin.Metadata
|
||||
public final class Sealed$Inner {
|
||||
synthetic final @org.jetbrains.annotations.NotNull field this$0: Sealed
|
||||
private final field z2: int
|
||||
inner class Sealed$Inner
|
||||
public synthetic @Ann method <init>(p0: Sealed, p1: int, @Ann p2: int, @Ann p3: java.lang.String, p4: kotlin.jvm.internal.DefaultConstructorMarker): void
|
||||
private method <init>(p0: Sealed, p1: int, p2: int, p3: java.lang.String): void
|
||||
public final method getZ2-a_XrcN0(): int
|
||||
}
|
||||
|
||||
@kotlin.Metadata
|
||||
public abstract class Sealed {
|
||||
private final field z: int
|
||||
inner class Sealed$Derived
|
||||
inner class Sealed$Inner
|
||||
private @Ann method <init>(@Ann p0: int): void
|
||||
public synthetic method <init>(p0: int, p1: kotlin.jvm.internal.DefaultConstructorMarker): void
|
||||
public final method getZ-a_XrcN0(): int
|
||||
}
|
||||
|
||||
@kotlin.Metadata
|
||||
public final class Test$Inner {
|
||||
synthetic final @org.jetbrains.annotations.NotNull field this$0: Test
|
||||
private final field z2: int
|
||||
inner class Test$Inner
|
||||
public synthetic @Ann method <init>(p0: Test, p1: int, @Ann p2: int, @Ann p3: java.lang.String, p4: kotlin.jvm.internal.DefaultConstructorMarker): void
|
||||
private method <init>(p0: Test, p1: int, p2: int, p3: java.lang.String): void
|
||||
public final method getZ2-a_XrcN0(): int
|
||||
}
|
||||
|
||||
@kotlin.Metadata
|
||||
public final class Test {
|
||||
private final field z: int
|
||||
inner class Test$Inner
|
||||
public synthetic @Ann method <init>(@Ann p0: int, p1: kotlin.jvm.internal.DefaultConstructorMarker): void
|
||||
private method <init>(p0: int): void
|
||||
public synthetic @Ann method <init>(p0: int, @Ann p1: int, p2: kotlin.jvm.internal.DefaultConstructorMarker): void
|
||||
private @Ann method <init>(p0: int, @Ann p1: java.lang.String): void
|
||||
private method <init>(p0: int, p1: int): void
|
||||
public final method getZ-a_XrcN0(): int
|
||||
}
|
||||
|
||||
@kotlin.Metadata
|
||||
public final class Z {
|
||||
private final field x: int
|
||||
private synthetic method <init>(p0: int): void
|
||||
public synthetic final static method box-impl(p0: int): Z
|
||||
public static method constructor-impl(p0: int): int
|
||||
public method equals(@org.jetbrains.annotations.Nullable p0: java.lang.Object): boolean
|
||||
public static method equals-impl(p0: int, @org.jetbrains.annotations.Nullable p1: java.lang.Object): boolean
|
||||
public final static method equals-impl0(p0: int, p1: int): boolean
|
||||
public final method getX(): int
|
||||
public method hashCode(): int
|
||||
public static method hashCode-impl(p0: int): int
|
||||
public @org.jetbrains.annotations.NotNull method toString(): java.lang.String
|
||||
public static @org.jetbrains.annotations.NotNull method toString-impl(p0: int): java.lang.String
|
||||
public synthetic final method unbox-impl(): int
|
||||
}
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user