Compare commits

..

64 Commits

Author SHA1 Message Date
Nicolay Mitropolsky
4a4eee7b36 JavaClassifierTypeImpl.resolutionResult dropped 2020-06-18 10:34:22 +03:00
Ilya Gorbunov
e13a38a758 Fix OnlyInputType usage in tests where it can be invisible 2020-06-18 09:34:13 +03:00
Jinseong Jeon
9e9ca4953f FIR2IR: coerce to Unit when "when" expr is not effectively exhaustive 2020-06-18 09:23:32 +03:00
Vladimir Ilmov
62dcfcde79 (CoroutineDebugger) -core jar has precedence over -debug
#KT-39412 fixed
 #KT-39648 fixed
2020-06-17 23:48:09 +02:00
Dmitry Petrov
4739adb6dc KT-36992 Do not generate annotations on synthetic accessors
Also, do not generate nullability annotations on synthetic methods.
2020-06-17 23:54:51 +03:00
Steven Schäfer
03651f1dd4 IR: Fix inner class type parameters in IrTypeSystemContext 2020-06-17 22:10:00 +03:00
Alexander Udalov
650469024e Fix expected FQ name in JavaTypeTest.nestedTypes 2020-06-17 19:47:45 +02:00
Alexander Udalov
2be94d9d2f Fix compilation of stdlib when JDK_16 points to JDK 8+ 2020-06-17 19:46:18 +02:00
Georgy Bronnikov
c015463926 IR: remove field fake overrides 2020-06-17 20:02:26 +03:00
Georgy Bronnikov
1bb3f60bad IR: use super qualifier in Java field accesses 2020-06-17 20:02:26 +03:00
Georgy Bronnikov
36f22dafc5 IR: remove field fake override usage
Still a problem: Java static fields.
2020-06-17 20:02:26 +03:00
Ilya Gorbunov
41131e46d7 Shadow addSuppressed member with an extension
#KT-38777
2020-06-17 19:45:15 +03:00
Ilya Gorbunov
95625d0fae Do not place copyrights in stdlib api dump .kt files 2020-06-17 19:45:15 +03:00
Ilya Gorbunov
2fe222e8e7 Add SKIP_DCE_DRIVEN directive in JS-IR tests
Otherwise they fail with a compiler exception:
"An operation is not implemented: SAM conversion"
2020-06-17 19:45:15 +03:00
Ilya Gorbunov
de6154980d Make ReadOnlyProperty and PropertyDelegateProvider fun interfaces 2020-06-17 19:45:15 +03:00
Ilya Gorbunov
d2ea108123 Make Comparator fun interface in Common and JS 2020-06-17 19:45:15 +03:00
Ilya Gorbunov
388e619d90 Increase memory for Kotlin compile daemon to 2200M 2020-06-17 19:37:03 +03:00
Ilya Gorbunov
f3a2ff8646 Advance bootstrap to 1.4.20-dev-710 2020-06-17 19:37:03 +03:00
Alexander Udalov
117aae8a6b Use experimental javaType in full reflect where it's not supported yet
#KT-22936 Fixed
 #KT-34344 Fixed
2020-06-17 18:33:08 +02:00
Alexander Udalov
9e37b62f62 Support KType.javaType in stdlib
#KT-32241 Fixed
2020-06-17 18:33:08 +02:00
Dmitry Savvinov
55595fe2c6 Make sure that commonizer is enabled before adding -no-default-libs argument
^KT-39632 Fixed
2020-06-17 17:51:29 +03:00
Vladimir Ilmov
db127bb414 (CoroutineDebugger) fails to start in gradle mode
#KT-39634 fixed
2020-06-17 15:35:10 +02:00
Sergey Rostov
3d86e92bf5 gradle.kts standalone scripts: show actions inside single notification 2020-06-17 14:30:18 +03:00
Sergey Rostov
64b1cc7fd4 gradle.kts legacy: out of project script notification 2020-06-17 14:30:18 +03:00
Sergey Rostov
cc95c16ac2 minor: rename GradleScriptNotificationProvider 2020-06-17 14:30:18 +03:00
Sergey Rostov
bc16fbf438 gradle.kts: check gradle version before loading from fs cache 2020-06-17 14:30:18 +03:00
Sergey Rostov
7d31d7f20c default scripting support: remove notifications after script definitions update 2020-06-17 14:30:18 +03:00
Sergey Rostov
b9fda902fb gradle.kts: update notification only after caches updated 2020-06-17 14:30:17 +03:00
Sergey Rostov
ce20196006 GradleScriptConfigurationsImportingFeature 2020-06-17 14:30:17 +03:00
Sergey Rostov
631e68c99a gradle.kts postponed loading: hide notifaction right after click on action 2020-06-17 14:30:17 +03:00
Sergey Rostov
ace7ae19b4 gradle.kts standalone scripts: load configuration after switching without prompt 2020-06-17 14:30:17 +03:00
Sergey Rostov
07654b4c0e gradle.kts, minor: cleanup & simplify code 2020-06-17 14:30:17 +03:00
Sergey Rostov
b2e629dceb gradle.kts legacy: don't start loading without prompt on first opening 2020-06-17 14:30:17 +03:00
Sergey Rostov
0234678804 gradle.kts: update notifications when scripting support was changed 2020-06-17 14:30:17 +03:00
Sergey Rostov
caa5aadc98 GradleBuildRootsManager: check gradle version change in gradle-wrapper.properties 2020-06-17 14:30:17 +03:00
Sergey Rostov
463908f6f4 scriptConfigurationsNeedToBeUpdatedBalloon registry key 2020-06-17 14:30:17 +03:00
Sergey Rostov
cc67ac631f GradleBuildRootsManager: update notifications in corner cases
- notification for all visible editors should be updates on each change,
since it may depend on last modified ts.
- notifications should be updated only for active editors, not all opened
- we should recheck it on editor activation too
- analyzer should be restarted on roots update only
2020-06-17 14:30:16 +03:00
Sergey Rostov
a150014e74 GradleBuildRootsManager: implement getScriptFirstSeenTs 2020-06-17 14:30:16 +03:00
Sergey Rostov
b543588ccd GradleScriptNotifications: suggest to import and link gradle project 2020-06-17 14:30:16 +03:00
Sergey Rostov
9096d21fcd GradleScriptNotifications: extract and fix i18n strings 2020-06-17 14:30:16 +03:00
Sergey Rostov
632e88459e GradleBuildRootsManager: fix for autoload 2020-06-17 14:30:16 +03:00
Sergey Rostov
de7d82e42b GradleScriptNotifications: typo in code 2020-06-17 14:30:16 +03:00
Sergey Rostov
6f0bd6c122 GradleBuildRoot: ability to detect if file was existed before import 2020-06-17 14:30:16 +03:00
Sergey Rostov
7384c89ddd GradleBuildRootsManager, minor: fix notifications 2020-06-17 14:30:16 +03:00
Sergey Rostov
fd9b14ed29 GradleBuildRoot: require LastModifiedFiles explicitly 2020-06-17 14:30:16 +03:00
Sergey Rostov
2ed68643cb GradleBuildRoot: remove classes nesting 2020-06-17 14:30:15 +03:00
Sergey Rostov
d8892ced9d gradle.kts: standalone scripts support (without ui and persistence) 2020-06-17 14:30:15 +03:00
Sergey Rostov
5ed7abd15d scripting: drop ManualConfigurationLoading and kotlin.gradle.scripts.useIdeaProjectImport registry flag 2020-06-17 14:30:15 +03:00
Sergey Rostov
69dc963f97 LastModifiedFiles: fix concurrency 2020-06-17 14:30:15 +03:00
Sergey Rostov
19cc9c81dc GradleBuildRoot: std scripts under project roots should be treated as new 2020-06-17 14:30:15 +03:00
Sergey Rostov
7b1b50499d GradleBuildRoot: add projects from settings
Fir the cases when they are missed absent in imported data
2020-06-17 14:30:15 +03:00
Sergey Rostov
a3750b6419 GradleBuildRoot: extract GradleBuildRootsLocator for testing 2020-06-17 14:30:15 +03:00
Victor Petukhov
c0f4ee7dc9 Revert "Add missing definitelyDoesNotContainName methods"
This reverts commit b74692e9
2020-06-17 13:16:16 +03:00
Victor Petukhov
447308dcfc Revert "Revert "Revert "Completely rewrite reifiedIntTypeAnalysis, making it more streamline"""
This reverts commit 5567033b
2020-06-17 13:02:40 +03:00
Ilmir Usmanov
1cccceabb9 Revert "Fix merging two reference values"
This reverts commit 85e2392f
2020-06-17 13:02:40 +03:00
Ilmir Usmanov
d9821412d0 Do not generate fields for unused suspend lambda parameters
This also allows us to not spill them in the lambda.
But, disable this optimization for local named functions.

 #KT-16222 In progress
2020-06-17 12:00:25 +02:00
Ilya Chernikov
a292eb865b Add script definition for extension scripts and...
IDE consoles.
2020-06-17 09:37:24 +02:00
Dmitriy Dolovov
1329030281 IDE perf tests for K/N: Re-enable PerformanceNativeProjectsTest 2020-06-17 12:03:39 +07:00
Dmitriy Dolovov
10e5dc1f63 IDE perf tests for K/N: Add assertion on failed Gradle project import 2020-06-17 12:03:33 +07:00
Dmitriy Dolovov
d9e5407ecb IDE perf tests for K/N: Switch to 1.4-M2 2020-06-17 12:03:27 +07:00
Dmitriy Dolovov
439808952d [Commonizer] Fix incorrect merging KLIB dependencies
^KT-39609
2020-06-17 11:38:27 +07:00
Victor Petukhov
901b794af3 Use lexical scope from trace during checking suspend context if the analysis of engaged parent function isn't completed
^KT-39461 Fixed
2020-06-16 22:00:04 +03:00
Dmitry Petrov
02f6a03ff7 JVM_IR: fix nullability annotations on synthetic marker parameters
Synthetic marker parameters (of type
Lkotlin/jvm/internal/DefaultConstructorMarker;) don't have annotations
(including nullability annotations).

Also, for constructor accessors corresponding parameter should be
nullable (since we pass 'null' as an argument there).

KT-36966
2020-06-16 21:29:52 +03:00
Ilya Chernikov
2656eeb164 NI: Optimize some potential hot places 2020-06-16 20:13:58 +03:00
225 changed files with 3674 additions and 1753 deletions

View File

@@ -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>

View File

@@ -1,3 +1,3 @@
<component name="DependencyValidationManager">
<scope name="Apply copyright" pattern="!file[*]:*//testData//*&amp;&amp;!file[*]:testData//*&amp;&amp;!file[*]:*.gradle.kts&amp;&amp;!file[*]:*.gradle&amp;&amp;!file[kotlin.kotlin-ultimate]:*/&amp;&amp;!file[kotlin.kotlin-ultimate.*]:*/" />
<scope name="Apply copyright" pattern="!file[*]:*//testData//*&amp;&amp;!file[*]:testData//*&amp;&amp;!file[*]:*.gradle.kts&amp;&amp;!file[*]:*.gradle&amp;&amp;!file[kotlin.kotlin-ultimate]:*/&amp;&amp;!file[kotlin.kotlin-ultimate.*]:*/&amp;&amp;!file[kotlin.libraries]:stdlib/api//*" />
</component>

View File

@@ -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.*;

View File

@@ -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> =

View File

@@ -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

View File

@@ -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>()

View File

@@ -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()

View File

@@ -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)
}
}

View File

@@ -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");

View File

@@ -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)

View File

@@ -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

View File

@@ -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");

View File

@@ -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");

View File

@@ -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
}
)
}
}

View File

@@ -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

View File

@@ -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")
}

View File

@@ -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
*/

View File

@@ -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

View File

@@ -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

View File

@@ -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>

View File

@@ -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

View File

@@ -775,8 +775,7 @@ class LocalDeclarationsLowering(
visibility,
isFinal = true,
isExternal = false,
isStatic = false,
isFakeOverride = false
isStatic = false
).also {
descriptor.bind(it)
it.parent = parent

View File

@@ -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)

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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")

View File

@@ -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
}

View File

@@ -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

View File

@@ -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 &&

View File

@@ -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)

View File

@@ -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) {

View File

@@ -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)
}

View File

@@ -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

View File

@@ -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 {

View File

@@ -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)
}

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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(

View File

@@ -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)

View File

@@ -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)
}

View File

@@ -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
}
}

View File

@@ -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?

View File

@@ -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?

View File

@@ -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

View File

@@ -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()
}

View File

@@ -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?,

View File

@@ -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")
}
}

View File

@@ -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

View File

@@ -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
)
}

View File

@@ -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()
}

View File

@@ -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, "")
}
}

View File

@@ -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)

View File

@@ -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

View File

@@ -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 =

View File

@@ -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
}
}

View File

@@ -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())

View File

@@ -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)
;
}

View File

@@ -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()
}
}

View File

@@ -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(

View File

@@ -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) {

View File

@@ -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
)

View File

@@ -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()
}

View File

@@ -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

View File

@@ -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)
}
}

View File

@@ -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))

View File

@@ -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()
}

View File

@@ -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
}

View File

@@ -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
}

View File

@@ -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> {

View 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
}

View File

@@ -1,5 +1,4 @@
// TARGET_BACKEND: JVM
// IGNORE_BACKEND_FIR: JVM_IR
// FILE: ProtectedField.java
public abstract class ProtectedField {

View File

@@ -1,5 +1,4 @@
// !LANGUAGE: -ProhibitProtectedCallFromInline
// IGNORE_BACKEND_FIR: JVM_IR
// TARGET_BACKEND: JVM
// FILE: JavaClass.java

View 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"
}

View 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"
}

View File

@@ -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"
}

View File

@@ -1,4 +1,3 @@
// IGNORE_BACKEND_FIR: JVM_IR
// TARGET_BACKEND: JVM
// WITH_RUNTIME

View File

@@ -1,4 +1,3 @@
// IGNORE_BACKEND_FIR: JVM_IR
// TARGET_BACKEND: JVM
// WITH_RUNTIME

View File

@@ -1,4 +1,3 @@
// IGNORE_BACKEND_FIR: JVM_IR
// TARGET_BACKEND: JVM
// WITH_RUNTIME

View File

@@ -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)

View File

@@ -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)

View File

@@ -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
}

View File

@@ -1,4 +1,3 @@
// IGNORE_BACKEND: JVM_IR
annotation class Ann
class Foo private @Ann constructor(@Ann s: String) {

View 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
}

View 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()
}
}

View 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

View 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)
}
}

View 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
}

View 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
}
}

View 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

View 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())
}
}

View 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
}

View 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) {}
}
}

View 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
}

View File

@@ -0,0 +1,11 @@
// WITH_RUNTIME
// IGNORE_BACKEND: JVM_IR
fun use(c: suspend (String) -> Unit) {}
fun test() {
use {
throw IllegalStateException("")
it + ""
}
}

View 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
}

View File

@@ -1,5 +1,4 @@
// !LANGUAGE: +InlineClasses
// IGNORE_BACKEND: JVM_IR
annotation class Ann

View 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