mirror of
https://github.com/jlengrand/kotlin.git
synced 2026-05-04 00:21:28 +00:00
Compare commits
93 Commits
build-1.5.
...
rrn/perf/r
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
88e4f79050 | ||
|
|
47a8a7d7ec | ||
|
|
9d857fbb30 | ||
|
|
89f4a8a72b | ||
|
|
525d7c37a4 | ||
|
|
53bf0b1c42 | ||
|
|
540c69ab89 | ||
|
|
86041096fd | ||
|
|
f82c28bd79 | ||
|
|
a0d35e56a9 | ||
|
|
fa525a8359 | ||
|
|
c4ddf3530d | ||
|
|
e5f3091f2c | ||
|
|
5dc0b52e38 | ||
|
|
03b5c14944 | ||
|
|
302e0fa46b | ||
|
|
8e10b5fdec | ||
|
|
8da183e4f4 | ||
|
|
b9209962cd | ||
|
|
1407af6301 | ||
|
|
2530ae6b3d | ||
|
|
c9cd49d34f | ||
|
|
89f0a790c9 | ||
|
|
468fc86a3f | ||
|
|
57d3f98ece | ||
|
|
c898805ac5 | ||
|
|
f63dac26e6 | ||
|
|
d397efb2bd | ||
|
|
3db5ba98ad | ||
|
|
3532ce7fbc | ||
|
|
c284eab2dd | ||
|
|
eb4bb9554d | ||
|
|
85d9e96632 | ||
|
|
080a832605 | ||
|
|
335c5a03b6 | ||
|
|
dc1ce19db9 | ||
|
|
bee8c0bb90 | ||
|
|
c2a46baa77 | ||
|
|
640d263ae1 | ||
|
|
656c2496a6 | ||
|
|
614d529168 | ||
|
|
47dc524763 | ||
|
|
90798d8857 | ||
|
|
f9087a8ab1 | ||
|
|
accc0e3761 | ||
|
|
0ba6412f96 | ||
|
|
bbe5cf0a70 | ||
|
|
e14848740a | ||
|
|
626c1d3b48 | ||
|
|
7cea639209 | ||
|
|
ac0aaff611 | ||
|
|
bdfc879f00 | ||
|
|
d2f831b635 | ||
|
|
7ac599520e | ||
|
|
6919f3dbb5 | ||
|
|
bf85b110da | ||
|
|
cd7841ceed | ||
|
|
f574f89f78 | ||
|
|
40eeee48b6 | ||
|
|
cbe3c66156 | ||
|
|
209ec68591 | ||
|
|
5ff4d648f4 | ||
|
|
6182228de8 | ||
|
|
c98dba6aea | ||
|
|
cf5e6b242b | ||
|
|
e9af2849ef | ||
|
|
6bc4e124fb | ||
|
|
d70b889004 | ||
|
|
36a25353e9 | ||
|
|
ac9e8f667d | ||
|
|
05872fc6a8 | ||
|
|
df815a64cf | ||
|
|
6a51ddf755 | ||
|
|
b7eded6e48 | ||
|
|
e56a3b3c30 | ||
|
|
686368749a | ||
|
|
7388e60869 | ||
|
|
042ac5555c | ||
|
|
27903b4cd6 | ||
|
|
d306d8a90e | ||
|
|
124bd559de | ||
|
|
f83841a34f | ||
|
|
9273c6326e | ||
|
|
7a745cfe5c | ||
|
|
417c841f77 | ||
|
|
e56b39bbd8 | ||
|
|
d09be811f0 | ||
|
|
0b8b20eda0 | ||
|
|
53aafbd7d9 | ||
|
|
00031c8eb1 | ||
|
|
34387e228f | ||
|
|
06ba143afe | ||
|
|
b771f9eea4 |
@@ -4,6 +4,8 @@
|
||||
[](https://www.apache.org/licenses/LICENSE-2.0)
|
||||
[](https://ge.jetbrains.com/scans?search.rootProjectNames=Kotlin)
|
||||
|
||||
[Join Kotlin 1.5 Online Event on May 25, 2021!](https://pages.jetbrains.com/kotlin-online-event-2021/github-readme)
|
||||
|
||||
# Kotlin Programming Language
|
||||
|
||||
Welcome to [Kotlin](https://kotlinlang.org/)!
|
||||
|
||||
@@ -30,7 +30,7 @@ buildscript {
|
||||
dependencies {
|
||||
bootstrapCompilerClasspath(kotlin("compiler-embeddable", bootstrapKotlinVersion))
|
||||
|
||||
classpath("org.jetbrains.kotlin:kotlin-build-gradle-plugin:0.0.27")
|
||||
classpath("org.jetbrains.kotlin:kotlin-build-gradle-plugin:0.0.28")
|
||||
classpath(kotlin("gradle-plugin", bootstrapKotlinVersion))
|
||||
classpath(kotlin("serialization", bootstrapKotlinVersion))
|
||||
classpath("org.jetbrains.dokka:dokka-gradle-plugin:0.9.17")
|
||||
@@ -335,6 +335,7 @@ extra["tasksWithWarnings"] = listOf(
|
||||
":kotlin-stdlib:compileTestKotlin",
|
||||
":kotlin-stdlib-jdk7:compileTestKotlin",
|
||||
":kotlin-stdlib-jdk8:compileTestKotlin",
|
||||
":plugins:uast-kotlin-base:compileKotlin",
|
||||
":plugins:uast-kotlin:compileKotlin",
|
||||
":plugins:uast-kotlin:compileTestKotlin",
|
||||
":plugins:uast-kotlin-fir:compileKotlin",
|
||||
@@ -850,7 +851,8 @@ tasks {
|
||||
":idea:idea-frontend-api:test",
|
||||
":idea:idea-frontend-fir:test",
|
||||
":idea:idea-frontend-fir:idea-fir-low-level-api:test",
|
||||
":plugins:uast-kotlin-fir:test"
|
||||
":plugins:uast-kotlin-fir:test",
|
||||
":idea:idea-fir-fe10-binding:test"
|
||||
)
|
||||
}
|
||||
|
||||
@@ -967,6 +969,7 @@ tasks {
|
||||
":prepare:ide-plugin-dependencies:compiler-components-for-jps:publish",
|
||||
":prepare:ide-plugin-dependencies:parcelize-compiler-plugin-for-ide:publish",
|
||||
":prepare:ide-plugin-dependencies:lombok-compiler-plugin-for-ide:publish",
|
||||
":prepare:ide-plugin-dependencies:kotlin-compiler-tests-for-ide:publish",
|
||||
":kotlin-script-runtime:publish",
|
||||
":kotlin-script-util:publish",
|
||||
":kotlin-scripting-common:publish",
|
||||
|
||||
@@ -22,7 +22,7 @@ buildscript {
|
||||
}
|
||||
|
||||
dependencies {
|
||||
classpath("org.jetbrains.kotlin:kotlin-build-gradle-plugin:0.0.27")
|
||||
classpath("org.jetbrains.kotlin:kotlin-build-gradle-plugin:0.0.28")
|
||||
classpath("org.jetbrains.kotlin:kotlin-gradle-plugin:${project.bootstrapKotlinVersion}")
|
||||
classpath("org.jetbrains.kotlin:kotlin-sam-with-receiver:${project.bootstrapKotlinVersion}")
|
||||
}
|
||||
@@ -144,7 +144,7 @@ java {
|
||||
dependencies {
|
||||
implementation(kotlin("stdlib", embeddedKotlinVersion))
|
||||
implementation("org.jetbrains.kotlin:kotlin-gradle-plugin:${project.bootstrapKotlinVersion}")
|
||||
implementation("org.jetbrains.kotlin:kotlin-build-gradle-plugin:0.0.27")
|
||||
implementation("org.jetbrains.kotlin:kotlin-build-gradle-plugin:0.0.28")
|
||||
implementation("com.gradle.publish:plugin-publish-plugin:0.14.0")
|
||||
|
||||
implementation("net.rubygrapefruit:native-platform:${property("versions.native-platform")}")
|
||||
|
||||
@@ -21,7 +21,7 @@ buildscript {
|
||||
mavenCentral()
|
||||
}
|
||||
dependencies {
|
||||
classpath("org.jetbrains.kotlin:kotlin-build-gradle-plugin:0.0.27")
|
||||
classpath("org.jetbrains.kotlin:kotlin-build-gradle-plugin:0.0.28")
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -274,13 +274,15 @@ fun Project.publishProjectJars(projects: List<String>, libraryDependencies: List
|
||||
javadocJar()
|
||||
}
|
||||
|
||||
fun Project.publishTestJar(projectName: String) {
|
||||
fun Project.publishTestJar(projects: List<String>) {
|
||||
apply<JavaPlugin>()
|
||||
|
||||
val fatJarContents by configurations.creating
|
||||
|
||||
dependencies {
|
||||
fatJarContents(project(projectName, configuration = "tests-jar")) { isTransitive = false }
|
||||
for (projectName in projects) {
|
||||
fatJarContents(project(projectName, configuration = "tests-jar")) { isTransitive = false }
|
||||
}
|
||||
}
|
||||
|
||||
publish()
|
||||
@@ -297,7 +299,7 @@ fun Project.publishTestJar(projectName: String) {
|
||||
|
||||
sourcesJar {
|
||||
from {
|
||||
project(projectName).testSourceSet.allSource
|
||||
projects.map { project(it).testSourceSet.allSource }
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -47,7 +47,9 @@ abstract class LambdaInfo(@JvmField val isCrossInline: Boolean) : FunctionalArgu
|
||||
|
||||
abstract val invokeMethod: Method
|
||||
|
||||
abstract val invokeMethodDescriptor: FunctionDescriptor
|
||||
abstract val invokeMethodParameters: List<KotlinType?>
|
||||
|
||||
abstract val invokeMethodReturnType: KotlinType?
|
||||
|
||||
abstract val capturedVars: List<CapturedParamDesc>
|
||||
|
||||
@@ -98,14 +100,16 @@ class PsiDefaultLambda(
|
||||
offset: Int,
|
||||
needReification: Boolean
|
||||
) : DefaultLambda(lambdaClassType, capturedArgs, parameterDescriptor, offset, needReification) {
|
||||
override fun mapAsmSignature(sourceCompiler: SourceCompilerForInline): Method {
|
||||
return sourceCompiler.state.typeMapper.mapSignatureSkipGeneric(invokeMethodDescriptor).asmMethod
|
||||
}
|
||||
override fun mapAsmSignature(sourceCompiler: SourceCompilerForInline, descriptor: FunctionDescriptor): Method =
|
||||
sourceCompiler.state.typeMapper.mapSignatureSkipGeneric(descriptor).asmMethod
|
||||
|
||||
override fun findInvokeMethodDescriptor(): FunctionDescriptor =
|
||||
override fun findInvokeMethodDescriptor(isPropertyReference: Boolean): FunctionDescriptor =
|
||||
parameterDescriptor.type.memberScope
|
||||
.getContributedFunctions(OperatorNameConventions.INVOKE, NoLookupLocation.FROM_BACKEND)
|
||||
.single()
|
||||
.single().let {
|
||||
// property reference generates erased 'get' method
|
||||
if (isPropertyReference) it.original else it
|
||||
}
|
||||
}
|
||||
|
||||
abstract class DefaultLambda(
|
||||
@@ -124,7 +128,13 @@ abstract class DefaultLambda(
|
||||
final override lateinit var invokeMethod: Method
|
||||
private set
|
||||
|
||||
override lateinit var invokeMethodDescriptor: FunctionDescriptor
|
||||
private lateinit var invokeMethodDescriptor: FunctionDescriptor
|
||||
|
||||
override val invokeMethodParameters: List<KotlinType?>
|
||||
get() = invokeMethodDescriptor.valueParameters.map { it.returnType } // should be FunctionN, so no extension receiver
|
||||
|
||||
override val invokeMethodReturnType: KotlinType?
|
||||
get() = invokeMethodDescriptor.returnType
|
||||
|
||||
final override lateinit var capturedVars: List<CapturedParamDesc>
|
||||
private set
|
||||
@@ -155,10 +165,7 @@ abstract class DefaultLambda(
|
||||
}
|
||||
}, ClassReader.SKIP_CODE or ClassReader.SKIP_FRAMES or ClassReader.SKIP_DEBUG)
|
||||
|
||||
invokeMethodDescriptor = findInvokeMethodDescriptor().let {
|
||||
//property reference generates erased 'get' method
|
||||
if (isPropertyReference) it.original else it
|
||||
}
|
||||
invokeMethodDescriptor = findInvokeMethodDescriptor(isPropertyReference)
|
||||
|
||||
val descriptor = Type.getMethodDescriptor(Type.VOID_TYPE, *capturedArgs)
|
||||
val constructor = getMethodNode(classBytes, "<init>", descriptor, lambdaClassType)?.node
|
||||
@@ -182,7 +189,7 @@ abstract class DefaultLambda(
|
||||
|
||||
val methodName = (if (isPropertyReference) OperatorNameConventions.GET else OperatorNameConventions.INVOKE).asString()
|
||||
|
||||
val signature = mapAsmSignature(sourceCompiler)
|
||||
val signature = mapAsmSignature(sourceCompiler, invokeMethodDescriptor)
|
||||
|
||||
node = getMethodNode(classBytes, methodName, signature.descriptor, lambdaClassType, signatureAmbiguity = true)
|
||||
?: error("Can't find method '$methodName$signature' in '${classReader.className}'")
|
||||
@@ -195,9 +202,10 @@ abstract class DefaultLambda(
|
||||
}
|
||||
}
|
||||
|
||||
protected abstract fun mapAsmSignature(sourceCompiler: SourceCompilerForInline): Method
|
||||
protected abstract fun mapAsmSignature(sourceCompiler: SourceCompilerForInline, descriptor: FunctionDescriptor): Method
|
||||
|
||||
protected abstract fun findInvokeMethodDescriptor(): FunctionDescriptor
|
||||
// TODO: get rid of this; descriptors should *only* be used by PsiDefaultLambda
|
||||
protected abstract fun findInvokeMethodDescriptor(isPropertyReference: Boolean): FunctionDescriptor
|
||||
|
||||
private companion object {
|
||||
val PROPERTY_REFERENCE_SUPER_CLASSES =
|
||||
@@ -221,7 +229,6 @@ abstract class ExpressionLambda(isCrossInline: Boolean) : LambdaInfo(isCrossInli
|
||||
node.node.preprocessSuspendMarkers(forInline = true, keepFakeContinuation = false)
|
||||
}
|
||||
|
||||
abstract fun getInlineSuspendLambdaViewDescriptor(): FunctionDescriptor
|
||||
abstract fun isCapturedSuspend(desc: CapturedParamDesc): Boolean
|
||||
}
|
||||
|
||||
@@ -237,7 +244,24 @@ class PsiExpressionLambda(
|
||||
|
||||
override val invokeMethod: Method
|
||||
|
||||
override val invokeMethodDescriptor: FunctionDescriptor
|
||||
val invokeMethodDescriptor: FunctionDescriptor
|
||||
|
||||
override val invokeMethodParameters: List<KotlinType?>
|
||||
get() {
|
||||
val actualInvokeDescriptor = if (isSuspend)
|
||||
getOrCreateJvmSuspendFunctionView(
|
||||
invokeMethodDescriptor,
|
||||
languageVersionSettings.isReleaseCoroutines(),
|
||||
typeMapper.bindingContext
|
||||
)
|
||||
else
|
||||
invokeMethodDescriptor
|
||||
val valueParameters = actualInvokeDescriptor.valueParameters.map { it.returnType }
|
||||
return actualInvokeDescriptor.extensionReceiverParameter?.let { listOf(it.returnType) + valueParameters } ?: valueParameters
|
||||
}
|
||||
|
||||
override val invokeMethodReturnType: KotlinType?
|
||||
get() = invokeMethodDescriptor.returnType
|
||||
|
||||
val classDescriptor: ClassDescriptor
|
||||
|
||||
@@ -325,14 +349,6 @@ class PsiExpressionLambda(
|
||||
val isPropertyReference: Boolean
|
||||
get() = propertyReferenceInfo != null
|
||||
|
||||
override fun getInlineSuspendLambdaViewDescriptor(): FunctionDescriptor {
|
||||
return getOrCreateJvmSuspendFunctionView(
|
||||
invokeMethodDescriptor,
|
||||
languageVersionSettings.isReleaseCoroutines(),
|
||||
typeMapper.bindingContext
|
||||
)
|
||||
}
|
||||
|
||||
override fun isCapturedSuspend(desc: CapturedParamDesc): Boolean =
|
||||
isCapturedSuspendLambda(closure, desc.fieldName, typeMapper.bindingContext)
|
||||
}
|
||||
|
||||
@@ -23,13 +23,13 @@ import org.jetbrains.kotlin.codegen.optimization.fixStack.top
|
||||
import org.jetbrains.kotlin.codegen.optimization.nullCheck.isCheckParameterIsNotNull
|
||||
import org.jetbrains.kotlin.codegen.pseudoInsns.PseudoInsn
|
||||
import org.jetbrains.kotlin.config.LanguageFeature
|
||||
import org.jetbrains.kotlin.descriptors.FunctionDescriptor
|
||||
import org.jetbrains.kotlin.descriptors.ParameterDescriptor
|
||||
import org.jetbrains.kotlin.descriptors.ValueParameterDescriptor
|
||||
import org.jetbrains.kotlin.incremental.components.NoLookupLocation
|
||||
import org.jetbrains.kotlin.load.java.JvmAbi
|
||||
import org.jetbrains.kotlin.resolve.descriptorUtil.builtIns
|
||||
import org.jetbrains.kotlin.resolve.jvm.AsmTypes
|
||||
import org.jetbrains.kotlin.resolve.jvm.AsmTypes.OBJECT_TYPE
|
||||
import org.jetbrains.kotlin.types.KotlinType
|
||||
import org.jetbrains.kotlin.util.OperatorNameConventions
|
||||
import org.jetbrains.kotlin.utils.SmartList
|
||||
import org.jetbrains.kotlin.utils.SmartSet
|
||||
import org.jetbrains.kotlin.utils.addToStdlib.safeAs
|
||||
@@ -233,38 +233,24 @@ class MethodInliner(
|
||||
return
|
||||
}
|
||||
|
||||
// in case of inlining suspend lambda reference as ordinary parameter of inline function:
|
||||
// suspend fun foo (...) ...
|
||||
// inline fun inlineMe(c: (...) -> ...) ...
|
||||
// builder {
|
||||
// inlineMe(::foo)
|
||||
// }
|
||||
// we should create additional parameter for continuation.
|
||||
val valueParameters = info.invokeMethodParameters
|
||||
// If suspend lambda has no continuation at the end, add it here. (In the IR backend, suspend lambdas
|
||||
// always come pre-lowered with the continuation parameter.)
|
||||
var coroutineDesc = desc
|
||||
val actualInvokeDescriptor: FunctionDescriptor
|
||||
if (info.isSuspend) {
|
||||
actualInvokeDescriptor = (info as ExpressionLambda).getInlineSuspendLambdaViewDescriptor()
|
||||
val parametersSize = actualInvokeDescriptor.valueParameters.size +
|
||||
(if (actualInvokeDescriptor.extensionReceiverParameter != null) 1 else 0)
|
||||
// And here we expect invoke(...Ljava/lang/Object;) be replaced with invoke(...Lkotlin/coroutines/Continuation;)
|
||||
// if this does not happen, insert fake continuation, since we could not have one yet.
|
||||
if (!inliningContext.root.state.isIrBackend && info.isSuspend) {
|
||||
val argumentTypes = Type.getArgumentTypes(desc)
|
||||
if (argumentTypes.size != parametersSize &&
|
||||
// But do not add it in IR. In IR we already have lowered lambdas with additional parameter, while in Old BE we don't.
|
||||
!inliningContext.root.state.isIrBackend
|
||||
) {
|
||||
if (argumentTypes.size != valueParameters.size) {
|
||||
addFakeContinuationMarker(this)
|
||||
coroutineDesc = Type.getMethodDescriptor(Type.getReturnType(desc), *argumentTypes, AsmTypes.OBJECT_TYPE)
|
||||
}
|
||||
} else {
|
||||
actualInvokeDescriptor = info.invokeMethodDescriptor
|
||||
}
|
||||
|
||||
val valueParameters =
|
||||
listOfNotNull(actualInvokeDescriptor.extensionReceiverParameter) + actualInvokeDescriptor.valueParameters
|
||||
|
||||
val erasedInvokeFunction = ClosureCodegen.getErasedInvokeFunction(actualInvokeDescriptor)
|
||||
val invokeParameters = erasedInvokeFunction.valueParameters
|
||||
// TODO: this is a weird way to get N instances of `Any?`
|
||||
val moduleBuiltIns = inliningContext.root.sourceCompilerForInline.compilationContextDescriptor.builtIns
|
||||
val erasedFunctionType = moduleBuiltIns.getFunction(valueParameters.size).defaultType
|
||||
val erasedInvokeFunction = erasedFunctionType.memberScope
|
||||
.getContributedFunctions(OperatorNameConventions.INVOKE, NoLookupLocation.FROM_BACKEND).first()
|
||||
val invokeParameters = erasedInvokeFunction.valueParameters.map { it.returnType }
|
||||
|
||||
val valueParamShift = max(nextLocalIndex, markerShift)//NB: don't inline cause it changes
|
||||
val parameterTypesFromDesc = info.invokeMethod.argumentTypes
|
||||
@@ -305,7 +291,7 @@ class MethodInliner(
|
||||
result.reifiedTypeParametersUsages.mergeAll(lambdaResult.reifiedTypeParametersUsages)
|
||||
|
||||
StackValue
|
||||
.onStack(info.invokeMethod.returnType, info.invokeMethodDescriptor.returnType)
|
||||
.onStack(info.invokeMethod.returnType, info.invokeMethodReturnType)
|
||||
.put(OBJECT_TYPE, erasedInvokeFunction.returnType, this)
|
||||
setLambdaInlining(false)
|
||||
addInlineMarker(this, false)
|
||||
@@ -1075,8 +1061,8 @@ class MethodInliner(
|
||||
|
||||
private fun putStackValuesIntoLocalsForLambdaOnInvoke(
|
||||
directOrder: List<Type>,
|
||||
directOrderOfArguments: List<ParameterDescriptor>,
|
||||
directOrderOfInvokeParameters: List<ValueParameterDescriptor>,
|
||||
directOrderOfArguments: List<KotlinType?>,
|
||||
directOrderOfInvokeParameters: List<KotlinType?>,
|
||||
shift: Int,
|
||||
iv: InstructionAdapter,
|
||||
descriptor: String
|
||||
@@ -1099,8 +1085,8 @@ class MethodInliner(
|
||||
val argumentKotlinType: KotlinType?
|
||||
val invokeParameterKotlinType: KotlinType?
|
||||
if (safeToUseArgumentKotlinType) {
|
||||
argumentKotlinType = directOrderOfArguments[index].type
|
||||
invokeParameterKotlinType = directOrderOfInvokeParameters[index].type
|
||||
argumentKotlinType = directOrderOfArguments[index]
|
||||
invokeParameterKotlinType = directOrderOfInvokeParameters[index]
|
||||
} else {
|
||||
argumentKotlinType = null
|
||||
invokeParameterKotlinType = null
|
||||
|
||||
@@ -53,6 +53,7 @@ public class Usage {
|
||||
appendln(sb, "Advanced options are non-standard and may be changed or removed without any notice.");
|
||||
}
|
||||
else {
|
||||
renderOptionJUsage(sb);
|
||||
renderArgfileUsage(sb);
|
||||
}
|
||||
|
||||
@@ -103,6 +104,15 @@ public class Usage {
|
||||
appendln(sb, argument.description().replace("\n", "\n" + StringsKt.repeat(" ", OPTION_NAME_PADDING_WIDTH)));
|
||||
}
|
||||
|
||||
private static void renderOptionJUsage(@NotNull StringBuilder sb) {
|
||||
int descriptionStart = sb.length() + OPTION_NAME_PADDING_WIDTH;
|
||||
sb.append(" -J<option>");
|
||||
while (sb.length() < descriptionStart) {
|
||||
sb.append(" ");
|
||||
}
|
||||
appendln(sb, "Pass an option directly to JVM");
|
||||
}
|
||||
|
||||
private static void renderArgfileUsage(@NotNull StringBuilder sb) {
|
||||
int descriptionStart = sb.length() + OPTION_NAME_PADDING_WIDTH;
|
||||
sb.append(" ");
|
||||
|
||||
30
compiler/fir/analysis-tests/testData/resolveWithStdlib/problems/capturedTypeInEquality.fir.txt
vendored
Normal file
30
compiler/fir/analysis-tests/testData/resolveWithStdlib/problems/capturedTypeInEquality.fir.txt
vendored
Normal file
@@ -0,0 +1,30 @@
|
||||
FILE: capturedTypeInEquality.kt
|
||||
public abstract interface FirTargetElement : R|kotlin/Any| {
|
||||
}
|
||||
public abstract interface FirFunction<F : R|FirFunction<F>|> : R|FirTargetElement| {
|
||||
}
|
||||
public abstract interface FirPropertyAccessor : R|FirFunction<FirPropertyAccessor>| {
|
||||
}
|
||||
public abstract interface FirProperty : R|kotlin/Any| {
|
||||
public abstract val getter: R|FirPropertyAccessor|
|
||||
public get(): R|FirPropertyAccessor|
|
||||
|
||||
}
|
||||
public abstract interface FirTarget<E : R|FirTargetElement|> : R|kotlin/Any| {
|
||||
public abstract val labeledElement: R|E|
|
||||
public get(): R|E|
|
||||
|
||||
}
|
||||
public final fun foo(target: R|FirTarget<FirFunction<*>>|, property: R|FirProperty|): R|kotlin/Unit| {
|
||||
lval functionTarget: R|FirFunction<*>| = R|<local>/target|.R|SubstitutionOverride</FirTarget.labeledElement: R|FirFunction<*>|>|
|
||||
lval x: R|kotlin/Int?| = (R|<local>/functionTarget| as? R|FirFunction<CapturedType(*)>|)?.{ $subj$.R|kotlin/let|<R|FirFunction<*>|, R|kotlin/Int|>(<L> = let@fun <anonymous>(it: R|FirFunction<*>|): R|kotlin/Int| <inline=Inline, kind=EXACTLY_ONCE> {
|
||||
when () {
|
||||
===(R|<local>/property|.R|/FirProperty.getter|, R|<local>/functionTarget|) -> {
|
||||
^@let Int(1)
|
||||
}
|
||||
}
|
||||
|
||||
^ Int(0)
|
||||
}
|
||||
) }
|
||||
}
|
||||
23
compiler/fir/analysis-tests/testData/resolveWithStdlib/problems/capturedTypeInEquality.kt
vendored
Normal file
23
compiler/fir/analysis-tests/testData/resolveWithStdlib/problems/capturedTypeInEquality.kt
vendored
Normal file
@@ -0,0 +1,23 @@
|
||||
interface FirTargetElement
|
||||
|
||||
interface FirFunction<F : FirFunction<F>> : FirTargetElement
|
||||
|
||||
interface FirPropertyAccessor : FirFunction<FirPropertyAccessor>
|
||||
|
||||
interface FirProperty {
|
||||
val getter: FirPropertyAccessor
|
||||
}
|
||||
|
||||
interface FirTarget<E : FirTargetElement> {
|
||||
val labeledElement: E
|
||||
}
|
||||
|
||||
fun foo(target: FirTarget<FirFunction<*>>, property: FirProperty) {
|
||||
val functionTarget = target.labeledElement
|
||||
val x = (functionTarget as? FirFunction)?.let {
|
||||
if (<!EQUALITY_NOT_APPLICABLE_WARNING!>property.getter === functionTarget<!>) {
|
||||
return@let 1
|
||||
}
|
||||
0
|
||||
}
|
||||
}
|
||||
@@ -5293,6 +5293,12 @@ public class FirDiagnosticTestGenerated extends AbstractFirDiagnosticTest {
|
||||
KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("compiler/fir/analysis-tests/testData/resolveWithStdlib/problems"), Pattern.compile("^([^.]+)\\.kt$"), null, true);
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("capturedTypeInEquality.kt")
|
||||
public void testCapturedTypeInEquality() throws Exception {
|
||||
runTest("compiler/fir/analysis-tests/testData/resolveWithStdlib/problems/capturedTypeInEquality.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("DeepCopyIrTree.kt")
|
||||
public void testDeepCopyIrTree() throws Exception {
|
||||
|
||||
@@ -5293,6 +5293,12 @@ public class FirDiagnosticsWithLightTreeTestGenerated extends AbstractFirDiagnos
|
||||
KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("compiler/fir/analysis-tests/testData/resolveWithStdlib/problems"), Pattern.compile("^([^.]+)\\.kt$"), null, true);
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("capturedTypeInEquality.kt")
|
||||
public void testCapturedTypeInEquality() throws Exception {
|
||||
runTest("compiler/fir/analysis-tests/testData/resolveWithStdlib/problems/capturedTypeInEquality.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("DeepCopyIrTree.kt")
|
||||
public void testDeepCopyIrTree() throws Exception {
|
||||
|
||||
@@ -12395,6 +12395,12 @@ public class FirOldFrontendDiagnosticsTestGenerated extends AbstractFirDiagnosti
|
||||
runTest("compiler/testData/diagnostics/tests/inference/kt40396.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("kt46515.kt")
|
||||
public void testKt46515() throws Exception {
|
||||
runTest("compiler/testData/diagnostics/tests/inference/kt46515.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("kt6175.kt")
|
||||
public void testKt6175() throws Exception {
|
||||
|
||||
@@ -12395,6 +12395,12 @@ public class FirOldFrontendDiagnosticsWithLightTreeTestGenerated extends Abstrac
|
||||
runTest("compiler/testData/diagnostics/tests/inference/kt40396.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("kt46515.kt")
|
||||
public void testKt46515() throws Exception {
|
||||
runTest("compiler/testData/diagnostics/tests/inference/kt46515.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("kt6175.kt")
|
||||
public void testKt6175() throws Exception {
|
||||
|
||||
@@ -605,6 +605,9 @@ object DIAGNOSTICS_LIST : DiagnosticList() {
|
||||
val UNINITIALIZED_VARIABLE by error<KtSimpleNameExpression> {
|
||||
parameter<FirPropertySymbol>("variable")
|
||||
}
|
||||
val UNINITIALIZED_PARAMETER by error<KtSimpleNameExpression> {
|
||||
parameter<FirVariableSymbol<FirValueParameter>>("parameter")
|
||||
}
|
||||
val UNINITIALIZED_ENUM_ENTRY by error<KtSimpleNameExpression> {
|
||||
parameter<FirVariableSymbol<FirEnumEntry>>("enumEntry")
|
||||
}
|
||||
|
||||
@@ -370,6 +370,7 @@ object FirErrors {
|
||||
|
||||
// Control flow diagnostics
|
||||
val UNINITIALIZED_VARIABLE by error1<KtSimpleNameExpression, FirPropertySymbol>()
|
||||
val UNINITIALIZED_PARAMETER by error1<KtSimpleNameExpression, FirVariableSymbol<FirValueParameter>>()
|
||||
val UNINITIALIZED_ENUM_ENTRY by error1<KtSimpleNameExpression, FirVariableSymbol<FirEnumEntry>>()
|
||||
val UNINITIALIZED_ENUM_COMPANION by error1<KtSimpleNameExpression, FirRegularClassSymbol>(SourceElementPositioningStrategies.REFERENCE_BY_QUALIFIED)
|
||||
val VAL_REASSIGNMENT by error1<KtExpression, FirVariableSymbol<*>>()
|
||||
|
||||
@@ -27,10 +27,7 @@ import org.jetbrains.kotlin.fir.resolve.dfa.cfg.JumpNode
|
||||
import org.jetbrains.kotlin.fir.symbols.AbstractFirBasedSymbol
|
||||
import org.jetbrains.kotlin.fir.symbols.impl.FirPropertyAccessorSymbol
|
||||
import org.jetbrains.kotlin.fir.typeContext
|
||||
import org.jetbrains.kotlin.fir.types.ConeKotlinType
|
||||
import org.jetbrains.kotlin.fir.types.coneType
|
||||
import org.jetbrains.kotlin.fir.types.intersectTypesOrNull
|
||||
import org.jetbrains.kotlin.fir.types.isNullable
|
||||
import org.jetbrains.kotlin.fir.types.*
|
||||
import org.jetbrains.kotlin.types.AbstractTypeChecker
|
||||
import org.jetbrains.kotlin.types.ConstantValueKind
|
||||
import org.jetbrains.kotlin.utils.addIfNotNull
|
||||
@@ -56,7 +53,7 @@ object FirReturnsImpliesAnalyzer : FirControlFlowChecker() {
|
||||
throw IllegalStateException("Update of all receivers is not possible for this logic system")
|
||||
|
||||
override fun ConeKotlinType.isAcceptableForSmartcast(): Boolean {
|
||||
return true
|
||||
return !isNullableNothing
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -234,7 +234,8 @@ internal object ConeTypeCompatibilityChecker {
|
||||
is ConeDefinitelyNotNullType -> original.collectUpperBounds()
|
||||
is ConeIntersectionType -> intersectedTypes.flatMap { it.collectUpperBounds() }.toSet()
|
||||
is ConeFlexibleType -> upperBound.collectUpperBounds()
|
||||
is ConeCapturedType, is ConeStubType, is ConeIntegerLiteralType -> throw IllegalStateException("$this should not reach here")
|
||||
is ConeCapturedType -> constructor.supertypes?.flatMap { it.collectUpperBounds() }?.toSet().orEmpty()
|
||||
is ConeStubType, is ConeIntegerLiteralType -> throw IllegalStateException("$this should not reach here")
|
||||
}
|
||||
}
|
||||
|
||||
@@ -256,7 +257,8 @@ internal object ConeTypeCompatibilityChecker {
|
||||
is ConeDefinitelyNotNullType -> original.collectLowerBounds()
|
||||
is ConeIntersectionType -> intersectedTypes.flatMap { it.collectLowerBounds() }.toSet()
|
||||
is ConeFlexibleType -> lowerBound.collectLowerBounds()
|
||||
is ConeCapturedType, is ConeStubType, is ConeIntegerLiteralType -> throw IllegalStateException("$this should not reach here")
|
||||
is ConeCapturedType -> constructor.supertypes?.flatMap { it.collectLowerBounds() }?.toSet().orEmpty()
|
||||
is ConeStubType, is ConeIntegerLiteralType -> throw IllegalStateException("$this should not reach here")
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -9,21 +9,18 @@ import org.jetbrains.kotlin.descriptors.ClassKind
|
||||
import org.jetbrains.kotlin.descriptors.Modality
|
||||
import org.jetbrains.kotlin.descriptors.Visibilities
|
||||
import org.jetbrains.kotlin.descriptors.Visibility
|
||||
import org.jetbrains.kotlin.fir.FirSession
|
||||
import org.jetbrains.kotlin.fir.FirSymbolOwner
|
||||
import org.jetbrains.kotlin.fir.*
|
||||
import org.jetbrains.kotlin.fir.analysis.checkers.context.CheckerContext
|
||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.modalityModifier
|
||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.overrideModifier
|
||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.visibilityModifier
|
||||
import org.jetbrains.kotlin.fir.analysis.getChild
|
||||
import org.jetbrains.kotlin.fir.containingClass
|
||||
import org.jetbrains.kotlin.fir.declarations.*
|
||||
import org.jetbrains.kotlin.fir.expressions.FirComponentCall
|
||||
import org.jetbrains.kotlin.fir.expressions.FirExpression
|
||||
import org.jetbrains.kotlin.fir.expressions.FirFunctionCall
|
||||
import org.jetbrains.kotlin.fir.expressions.FirQualifiedAccessExpression
|
||||
import org.jetbrains.kotlin.fir.expressions.impl.FirEmptyExpressionBlock
|
||||
import org.jetbrains.kotlin.fir.references.FirResolvedNamedReference
|
||||
import org.jetbrains.kotlin.fir.resolve.SessionHolder
|
||||
import org.jetbrains.kotlin.fir.resolve.fullyExpandedType
|
||||
import org.jetbrains.kotlin.fir.resolve.inference.isBuiltinFunctionalType
|
||||
import org.jetbrains.kotlin.fir.resolve.symbolProvider
|
||||
@@ -32,11 +29,7 @@ import org.jetbrains.kotlin.fir.resolve.transformers.firClassLike
|
||||
import org.jetbrains.kotlin.fir.scopes.ProcessorAction
|
||||
import org.jetbrains.kotlin.fir.scopes.processOverriddenFunctions
|
||||
import org.jetbrains.kotlin.fir.scopes.unsubstitutedScope
|
||||
import org.jetbrains.kotlin.fir.symbols.impl.FirClassLikeSymbol
|
||||
import org.jetbrains.kotlin.fir.symbols.impl.FirClassSymbol
|
||||
import org.jetbrains.kotlin.fir.symbols.impl.FirFunctionSymbol
|
||||
import org.jetbrains.kotlin.fir.symbols.impl.FirRegularClassSymbol
|
||||
import org.jetbrains.kotlin.fir.typeContext
|
||||
import org.jetbrains.kotlin.fir.symbols.impl.*
|
||||
import org.jetbrains.kotlin.fir.types.*
|
||||
import org.jetbrains.kotlin.lexer.KtModifierKeywordToken
|
||||
import org.jetbrains.kotlin.lexer.KtTokens
|
||||
@@ -49,6 +42,8 @@ import org.jetbrains.kotlin.types.AbstractTypeChecker
|
||||
import org.jetbrains.kotlin.types.Variance
|
||||
import org.jetbrains.kotlin.types.model.KotlinTypeMarker
|
||||
import org.jetbrains.kotlin.types.model.TypeCheckerProviderContext
|
||||
import org.jetbrains.kotlin.util.ImplementationStatus
|
||||
import org.jetbrains.kotlin.util.OperatorNameConventions
|
||||
import org.jetbrains.kotlin.utils.addToStdlib.safeAs
|
||||
|
||||
private val INLINE_ONLY_ANNOTATION_CLASS_ID = ClassId.topLevel(FqName("kotlin.internal.InlineOnly"))
|
||||
@@ -293,16 +288,6 @@ fun FirClass<*>.findNonInterfaceSupertype(context: CheckerContext): FirTypeRef?
|
||||
return null
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns KtModifierToken by Modality
|
||||
*/
|
||||
fun Modality.toToken(): KtModifierKeywordToken = when (this) {
|
||||
Modality.FINAL -> KtTokens.FINAL_KEYWORD
|
||||
Modality.SEALED -> KtTokens.SEALED_KEYWORD
|
||||
Modality.OPEN -> KtTokens.OPEN_KEYWORD
|
||||
Modality.ABSTRACT -> KtTokens.ABSTRACT_KEYWORD
|
||||
}
|
||||
|
||||
val FirFunctionCall.isIterator
|
||||
get() = this.calleeReference.name.asString() == "<iterator>"
|
||||
|
||||
@@ -397,15 +382,16 @@ private fun lowerThanBound(context: ConeInferenceContext, argument: ConeKotlinTy
|
||||
|
||||
fun FirMemberDeclaration.isInlineOnly(): Boolean = isInline && hasAnnotation(INLINE_ONLY_ANNOTATION_CLASS_ID)
|
||||
|
||||
val FirExpression.isComponentCall
|
||||
get() = this is FirComponentCall
|
||||
|
||||
fun isSubtypeForTypeMismatch(context: ConeInferenceContext, subtype: ConeKotlinType, supertype: ConeKotlinType): Boolean {
|
||||
return AbstractTypeChecker.isSubtypeOf(context, subtype, supertype)
|
||||
|| isSubtypeOfForFunctionalTypeReturningUnit(context.session.typeContext, subtype, supertype)
|
||||
}
|
||||
|
||||
fun isSubtypeOfForFunctionalTypeReturningUnit(context: ConeInferenceContext, subtype: ConeKotlinType, supertype: ConeKotlinType): Boolean {
|
||||
private fun isSubtypeOfForFunctionalTypeReturningUnit(
|
||||
context: ConeInferenceContext,
|
||||
subtype: ConeKotlinType,
|
||||
supertype: ConeKotlinType
|
||||
): Boolean {
|
||||
if (!supertype.isBuiltinFunctionalType(context.session)) return false
|
||||
val functionalTypeReturnType = supertype.typeArguments.lastOrNull()
|
||||
if ((functionalTypeReturnType as? ConeClassLikeType)?.isUnit == true) {
|
||||
@@ -428,3 +414,107 @@ fun isSubtypeOfForFunctionalTypeReturningUnit(context: ConeInferenceContext, sub
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
fun FirCallableMemberDeclaration<*>.isVisibleInClass(parentClass: FirClass<*>): Boolean {
|
||||
val classPackage = parentClass.symbol.classId.packageFqName
|
||||
if (visibility == Visibilities.Private ||
|
||||
!visibility.visibleFromPackage(classPackage, symbol.callableId.packageName)
|
||||
) return false
|
||||
if (visibility == Visibilities.Internal &&
|
||||
declarationSiteSession !== parentClass.declarationSiteSession
|
||||
) return false
|
||||
return true
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the [ImplementationStatus] for this member.
|
||||
*
|
||||
* @param parentClass the contextual class for this query.
|
||||
*/
|
||||
fun FirCallableMemberDeclaration<*>.getImplementationStatus(sessionHolder: SessionHolder, parentClass: FirClass<*>): ImplementationStatus {
|
||||
val containingClass = getContainingClass(sessionHolder)
|
||||
val symbol = this.symbol
|
||||
if (symbol is FirIntersectionCallableSymbol) {
|
||||
if (containingClass === parentClass && symbol.subjectToManyNotImplemented(sessionHolder)) {
|
||||
return ImplementationStatus.AMBIGUOUSLY_INHERITED
|
||||
}
|
||||
// In Java 8, non-abstract intersection overrides having abstract symbol from base class
|
||||
// still should be implemented in current class (even when they have default interface implementation)
|
||||
if (symbol.intersections.any {
|
||||
val fir = (it.fir as FirCallableMemberDeclaration).unwrapFakeOverrides()
|
||||
fir.isAbstract && (fir.getContainingClass(sessionHolder) as? FirRegularClass)?.classKind == ClassKind.CLASS
|
||||
}
|
||||
) {
|
||||
// Exception from the rule above: interface implementation via delegation
|
||||
if (symbol.intersections.none {
|
||||
val fir = (it.fir as FirCallableMemberDeclaration)
|
||||
fir.origin == FirDeclarationOrigin.Delegated && !fir.isAbstract
|
||||
}
|
||||
) {
|
||||
return ImplementationStatus.NOT_IMPLEMENTED
|
||||
}
|
||||
}
|
||||
}
|
||||
if (this is FirSimpleFunction) {
|
||||
if (parentClass is FirRegularClass && parentClass.isData && matchesDataClassSyntheticMemberSignatures) {
|
||||
return ImplementationStatus.INHERITED_OR_SYNTHESIZED
|
||||
}
|
||||
// TODO: suspend function overridden by a Java class in the middle is not properly regarded as an override
|
||||
if (isSuspend) {
|
||||
return ImplementationStatus.INHERITED_OR_SYNTHESIZED
|
||||
}
|
||||
}
|
||||
return when {
|
||||
isFinal -> ImplementationStatus.CANNOT_BE_IMPLEMENTED
|
||||
containingClass === parentClass && origin == FirDeclarationOrigin.Source -> ImplementationStatus.ALREADY_IMPLEMENTED
|
||||
containingClass is FirRegularClass && containingClass.isExpect -> ImplementationStatus.CANNOT_BE_IMPLEMENTED
|
||||
isAbstract -> ImplementationStatus.NOT_IMPLEMENTED
|
||||
else -> ImplementationStatus.INHERITED_OR_SYNTHESIZED
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private fun FirIntersectionCallableSymbol.subjectToManyNotImplemented(sessionHolder: SessionHolder): Boolean {
|
||||
var nonAbstractCountInClass = 0
|
||||
var nonAbstractCountInInterface = 0
|
||||
var abstractCountInInterface = 0
|
||||
for (intersectionSymbol in intersections) {
|
||||
val intersection = intersectionSymbol.fir as FirCallableMemberDeclaration
|
||||
val containingClass = intersection.getContainingClass(sessionHolder) as? FirRegularClass
|
||||
val hasInterfaceContainer = containingClass?.classKind == ClassKind.INTERFACE
|
||||
if (intersection.modality != Modality.ABSTRACT) {
|
||||
if (hasInterfaceContainer) {
|
||||
nonAbstractCountInInterface++
|
||||
} else {
|
||||
nonAbstractCountInClass++
|
||||
}
|
||||
} else if (hasInterfaceContainer) {
|
||||
abstractCountInInterface++
|
||||
}
|
||||
if (nonAbstractCountInClass + nonAbstractCountInInterface > 1) {
|
||||
return true
|
||||
}
|
||||
if (nonAbstractCountInInterface > 0 && abstractCountInInterface > 0) {
|
||||
return true
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
private val FirSimpleFunction.matchesDataClassSyntheticMemberSignatures: Boolean
|
||||
get() = (this.name == OperatorNameConventions.EQUALS && matchesEqualsSignature) ||
|
||||
(this.name == HASHCODE_NAME && matchesHashCodeSignature) ||
|
||||
(this.name == OperatorNameConventions.TO_STRING && matchesToStringSignature)
|
||||
|
||||
private fun FirSymbolOwner<*>.getContainingClass(sessionHolder: SessionHolder): FirClassLikeDeclaration<*>? =
|
||||
this.safeAs<FirCallableMemberDeclaration<*>>()?.containingClass()?.toSymbol(sessionHolder.session)?.fir
|
||||
|
||||
// NB: we intentionally do not check return types
|
||||
private val FirSimpleFunction.matchesEqualsSignature: Boolean
|
||||
get() = valueParameters.size == 1 && valueParameters[0].returnTypeRef.coneType.isNullableAny
|
||||
|
||||
private val FirSimpleFunction.matchesHashCodeSignature: Boolean
|
||||
get() = valueParameters.isEmpty()
|
||||
|
||||
private val FirSimpleFunction.matchesToStringSignature: Boolean
|
||||
get() = valueParameters.isEmpty()
|
||||
|
||||
@@ -5,6 +5,7 @@
|
||||
|
||||
package org.jetbrains.kotlin.fir.analysis.checkers.declaration
|
||||
|
||||
import org.jetbrains.kotlin.fir.FirElement
|
||||
import org.jetbrains.kotlin.fir.FirRealSourceElementKind
|
||||
import org.jetbrains.kotlin.fir.analysis.checkers.context.CheckerContext
|
||||
import org.jetbrains.kotlin.fir.analysis.checkers.isInline
|
||||
@@ -12,19 +13,24 @@ import org.jetbrains.kotlin.fir.analysis.diagnostics.DiagnosticReporter
|
||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors
|
||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.reportOnWithSuppression
|
||||
import org.jetbrains.kotlin.fir.declarations.FirFunction
|
||||
import org.jetbrains.kotlin.fir.declarations.FirValueParameter
|
||||
import org.jetbrains.kotlin.fir.diagnostics.ConeSimpleDiagnostic
|
||||
import org.jetbrains.kotlin.fir.diagnostics.DiagnosticKind
|
||||
import org.jetbrains.kotlin.fir.expressions.FirQualifiedAccessExpression
|
||||
import org.jetbrains.kotlin.fir.references.FirResolvedNamedReference
|
||||
import org.jetbrains.kotlin.fir.typeContext
|
||||
import org.jetbrains.kotlin.fir.types.FirErrorTypeRef
|
||||
import org.jetbrains.kotlin.fir.types.arrayElementType
|
||||
import org.jetbrains.kotlin.fir.types.coneType
|
||||
import org.jetbrains.kotlin.fir.types.isUnsignedTypeOrNullableUnsignedType
|
||||
import org.jetbrains.kotlin.fir.visitors.FirVisitorVoid
|
||||
import org.jetbrains.kotlin.types.AbstractTypeChecker
|
||||
|
||||
object FirFunctionParameterChecker : FirFunctionChecker() {
|
||||
override fun check(declaration: FirFunction<*>, context: CheckerContext, reporter: DiagnosticReporter) {
|
||||
checkVarargParameters(declaration, context, reporter)
|
||||
checkParameterTypes(declaration, context, reporter)
|
||||
checkUninitializedParameter(declaration, context, reporter)
|
||||
}
|
||||
|
||||
private fun checkParameterTypes(declaration: FirFunction<*>, context: CheckerContext, reporter: DiagnosticReporter) {
|
||||
@@ -70,4 +76,33 @@ object FirFunctionParameterChecker : FirFunctionChecker() {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun checkUninitializedParameter(function: FirFunction<*>, context: CheckerContext, reporter: DiagnosticReporter) {
|
||||
for ((index, parameter) in function.valueParameters.withIndex()) {
|
||||
// Alas, CheckerContext.qualifiedAccesses stack is not available at this point.
|
||||
// Thus, manually visit default value expression and report the diagnostic on qualified accesses of interest.
|
||||
parameter.defaultValue?.accept(object : FirVisitorVoid() {
|
||||
override fun visitElement(element: FirElement) {
|
||||
element.acceptChildren(this)
|
||||
}
|
||||
|
||||
override fun visitQualifiedAccessExpression(qualifiedAccessExpression: FirQualifiedAccessExpression) {
|
||||
val namedReference = qualifiedAccessExpression.calleeReference as? FirResolvedNamedReference ?: return
|
||||
val referredParameter = namedReference.resolvedSymbol.fir as? FirValueParameter ?: return
|
||||
val referredParameterIndex = function.valueParameters.indexOf(referredParameter)
|
||||
// Skip if the referred parameter is not declared in the same function.
|
||||
if (referredParameterIndex < 0) return
|
||||
|
||||
if (index <= referredParameterIndex) {
|
||||
reporter.reportOnWithSuppression(
|
||||
qualifiedAccessExpression,
|
||||
FirErrors.UNINITIALIZED_PARAMETER,
|
||||
referredParameter.symbol,
|
||||
context
|
||||
)
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -8,13 +8,13 @@ package org.jetbrains.kotlin.fir.analysis.checkers.declaration
|
||||
import org.jetbrains.kotlin.KtNodeTypes
|
||||
import org.jetbrains.kotlin.fir.FirRealSourceElementKind
|
||||
import org.jetbrains.kotlin.fir.analysis.checkers.context.CheckerContext
|
||||
import org.jetbrains.kotlin.fir.analysis.checkers.isComponentCall
|
||||
import org.jetbrains.kotlin.fir.analysis.checkers.isSubtypeForTypeMismatch
|
||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.DiagnosticReporter
|
||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors
|
||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.INITIALIZER_TYPE_MISMATCH
|
||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.reportOn
|
||||
import org.jetbrains.kotlin.fir.declarations.FirProperty
|
||||
import org.jetbrains.kotlin.fir.expressions.FirComponentCall
|
||||
import org.jetbrains.kotlin.fir.resolve.fullyExpandedType
|
||||
import org.jetbrains.kotlin.fir.typeContext
|
||||
import org.jetbrains.kotlin.fir.types.*
|
||||
@@ -25,7 +25,7 @@ object FirInitializerTypeMismatchChecker : FirPropertyChecker() {
|
||||
val initializer = declaration.initializer ?: return
|
||||
val source = declaration.source ?: return
|
||||
if (source.elementType == KtNodeTypes.DESTRUCTURING_DECLARATION) return
|
||||
if (initializer.isComponentCall) return
|
||||
if (initializer is FirComponentCall) return
|
||||
if (declaration.returnTypeRef.source?.kind != FirRealSourceElementKind) return
|
||||
val propertyType = declaration.returnTypeRef.coneType
|
||||
val expressionType = initializer.typeRef.coneTypeSafe<ConeKotlinType>() ?: return
|
||||
|
||||
@@ -8,12 +8,9 @@ package org.jetbrains.kotlin.fir.analysis.checkers.declaration
|
||||
import org.jetbrains.kotlin.config.LanguageFeature
|
||||
import org.jetbrains.kotlin.descriptors.ClassKind
|
||||
import org.jetbrains.kotlin.descriptors.Modality
|
||||
import org.jetbrains.kotlin.descriptors.Visibilities
|
||||
import org.jetbrains.kotlin.fir.*
|
||||
import org.jetbrains.kotlin.fir.FirFakeSourceElementKind
|
||||
import org.jetbrains.kotlin.fir.analysis.checkers.*
|
||||
import org.jetbrains.kotlin.fir.analysis.checkers.context.CheckerContext
|
||||
import org.jetbrains.kotlin.fir.analysis.checkers.getContainingClass
|
||||
import org.jetbrains.kotlin.fir.analysis.checkers.modality
|
||||
import org.jetbrains.kotlin.fir.analysis.checkers.unsubstitutedScope
|
||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.DiagnosticReporter
|
||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.ABSTRACT_CLASS_MEMBER_NOT_IMPLEMENTED
|
||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.ABSTRACT_MEMBER_NOT_IMPLEMENTED
|
||||
@@ -24,15 +21,14 @@ import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.MANY_IMPL_MEMBER_
|
||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.MANY_INTERFACES_MEMBER_NOT_IMPLEMENTED
|
||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.OVERRIDING_FINAL_MEMBER_BY_DELEGATION
|
||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.reportOn
|
||||
import org.jetbrains.kotlin.fir.containingClass
|
||||
import org.jetbrains.kotlin.fir.declarations.*
|
||||
import org.jetbrains.kotlin.fir.languageVersionSettings
|
||||
import org.jetbrains.kotlin.fir.resolve.toSymbol
|
||||
import org.jetbrains.kotlin.fir.symbols.impl.FirCallableSymbol
|
||||
import org.jetbrains.kotlin.fir.symbols.impl.FirIntersectionCallableSymbol
|
||||
import org.jetbrains.kotlin.fir.symbols.impl.FirIntersectionOverrideFunctionSymbol
|
||||
import org.jetbrains.kotlin.fir.symbols.impl.FirIntersectionOverridePropertySymbol
|
||||
import org.jetbrains.kotlin.fir.types.coneType
|
||||
import org.jetbrains.kotlin.fir.types.isNullableAny
|
||||
import org.jetbrains.kotlin.util.OperatorNameConventions
|
||||
import org.jetbrains.kotlin.fir.unwrapFakeOverrides
|
||||
import org.jetbrains.kotlin.util.ImplementationStatus
|
||||
|
||||
object FirNotImplementedOverrideChecker : FirClassChecker() {
|
||||
|
||||
@@ -51,115 +47,24 @@ object FirNotImplementedOverrideChecker : FirClassChecker() {
|
||||
val notImplementedSymbols = mutableListOf<FirCallableSymbol<*>>()
|
||||
val notImplementedIntersectionSymbols = mutableListOf<FirCallableSymbol<*>>()
|
||||
val invisibleSymbols = mutableListOf<FirCallableSymbol<*>>()
|
||||
val classPackage = declaration.symbol.classId.packageFqName
|
||||
|
||||
fun FirCallableMemberDeclaration<*>.isInvisible(): Boolean {
|
||||
if (visibility == Visibilities.Private ||
|
||||
!visibility.visibleFromPackage(classPackage, symbol.callableId.packageName)
|
||||
) return true
|
||||
if (visibility == Visibilities.Internal &&
|
||||
declarationSiteSession !== declaration.declarationSiteSession
|
||||
) return true
|
||||
return false
|
||||
}
|
||||
|
||||
fun FirIntersectionCallableSymbol.subjectToManyNotImplemented(): Boolean {
|
||||
var nonAbstractCountInClass = 0
|
||||
var nonAbstractCountInInterface = 0
|
||||
var abstractCountInInterface = 0
|
||||
for (intersectionSymbol in intersections) {
|
||||
val intersection = intersectionSymbol.fir as FirCallableMemberDeclaration
|
||||
val containingClass = intersection.getContainingClass(context) as? FirRegularClass
|
||||
val hasInterfaceContainer = containingClass?.classKind == ClassKind.INTERFACE
|
||||
if (intersection.modality != Modality.ABSTRACT) {
|
||||
if (hasInterfaceContainer) {
|
||||
nonAbstractCountInInterface++
|
||||
} else {
|
||||
nonAbstractCountInClass++
|
||||
}
|
||||
} else if (hasInterfaceContainer) {
|
||||
abstractCountInInterface++
|
||||
fun collectSymbol(symbol: FirCallableSymbol<*>) {
|
||||
val fir = symbol.fir as? FirCallableMemberDeclaration<*> ?: return
|
||||
when (fir.getImplementationStatus(context.sessionHolder, declaration)) {
|
||||
ImplementationStatus.AMBIGUOUSLY_INHERITED -> notImplementedIntersectionSymbols.add(symbol)
|
||||
ImplementationStatus.NOT_IMPLEMENTED -> when {
|
||||
fir.isVisibleInClass(declaration) -> notImplementedSymbols.add(symbol)
|
||||
else -> invisibleSymbols.add(symbol)
|
||||
}
|
||||
if (nonAbstractCountInClass + nonAbstractCountInInterface > 1) {
|
||||
return true
|
||||
}
|
||||
if (nonAbstractCountInInterface > 0 && abstractCountInInterface > 0) {
|
||||
return true
|
||||
else -> {
|
||||
// nothing to do
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
fun FirIntersectionCallableSymbol.shouldBeImplemented(): Boolean {
|
||||
// In Java 8, non-abstract intersection overrides having abstract symbol from base class
|
||||
// still should be implemented in current class (even when they have default interface implementation)
|
||||
if (intersections.none {
|
||||
val fir = (it.fir as FirCallableMemberDeclaration).unwrapFakeOverrides()
|
||||
fir.isAbstract && (fir.getContainingClass(context) as? FirRegularClass)?.classKind == ClassKind.CLASS
|
||||
}
|
||||
) return false
|
||||
// Exception from the rule above: interface implementation via delegation
|
||||
if (intersections.any {
|
||||
val fir = (it.fir as FirCallableMemberDeclaration)
|
||||
fir.origin == FirDeclarationOrigin.Delegated && !fir.isAbstract
|
||||
}
|
||||
) return false
|
||||
return true
|
||||
}
|
||||
|
||||
fun FirCallableMemberDeclaration<*>.shouldBeImplemented(): Boolean {
|
||||
val containingClass = getContainingClass(context)
|
||||
if (containingClass is FirRegularClass && containingClass.isExpect) return false
|
||||
if (!isAbstract) {
|
||||
val symbol = symbol as? FirIntersectionCallableSymbol ?: return false
|
||||
return symbol.shouldBeImplemented()
|
||||
}
|
||||
if (containingClass === declaration && origin == FirDeclarationOrigin.Source) return false
|
||||
return true
|
||||
}
|
||||
|
||||
for (name in classScope.getCallableNames()) {
|
||||
classScope.processFunctionsByName(name) { namedFunctionSymbol ->
|
||||
val simpleFunction = namedFunctionSymbol.fir
|
||||
if (namedFunctionSymbol is FirIntersectionOverrideFunctionSymbol) {
|
||||
if (simpleFunction.getContainingClass(context) === declaration &&
|
||||
namedFunctionSymbol.subjectToManyNotImplemented()
|
||||
) {
|
||||
notImplementedIntersectionSymbols += namedFunctionSymbol
|
||||
return@processFunctionsByName
|
||||
}
|
||||
}
|
||||
if (!simpleFunction.shouldBeImplemented()) return@processFunctionsByName
|
||||
if (declaration is FirRegularClass && declaration.isData && simpleFunction.matchesDataClassSyntheticMemberSignatures) {
|
||||
return@processFunctionsByName
|
||||
}
|
||||
|
||||
// TODO: suspend function overridden by a Java class in the middle is not properly regarded as an override
|
||||
if (simpleFunction.isSuspend) return@processFunctionsByName
|
||||
if (simpleFunction.isInvisible()) {
|
||||
invisibleSymbols += namedFunctionSymbol
|
||||
} else {
|
||||
notImplementedSymbols += namedFunctionSymbol
|
||||
}
|
||||
}
|
||||
classScope.processPropertiesByName(name) { propertySymbol ->
|
||||
val property = propertySymbol.fir as? FirProperty ?: return@processPropertiesByName
|
||||
if (propertySymbol is FirIntersectionOverridePropertySymbol) {
|
||||
if (property.getContainingClass(context) === declaration &&
|
||||
propertySymbol.subjectToManyNotImplemented()
|
||||
) {
|
||||
notImplementedIntersectionSymbols += propertySymbol
|
||||
return@processPropertiesByName
|
||||
}
|
||||
}
|
||||
if (!property.shouldBeImplemented()) return@processPropertiesByName
|
||||
|
||||
if (property.isInvisible()) {
|
||||
invisibleSymbols += propertySymbol
|
||||
} else {
|
||||
notImplementedSymbols += propertySymbol
|
||||
}
|
||||
}
|
||||
classScope.processFunctionsByName(name, ::collectSymbol)
|
||||
classScope.processPropertiesByName(name, ::collectSymbol)
|
||||
}
|
||||
|
||||
if (notImplementedSymbols.isNotEmpty()) {
|
||||
@@ -237,19 +142,4 @@ object FirNotImplementedOverrideChecker : FirClassChecker() {
|
||||
|
||||
private fun FirCallableDeclaration<*>.isFromInterfaceOrEnum(context: CheckerContext): Boolean =
|
||||
(getContainingClass(context) as? FirRegularClass)?.let { it.isInterface || it.isEnumClass } == true
|
||||
|
||||
private val FirSimpleFunction.matchesDataClassSyntheticMemberSignatures: Boolean
|
||||
get() = (this.name == OperatorNameConventions.EQUALS && matchesEqualsSignature) ||
|
||||
(this.name == HASHCODE_NAME && matchesHashCodeSignature) ||
|
||||
(this.name == OperatorNameConventions.TO_STRING && matchesToStringSignature)
|
||||
|
||||
// NB: we intentionally do not check return types
|
||||
private val FirSimpleFunction.matchesEqualsSignature: Boolean
|
||||
get() = valueParameters.size == 1 && valueParameters[0].returnTypeRef.coneType.isNullableAny
|
||||
|
||||
private val FirSimpleFunction.matchesHashCodeSignature: Boolean
|
||||
get() = valueParameters.isEmpty()
|
||||
|
||||
private val FirSimpleFunction.matchesToStringSignature: Boolean
|
||||
get() = valueParameters.isEmpty()
|
||||
}
|
||||
|
||||
@@ -17,6 +17,8 @@ import org.jetbrains.kotlin.fir.resolve.inference.inferenceComponents
|
||||
import org.jetbrains.kotlin.fir.resolve.toFirRegularClass
|
||||
import org.jetbrains.kotlin.fir.types.*
|
||||
import org.jetbrains.kotlin.fir.analysis.checkers.ConeTypeCompatibilityChecker.areCompatible
|
||||
import org.jetbrains.kotlin.fir.declarations.FirFile
|
||||
import org.jetbrains.kotlin.fir.render
|
||||
|
||||
object FirEqualityCompatibilityChecker : FirEqualityOperatorCallChecker() {
|
||||
override fun check(expression: FirEqualityOperatorCall, context: CheckerContext, reporter: DiagnosticReporter) {
|
||||
@@ -30,7 +32,16 @@ object FirEqualityCompatibilityChecker : FirEqualityOperatorCallChecker() {
|
||||
val inferenceContext = context.session.inferenceComponents.ctx
|
||||
val intersectionType = inferenceContext.intersectTypesOrNull(listOf(lType, rType)) as? ConeIntersectionType ?: return
|
||||
|
||||
val compatibility = intersectionType.intersectedTypes.areCompatible(inferenceContext)
|
||||
val compatibility = try {
|
||||
intersectionType.intersectedTypes.areCompatible(inferenceContext)
|
||||
} catch (e: Throwable) {
|
||||
throw IllegalStateException(
|
||||
"Exception while determining type compatibility: type ${intersectionType.render()}, " +
|
||||
"equality ${expression.render()}, " +
|
||||
"file ${context.containingDeclarations.filterIsInstance<FirFile>().firstOrNull()?.name}",
|
||||
e
|
||||
)
|
||||
}
|
||||
if (compatibility != ConeTypeCompatibilityChecker.Compatibility.COMPATIBLE) {
|
||||
when (expression.source?.kind) {
|
||||
FirRealSourceElementKind -> {
|
||||
@@ -271,6 +271,7 @@ import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.TYPE_PARAMETER_ON
|
||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.UNEXPECTED_SAFE_CALL
|
||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.UNINITIALIZED_ENUM_COMPANION
|
||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.UNINITIALIZED_ENUM_ENTRY
|
||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.UNINITIALIZED_PARAMETER
|
||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.UNINITIALIZED_VARIABLE
|
||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.UNNECESSARY_LATEINIT
|
||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.UNNECESSARY_NOT_NULL_ASSERTION
|
||||
@@ -830,7 +831,8 @@ class FirDefaultErrorMessages : DefaultErrorMessages.Extension {
|
||||
)
|
||||
|
||||
// Control flow diagnostics
|
||||
map.put(UNINITIALIZED_VARIABLE, "{0} must be initialized before access", VARIABLE_NAME)
|
||||
map.put(UNINITIALIZED_VARIABLE, "Variable ''{0}'' must be initialized", VARIABLE_NAME)
|
||||
map.put(UNINITIALIZED_PARAMETER, "Parameter ''{0}'' is uninitialized here", VARIABLE_NAME)
|
||||
map.put(UNINITIALIZED_ENUM_ENTRY, "Enum entry ''{0}'' is uninitialized here", VARIABLE_NAME)
|
||||
map.put(UNINITIALIZED_ENUM_COMPANION, "Companion object of enum class ''{0}'' is uninitialized here", SYMBOL)
|
||||
map.put(VAL_REASSIGNMENT, "Val cannot be reassigned", VARIABLE_NAME)
|
||||
|
||||
@@ -59,6 +59,7 @@ if (kotlinBuildProperties.isInJpsBuildIdeaSync) {
|
||||
}
|
||||
|
||||
projectTest(jUnit5Enabled = true) {
|
||||
dependsOn(":dist")
|
||||
workingDir = rootDir
|
||||
useJUnitPlatform()
|
||||
}
|
||||
|
||||
@@ -95,21 +95,20 @@ class Fir2IrConversionScope {
|
||||
}
|
||||
|
||||
fun returnTarget(expression: FirReturnExpression, declarationStorage: Fir2IrDeclarationStorage): IrFunction {
|
||||
val firTarget = expression.target.labeledElement
|
||||
val irTarget = (firTarget as? FirFunction)?.let {
|
||||
when (it) {
|
||||
is FirConstructor -> declarationStorage.getCachedIrConstructor(it)
|
||||
is FirPropertyAccessor -> {
|
||||
for ((property, firProperty) in propertyStack.asReversed()) {
|
||||
if (firProperty?.getter === firTarget) {
|
||||
return@let property.getter
|
||||
} else if (firProperty?.setter === firTarget) {
|
||||
return@let property.setter
|
||||
}
|
||||
val irTarget = when (val firTarget = expression.target.labeledElement) {
|
||||
is FirConstructor -> declarationStorage.getCachedIrConstructor(firTarget)
|
||||
is FirPropertyAccessor -> {
|
||||
var answer: IrFunction? = null
|
||||
for ((property, firProperty) in propertyStack.asReversed()) {
|
||||
if (firProperty?.getter === firTarget) {
|
||||
answer = property.getter
|
||||
} else if (firProperty?.setter === firTarget) {
|
||||
answer = property.setter
|
||||
}
|
||||
}
|
||||
else -> declarationStorage.getCachedIrFunction(it)
|
||||
answer
|
||||
}
|
||||
else -> declarationStorage.getCachedIrFunction(firTarget)
|
||||
}
|
||||
for (potentialTarget in functionStack.asReversed()) {
|
||||
if (potentialTarget == irTarget) {
|
||||
|
||||
@@ -277,6 +277,14 @@ class Fir2IrImplicitCastInserter(
|
||||
return implicitCastOrExpression(data as IrExpression, expressionWithSmartcast.typeRef)
|
||||
}
|
||||
|
||||
override fun visitExpressionWithSmartcastToNull(
|
||||
expressionWithSmartcastToNull: FirExpressionWithSmartcastToNull,
|
||||
data: IrElement
|
||||
): IrElement {
|
||||
// We don't want an implicit cast to Nothing?. This expression just encompasses nullability after null check.
|
||||
return data
|
||||
}
|
||||
|
||||
internal fun implicitCastFromDispatchReceiver(
|
||||
original: IrExpression,
|
||||
originalTypeRef: FirTypeRef,
|
||||
|
||||
@@ -420,6 +420,14 @@ class Fir2IrVisitor(
|
||||
return implicitCastInserter.visitExpressionWithSmartcast(expressionWithSmartcast, value)
|
||||
}
|
||||
|
||||
override fun visitExpressionWithSmartcastToNull(
|
||||
expressionWithSmartcastToNull: FirExpressionWithSmartcastToNull,
|
||||
data: Any?
|
||||
): IrElement {
|
||||
// This should not be materialized. Generate the expression with the original expression.
|
||||
return convertToIrExpression(expressionWithSmartcastToNull.originalExpression)
|
||||
}
|
||||
|
||||
override fun visitCallableReferenceAccess(callableReferenceAccess: FirCallableReferenceAccess, data: Any?): IrElement {
|
||||
val explicitReceiverExpression = convertToIrReceiverExpression(
|
||||
callableReferenceAccess.explicitReceiver, callableReferenceAccess.calleeReference, callableReferenceAccess
|
||||
|
||||
@@ -429,6 +429,24 @@ public class FirBlackBoxCodegenTestGenerated extends AbstractFirBlackBoxCodegenT
|
||||
runTest("compiler/testData/codegen/box/annotations/typeAnnotations/checkingNotincorporatedInputTypes.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("classTypeParameterBound.kt")
|
||||
public void testClassTypeParameterBound() throws Exception {
|
||||
runTest("compiler/testData/codegen/box/annotations/typeAnnotations/classTypeParameterBound.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("classTypeParameterBoundsJava.kt")
|
||||
public void testClassTypeParameterBoundsJava() throws Exception {
|
||||
runTest("compiler/testData/codegen/box/annotations/typeAnnotations/classTypeParameterBoundsJava.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("functionTypeParameterBound.kt")
|
||||
public void testFunctionTypeParameterBound() throws Exception {
|
||||
runTest("compiler/testData/codegen/box/annotations/typeAnnotations/functionTypeParameterBound.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("implicitReturn.kt")
|
||||
public void testImplicitReturn() throws Exception {
|
||||
@@ -453,6 +471,12 @@ public class FirBlackBoxCodegenTestGenerated extends AbstractFirBlackBoxCodegenT
|
||||
runTest("compiler/testData/codegen/box/annotations/typeAnnotations/methodParameters.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("methodTypeParameters.kt")
|
||||
public void testMethodTypeParameters() throws Exception {
|
||||
runTest("compiler/testData/codegen/box/annotations/typeAnnotations/methodTypeParameters.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("typeAnnotationTarget6.kt")
|
||||
public void testTypeAnnotationTarget6() throws Exception {
|
||||
@@ -9060,6 +9084,12 @@ public class FirBlackBoxCodegenTestGenerated extends AbstractFirBlackBoxCodegenT
|
||||
runTest("compiler/testData/codegen/box/coroutines/iterateOverArray.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("jvmStaticAndJvmInline.kt")
|
||||
public void testJvmStaticAndJvmInline() throws Exception {
|
||||
runTest("compiler/testData/codegen/box/coroutines/jvmStaticAndJvmInline.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("kt12958.kt")
|
||||
public void testKt12958() throws Exception {
|
||||
@@ -15686,6 +15716,12 @@ public class FirBlackBoxCodegenTestGenerated extends AbstractFirBlackBoxCodegenT
|
||||
runTest("compiler/testData/codegen/box/funInterface/kt45444_privateFunInterface.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("kt46512_indyFunInterfaceOverCallableReference.kt")
|
||||
public void testKt46512_indyFunInterfaceOverCallableReference() throws Exception {
|
||||
runTest("compiler/testData/codegen/box/funInterface/kt46512_indyFunInterfaceOverCallableReference.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("multimodule.kt")
|
||||
public void testMultimodule() throws Exception {
|
||||
@@ -18970,6 +19006,12 @@ public class FirBlackBoxCodegenTestGenerated extends AbstractFirBlackBoxCodegenT
|
||||
runTest("compiler/testData/codegen/box/inlineClasses/callableReferences/let/intN.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("null.kt")
|
||||
public void testNull() throws Exception {
|
||||
runTest("compiler/testData/codegen/box/inlineClasses/callableReferences/let/null.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("result.kt")
|
||||
public void testResult() throws Exception {
|
||||
@@ -19914,6 +19956,12 @@ public class FirBlackBoxCodegenTestGenerated extends AbstractFirBlackBoxCodegenT
|
||||
runTest("compiler/testData/codegen/box/inlineClasses/unboxGenericParameter/funInterface/ifaceChild.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("nullableResult.kt")
|
||||
public void testNullableResult() throws Exception {
|
||||
runTest("compiler/testData/codegen/box/inlineClasses/unboxGenericParameter/funInterface/nullableResult.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("primitive.kt")
|
||||
public void testPrimitive() throws Exception {
|
||||
@@ -19972,6 +20020,12 @@ public class FirBlackBoxCodegenTestGenerated extends AbstractFirBlackBoxCodegenT
|
||||
runTest("compiler/testData/codegen/box/inlineClasses/unboxGenericParameter/lambda/ifaceChild.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("nullableResult.kt")
|
||||
public void testNullableResult() throws Exception {
|
||||
runTest("compiler/testData/codegen/box/inlineClasses/unboxGenericParameter/lambda/nullableResult.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("primitive.kt")
|
||||
public void testPrimitive() throws Exception {
|
||||
@@ -20030,6 +20084,12 @@ public class FirBlackBoxCodegenTestGenerated extends AbstractFirBlackBoxCodegenT
|
||||
runTest("compiler/testData/codegen/box/inlineClasses/unboxGenericParameter/objectLiteral/ifaceChild.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("nullableResult.kt")
|
||||
public void testNullableResult() throws Exception {
|
||||
runTest("compiler/testData/codegen/box/inlineClasses/unboxGenericParameter/objectLiteral/nullableResult.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("primitive.kt")
|
||||
public void testPrimitive() throws Exception {
|
||||
@@ -20901,6 +20961,18 @@ public class FirBlackBoxCodegenTestGenerated extends AbstractFirBlackBoxCodegenT
|
||||
runTest("compiler/testData/codegen/box/invokedynamic/sam/samExtFunWithCapturingLambda.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("serializableSam1.kt")
|
||||
public void testSerializableSam1() throws Exception {
|
||||
runTest("compiler/testData/codegen/box/invokedynamic/sam/serializableSam1.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("serializableSam2.kt")
|
||||
public void testSerializableSam2() throws Exception {
|
||||
runTest("compiler/testData/codegen/box/invokedynamic/sam/serializableSam2.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("simpleFunInterfaceConstructor.kt")
|
||||
public void testSimpleFunInterfaceConstructor() throws Exception {
|
||||
@@ -24166,6 +24238,12 @@ public class FirBlackBoxCodegenTestGenerated extends AbstractFirBlackBoxCodegenT
|
||||
runTest("compiler/testData/codegen/box/jvmStatic/kt45408.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("kt46568.kt")
|
||||
public void testKt46568() throws Exception {
|
||||
runTest("compiler/testData/codegen/box/jvmStatic/kt46568.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("kt9897_static.kt")
|
||||
public void testKt9897_static() throws Exception {
|
||||
|
||||
@@ -3512,6 +3512,12 @@ public class FirBytecodeTextTestGenerated extends AbstractFirBytecodeTextTest {
|
||||
runTest("compiler/testData/codegen/bytecodeText/inlineClasses/generationOfAccessorToUnderlyingValue.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("genericNoUnbox.kt")
|
||||
public void testGenericNoUnbox() throws Exception {
|
||||
runTest("compiler/testData/codegen/bytecodeText/inlineClasses/genericNoUnbox.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("hashCodeIsCalledByInlineClass.kt")
|
||||
public void testHashCodeIsCalledByInlineClass() throws Exception {
|
||||
|
||||
@@ -1574,7 +1574,7 @@ class DeclarationsConverter(
|
||||
val delegateName = Name.special("<\$\$delegate_${delegateFields.size}>")
|
||||
delegateFields.add(
|
||||
buildField {
|
||||
source = firExpression!!.source
|
||||
source = firExpression!!.source?.fakeElement(FirFakeSourceElementKind.ClassDelegationField)
|
||||
declarationSiteSession = baseSession
|
||||
origin = FirDeclarationOrigin.Synthetic
|
||||
name = delegateName
|
||||
|
||||
@@ -566,7 +566,8 @@ open class RawFirBuilder(
|
||||
val delegateExpression = { superTypeListEntry.delegateExpression }.toFirExpression("Should have delegate")
|
||||
container.superTypeRefs += type
|
||||
val delegateName = Name.special("<\$\$delegate_${delegateFields.size}>")
|
||||
val delegateSource = superTypeListEntry.delegateExpression?.toFirSourceElement()
|
||||
val delegateSource =
|
||||
superTypeListEntry.delegateExpression?.toFirSourceElement(FirFakeSourceElementKind.ClassDelegationField)
|
||||
val delegateField = buildField {
|
||||
source = delegateSource
|
||||
declarationSiteSession = baseSession
|
||||
|
||||
@@ -185,9 +185,12 @@ class FirTowerDataContextsForClassParts(
|
||||
modeMap[mode] = value
|
||||
}
|
||||
|
||||
fun setAnonymousFunctionContext(symbol: FirAnonymousFunctionSymbol) {
|
||||
mode = SPECIAL
|
||||
modeMap[SPECIAL] = towerDataContextForAnonymousFunctions.getValue(symbol)
|
||||
fun setAnonymousFunctionContextIfAny(symbol: FirAnonymousFunctionSymbol) {
|
||||
val context = towerDataContextForAnonymousFunctions[symbol]
|
||||
if (context != null) {
|
||||
mode = SPECIAL
|
||||
modeMap[SPECIAL] = context
|
||||
}
|
||||
}
|
||||
|
||||
fun setCallableReferenceContextIfAny(access: FirCallableReferenceAccess) {
|
||||
|
||||
@@ -247,9 +247,35 @@ private fun BodyResolveComponents.typeFromSymbol(symbol: AbstractFirBasedSymbol<
|
||||
}
|
||||
}
|
||||
|
||||
fun BodyResolveComponents.transformQualifiedAccessUsingSmartcastInfo(qualifiedAccessExpression: FirQualifiedAccessExpression): FirQualifiedAccessExpression {
|
||||
fun BodyResolveComponents.transformQualifiedAccessUsingSmartcastInfo(
|
||||
qualifiedAccessExpression: FirQualifiedAccessExpression
|
||||
): FirQualifiedAccessExpression {
|
||||
val typesFromSmartCast = dataFlowAnalyzer.getTypeUsingSmartcastInfo(qualifiedAccessExpression) ?: return qualifiedAccessExpression
|
||||
val originalType = qualifiedAccessExpression.resultType.coneType
|
||||
// For example, if (x == null) { ... },
|
||||
// we don't want to smartcast to Nothing?, but we want to record the nullability to its own kind of node.
|
||||
// TODO: should we differentiate x == null v.s. x is Nothing?
|
||||
if (typesFromSmartCast.any { it.isNullableNothing }) {
|
||||
val typesFromSmartcastWithoutNullableNothing =
|
||||
typesFromSmartCast.filterTo(mutableListOf()) { !it.isNullableNothing }.also {
|
||||
it += originalType
|
||||
}
|
||||
val intersectedTypeWithoutNullableNothing =
|
||||
ConeTypeIntersector.intersectTypes(session.inferenceComponents.ctx, typesFromSmartcastWithoutNullableNothing)
|
||||
val intersectedTypeRefWithoutNullableNothing = buildResolvedTypeRef {
|
||||
source = qualifiedAccessExpression.resultType.source?.fakeElement(FirFakeSourceElementKind.SmartCastedTypeRef)
|
||||
type = intersectedTypeWithoutNullableNothing
|
||||
annotations += qualifiedAccessExpression.resultType.annotations
|
||||
delegatedTypeRef = qualifiedAccessExpression.resultType
|
||||
}
|
||||
return buildExpressionWithSmartcastToNull {
|
||||
originalExpression = qualifiedAccessExpression
|
||||
// TODO: Use Nothing? during resolution?
|
||||
typeRef = intersectedTypeRefWithoutNullableNothing
|
||||
// NB: Nothing? in types from smartcast in DFA is recorded here (and the expression kind itself).
|
||||
this.typesFromSmartCast = typesFromSmartCast
|
||||
}
|
||||
}
|
||||
val allTypes = typesFromSmartCast.also {
|
||||
it += originalType
|
||||
}
|
||||
@@ -259,6 +285,7 @@ fun BodyResolveComponents.transformQualifiedAccessUsingSmartcastInfo(qualifiedAc
|
||||
source = qualifiedAccessExpression.resultType.source?.fakeElement(FirFakeSourceElementKind.SmartCastedTypeRef)
|
||||
type = intersectedType
|
||||
annotations += qualifiedAccessExpression.resultType.annotations
|
||||
delegatedTypeRef = qualifiedAccessExpression.resultType
|
||||
}
|
||||
return buildExpressionWithSmartcast {
|
||||
originalExpression = qualifiedAccessExpression
|
||||
|
||||
@@ -119,9 +119,11 @@ abstract class FirDataFlowAnalyzer<FLOW : Flow>(
|
||||
}
|
||||
|
||||
override fun ConeKotlinType.isAcceptableForSmartcast(): Boolean {
|
||||
if (this.isNullableNothing) return false
|
||||
return when (this) {
|
||||
is ConeClassLikeType -> {
|
||||
val symbol = fullyExpandedType(components.session).lookupTag.toSymbol(components.session) ?: return false
|
||||
val symbol =
|
||||
fullyExpandedType(components.session).lookupTag.toSymbol(components.session) ?: return false
|
||||
val declaration = symbol.fir as? FirRegularClass ?: return true
|
||||
visibilityChecker.isVisible(
|
||||
declaration,
|
||||
@@ -149,7 +151,7 @@ abstract class FirDataFlowAnalyzer<FLOW : Flow>(
|
||||
|
||||
private var contractDescriptionVisitingMode = false
|
||||
|
||||
protected val any = components.session.builtinTypes.anyType.type
|
||||
private val any = components.session.builtinTypes.anyType.type
|
||||
private val nullableNothing = components.session.builtinTypes.nullableNothingType.type
|
||||
|
||||
@PrivateForInline
|
||||
@@ -472,11 +474,18 @@ abstract class FirDataFlowAnalyzer<FLOW : Flow>(
|
||||
) {
|
||||
val leftIsNullable = leftOperand.coneType.isMarkedNullable
|
||||
val rightIsNullable = rightOperand.coneType.isMarkedNullable
|
||||
|
||||
// left == right && right not null -> left != null
|
||||
// [processEqNull] adds both implications: operator call could be true or false. We definitely need the matched case only.
|
||||
fun shouldAddImplicationForStatement(operationStatement: OperationStatement): Boolean {
|
||||
// Only if operation statement is == True, i.e., left == right
|
||||
return (operation.isEq() && operationStatement.operation == Operation.EqTrue) ||
|
||||
(!operation.isEq() && operationStatement.operation == Operation.EqFalse)
|
||||
}
|
||||
when {
|
||||
leftIsNullable && rightIsNullable -> return
|
||||
leftIsNullable -> processEqNull(node, leftOperand, operation.invert())
|
||||
rightIsNullable -> processEqNull(node, rightOperand, operation.invert())
|
||||
leftIsNullable -> processEqNull(node, leftOperand, operation.invert(), ::shouldAddImplicationForStatement)
|
||||
rightIsNullable -> processEqNull(node, rightOperand, operation.invert(), ::shouldAddImplicationForStatement)
|
||||
}
|
||||
|
||||
if (operation == FirOperation.IDENTITY || operation == FirOperation.NOT_IDENTITY) {
|
||||
@@ -484,7 +493,25 @@ abstract class FirDataFlowAnalyzer<FLOW : Flow>(
|
||||
}
|
||||
}
|
||||
|
||||
private fun processEqNull(node: EqualityOperatorCallNode, operand: FirExpression, operation: FirOperation) {
|
||||
/*
|
||||
* Process x == null in general: add implications for both cases.
|
||||
* E.g., say d1 is an eq operator call node, d2 represents `x`, the variable inside the operator call. So, d1: x == null
|
||||
* This util adds: "d1 == True -> d2 == null" and "d1 == False -> d2 != null"
|
||||
* so that both branches after the operator call can infer the type of x.
|
||||
*
|
||||
* However, users can specify what conditions are of interest.
|
||||
* E.g., say left == right _and_ right != null, then we can conclude left != null.
|
||||
* In this example, say d1 is an eq operator call (left == right), and d2 is left.
|
||||
* Unlike general cases, we want to add: "d1 == True -> d2 != null", and nothing more because the counter part,
|
||||
* "d1 == False -> d2 == null" doesn't hold. That is, left != right and right != null don't mean left == null. It just means, left is
|
||||
* something different from right, including null. By filtering "d1 == True" condition only, all the remaining logic can be shared.
|
||||
*/
|
||||
private fun processEqNull(
|
||||
node: EqualityOperatorCallNode,
|
||||
operand: FirExpression,
|
||||
operation: FirOperation,
|
||||
shouldAddImplicationForStatement: (OperationStatement) -> Boolean = { true }
|
||||
) {
|
||||
val flow = node.flow
|
||||
val expressionVariable = variableStorage.createSyntheticVariable(node.fir)
|
||||
val operandVariable = variableStorage.getOrCreateVariable(node.previousFlow, operand)
|
||||
@@ -497,20 +524,35 @@ abstract class FirDataFlowAnalyzer<FLOW : Flow>(
|
||||
}
|
||||
|
||||
logicSystem.approveOperationStatement(flow, predicate).forEach { effect ->
|
||||
flow.addImplication((expressionVariable eq true) implies effect)
|
||||
flow.addImplication((expressionVariable eq false) implies effect.invert())
|
||||
if (shouldAddImplicationForStatement(expressionVariable eq true)) {
|
||||
flow.addImplication((expressionVariable eq true) implies effect)
|
||||
}
|
||||
if (shouldAddImplicationForStatement(expressionVariable eq false)) {
|
||||
flow.addImplication((expressionVariable eq false) implies effect.invert())
|
||||
}
|
||||
}
|
||||
|
||||
flow.addImplication((expressionVariable eq isEq) implies (operandVariable eq null))
|
||||
flow.addImplication((expressionVariable notEq isEq) implies (operandVariable notEq null))
|
||||
if (shouldAddImplicationForStatement(expressionVariable eq isEq)) {
|
||||
flow.addImplication((expressionVariable eq isEq) implies (operandVariable eq null))
|
||||
}
|
||||
if (shouldAddImplicationForStatement(expressionVariable notEq isEq)) {
|
||||
flow.addImplication((expressionVariable notEq isEq) implies (operandVariable notEq null))
|
||||
}
|
||||
|
||||
if (operandVariable is RealVariable) {
|
||||
flow.addImplication((expressionVariable eq isEq) implies (operandVariable typeNotEq any))
|
||||
flow.addImplication((expressionVariable notEq isEq) implies (operandVariable typeEq any))
|
||||
if (operandVariable.isReal()) {
|
||||
if (shouldAddImplicationForStatement(expressionVariable eq isEq)) {
|
||||
flow.addImplication((expressionVariable eq isEq) implies (operandVariable typeNotEq any))
|
||||
}
|
||||
if (shouldAddImplicationForStatement(expressionVariable notEq isEq)) {
|
||||
flow.addImplication((expressionVariable notEq isEq) implies (operandVariable typeEq any))
|
||||
}
|
||||
|
||||
// TODO: design do we need casts to Nothing?
|
||||
// flow.addImplication((expressionVariable eq !isEq) implies (operandVariable typeEq nullableNothing))
|
||||
// flow.addImplication((expressionVariable notEq !isEq) implies (operandVariable typeNotEq nullableNothing))
|
||||
if (shouldAddImplicationForStatement(expressionVariable eq !isEq)) {
|
||||
flow.addImplication((expressionVariable eq !isEq) implies (operandVariable typeNotEq nullableNothing))
|
||||
}
|
||||
if (shouldAddImplicationForStatement(expressionVariable notEq !isEq)) {
|
||||
flow.addImplication((expressionVariable notEq !isEq) implies (operandVariable typeEq nullableNothing))
|
||||
}
|
||||
}
|
||||
node.flow = flow
|
||||
}
|
||||
|
||||
@@ -42,7 +42,6 @@ class PersistentFlow : Flow {
|
||||
var logicStatements: PersistentImplications
|
||||
val level: Int
|
||||
var approvedTypeStatementsDiff: PersistentApprovedTypeStatements = persistentHashMapOf()
|
||||
var updatedAliasDiff: PersistentSet<RealVariable> = persistentSetOf()
|
||||
|
||||
/*
|
||||
* val x = a
|
||||
@@ -204,7 +203,6 @@ abstract class PersistentLogicSystem(context: ConeInferenceContext) : LogicSyste
|
||||
}
|
||||
|
||||
override fun removeLocalVariableAlias(flow: PersistentFlow, alias: RealVariable) {
|
||||
flow.updatedAliasDiff += alias
|
||||
val original = flow.directAliasMap[alias]?.variable ?: return
|
||||
flow.directAliasMap = flow.directAliasMap.remove(alias)
|
||||
val variables = flow.backwardsAliasMap.getValue(original)
|
||||
@@ -300,7 +298,6 @@ abstract class PersistentLogicSystem(context: ConeInferenceContext) : LogicSyste
|
||||
} else {
|
||||
flow.backwardsAliasMap.put(existedAlias, updatedBackwardsAliasList)
|
||||
}
|
||||
flow.updatedAliasDiff = flow.updatedAliasDiff.add(variable)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -99,7 +99,10 @@ internal val FirElement.symbol: AbstractFirBasedSymbol<*>?
|
||||
is FirWhenSubjectExpression -> whenRef.value.subject?.symbol
|
||||
is FirSafeCallExpression -> regularQualifiedAccess.symbol
|
||||
else -> null
|
||||
}?.takeIf { this.unwrapSmartcastExpression() is FirThisReceiverExpression || (it !is FirFunctionSymbol<*> && it !is FirAccessorSymbol) }
|
||||
}?.takeIf {
|
||||
(this as? FirExpression)?.unwrapSmartcastExpression() is FirThisReceiverExpression ||
|
||||
(it !is FirFunctionSymbol<*> && it !is FirAccessorSymbol)
|
||||
}
|
||||
|
||||
@DfaInternals
|
||||
internal val FirResolvable.symbol: AbstractFirBasedSymbol<*>?
|
||||
@@ -110,4 +113,8 @@ internal val FirResolvable.symbol: AbstractFirBasedSymbol<*>?
|
||||
else -> null
|
||||
}
|
||||
|
||||
private fun FirElement.unwrapSmartcastExpression(): FirElement = if (this is FirExpressionWithSmartcast) originalExpression else this
|
||||
internal fun FirExpression.unwrapSmartcastExpression(): FirExpression =
|
||||
when (this) {
|
||||
is FirExpressionWithSmartcast -> originalExpression
|
||||
else -> this
|
||||
}
|
||||
|
||||
@@ -238,7 +238,7 @@ class BodyResolveContext(
|
||||
return FirMemberTypeParameterScope(this)
|
||||
}
|
||||
|
||||
private fun buildSecondaryConstructorParametersScope(constructor: FirConstructor): FirLocalScope =
|
||||
fun buildSecondaryConstructorParametersScope(constructor: FirConstructor): FirLocalScope =
|
||||
constructor.valueParameters.fold(FirLocalScope()) { acc, param -> acc.storeVariable(param) }
|
||||
|
||||
@PrivateForInline
|
||||
@@ -296,7 +296,7 @@ class BodyResolveContext(
|
||||
@OptIn(PrivateForInline::class)
|
||||
inline fun <T> withAnonymousFunctionTowerDataContext(symbol: FirAnonymousFunctionSymbol, f: () -> T): T {
|
||||
return withTowerModeCleanup {
|
||||
towerDataContextsForClassParts.setAnonymousFunctionContext(symbol)
|
||||
towerDataContextsForClassParts.setAnonymousFunctionContextIfAny(symbol)
|
||||
f()
|
||||
}
|
||||
}
|
||||
@@ -486,6 +486,12 @@ class BodyResolveContext(
|
||||
return withTowerDataCleanup {
|
||||
addLocalScope(FirLocalScope())
|
||||
if (function is FirSimpleFunction) {
|
||||
// Make all value parameters available in the local scope so that even one parameter that refers to another parameter,
|
||||
// which may not be initialized yet, can be resolved. [FirFunctionParameterChecker] will detect and report an error
|
||||
// if an uninitialized parameter is accessed by a preceding parameter.
|
||||
for (parameter in function.valueParameters) {
|
||||
storeVariable(parameter)
|
||||
}
|
||||
val receiverTypeRef = function.receiverTypeRef
|
||||
withLabelAndReceiverType(function.name, function, receiverTypeRef?.coneType, holder, f)
|
||||
} else {
|
||||
@@ -665,19 +671,23 @@ class BodyResolveContext(
|
||||
f: () -> T
|
||||
): T {
|
||||
// Default values of constructor can't access members of constructing class
|
||||
return withTowerDataMode(FirTowerDataMode.CONSTRUCTOR_HEADER) {
|
||||
if (!constructor.isPrimary) {
|
||||
addInaccessibleImplicitReceiverValue(owningClass, holder)
|
||||
}
|
||||
withTowerDataCleanup {
|
||||
addLocalScope(FirLocalScope())
|
||||
f()
|
||||
}
|
||||
}
|
||||
// But, let them get resolved, then [FirFunctionParameterChecker] will detect and report an error
|
||||
// if an uninitialized parameter is accessed by a preceding parameter.
|
||||
return forConstructorParametersOrDelegatedConstructorCall(constructor, owningClass, holder, f)
|
||||
}
|
||||
|
||||
@OptIn(PrivateForInline::class)
|
||||
fun <T> forDelegatedConstructor(
|
||||
inline fun <T> forDelegatedConstructorCall(
|
||||
constructor: FirConstructor,
|
||||
owningClass: FirRegularClass?,
|
||||
holder: SessionHolder,
|
||||
f: () -> T
|
||||
): T {
|
||||
return forConstructorParametersOrDelegatedConstructorCall(constructor, owningClass, holder, f)
|
||||
}
|
||||
|
||||
@OptIn(PrivateForInline::class)
|
||||
inline fun <T> forConstructorParametersOrDelegatedConstructorCall(
|
||||
constructor: FirConstructor,
|
||||
owningClass: FirRegularClass?,
|
||||
holder: SessionHolder,
|
||||
|
||||
@@ -22,6 +22,7 @@ import org.jetbrains.kotlin.fir.references.FirResolvedNamedReference
|
||||
import org.jetbrains.kotlin.fir.resolve.*
|
||||
import org.jetbrains.kotlin.fir.resolve.calls.FirNamedReferenceWithCandidate
|
||||
import org.jetbrains.kotlin.fir.resolve.dfa.FirControlFlowGraphReferenceImpl
|
||||
import org.jetbrains.kotlin.fir.resolve.dfa.unwrapSmartcastExpression
|
||||
import org.jetbrains.kotlin.fir.resolve.inference.extractLambdaInfoFromFunctionalType
|
||||
import org.jetbrains.kotlin.fir.resolve.inference.isSuspendFunctionType
|
||||
import org.jetbrains.kotlin.fir.resolve.substitution.ConeSubstitutor
|
||||
@@ -594,9 +595,7 @@ open class FirDeclarationsResolveTransformer(transformer: FirBodyResolveTransfor
|
||||
ConeSimpleDiagnostic("No type for parameter", DiagnosticKind.ValueParameterWithNoTypeAnnotation)
|
||||
)
|
||||
)
|
||||
return context.withValueParameter(valueParameter) {
|
||||
valueParameter
|
||||
}
|
||||
return valueParameter
|
||||
}
|
||||
|
||||
dataFlowAnalyzer.enterValueParameter(valueParameter)
|
||||
@@ -795,7 +794,7 @@ open class FirDeclarationsResolveTransformer(transformer: FirBodyResolveTransfor
|
||||
if (variable.returnTypeRef is FirImplicitTypeRef) {
|
||||
val resultType = when {
|
||||
initializer != null -> {
|
||||
val unwrappedInitializer = (initializer as? FirExpressionWithSmartcast)?.originalExpression ?: initializer
|
||||
val unwrappedInitializer = initializer.unwrapSmartcastExpression()
|
||||
unwrappedInitializer.resultType
|
||||
}
|
||||
variable.getter != null && variable.getter !is FirDefaultPropertyAccessor -> variable.getter?.returnTypeRef
|
||||
|
||||
@@ -863,7 +863,7 @@ open class FirExpressionsResolveTransformer(transformer: FirBodyResolveTransform
|
||||
var result = delegatedConstructorCall
|
||||
try {
|
||||
val lastDispatchReceiver = implicitReceiverStack.lastDispatchReceiver()
|
||||
context.forDelegatedConstructor(containingConstructor, containingClass as? FirRegularClass, components) {
|
||||
context.forDelegatedConstructorCall(containingConstructor, containingClass as? FirRegularClass, components) {
|
||||
delegatedConstructorCall.transformChildren(transformer, ResolutionMode.ContextDependent)
|
||||
}
|
||||
|
||||
|
||||
@@ -118,6 +118,13 @@ class ConeEffectExtractor(
|
||||
return expressionWithSmartcast.originalExpression.accept(this, data)
|
||||
}
|
||||
|
||||
override fun visitExpressionWithSmartcastToNull(
|
||||
expressionWithSmartcastToNull: FirExpressionWithSmartcastToNull,
|
||||
data: Nothing?
|
||||
): ConeContractDescriptionElement? {
|
||||
return expressionWithSmartcastToNull.originalExpression.accept(this, data)
|
||||
}
|
||||
|
||||
override fun visitQualifiedAccessExpression(
|
||||
qualifiedAccessExpression: FirQualifiedAccessExpression,
|
||||
data: Nothing?
|
||||
@@ -189,4 +196,4 @@ class ConeEffectExtractor(
|
||||
else -> null
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,63 @@
|
||||
/*
|
||||
* Copyright 2010-2021 JetBrains s.r.o. and Kotlin Programming Language contributors.
|
||||
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
|
||||
*/
|
||||
|
||||
package org.jetbrains.kotlin.fir.expressions
|
||||
|
||||
import org.jetbrains.kotlin.fir.FirElement
|
||||
import org.jetbrains.kotlin.fir.FirSourceElement
|
||||
import org.jetbrains.kotlin.fir.references.FirReference
|
||||
import org.jetbrains.kotlin.fir.types.ConeKotlinType
|
||||
import org.jetbrains.kotlin.fir.types.FirTypeProjection
|
||||
import org.jetbrains.kotlin.fir.types.FirTypeRef
|
||||
import org.jetbrains.kotlin.fir.visitors.*
|
||||
import org.jetbrains.kotlin.fir.FirImplementationDetail
|
||||
|
||||
/*
|
||||
* This file was generated automatically
|
||||
* DO NOT MODIFY IT MANUALLY
|
||||
*/
|
||||
|
||||
abstract class FirExpressionWithSmartcastToNull : FirExpressionWithSmartcast() {
|
||||
abstract override val source: FirSourceElement?
|
||||
abstract override val typeRef: FirTypeRef
|
||||
abstract override val annotations: List<FirAnnotationCall>
|
||||
abstract override val calleeReference: FirReference
|
||||
abstract override val typeArguments: List<FirTypeProjection>
|
||||
abstract override val explicitReceiver: FirExpression?
|
||||
abstract override val dispatchReceiver: FirExpression
|
||||
abstract override val extensionReceiver: FirExpression
|
||||
abstract override val originalExpression: FirQualifiedAccessExpression
|
||||
abstract override val typesFromSmartCast: Collection<ConeKotlinType>
|
||||
abstract override val originalType: FirTypeRef
|
||||
|
||||
override fun <R, D> accept(visitor: FirVisitor<R, D>, data: D): R = visitor.visitExpressionWithSmartcastToNull(this, data)
|
||||
|
||||
@Suppress("UNCHECKED_CAST")
|
||||
override fun <E: FirElement, D> transform(transformer: FirTransformer<D>, data: D): E =
|
||||
transformer.transformExpressionWithSmartcastToNull(this, data) as E
|
||||
|
||||
@FirImplementationDetail
|
||||
abstract override fun replaceSource(newSource: FirSourceElement?)
|
||||
|
||||
abstract override fun replaceTypeRef(newTypeRef: FirTypeRef)
|
||||
|
||||
abstract override fun replaceCalleeReference(newCalleeReference: FirReference)
|
||||
|
||||
abstract override fun replaceTypeArguments(newTypeArguments: List<FirTypeProjection>)
|
||||
|
||||
abstract override fun replaceExplicitReceiver(newExplicitReceiver: FirExpression?)
|
||||
|
||||
abstract override fun <D> transformAnnotations(transformer: FirTransformer<D>, data: D): FirExpressionWithSmartcastToNull
|
||||
|
||||
abstract override fun <D> transformCalleeReference(transformer: FirTransformer<D>, data: D): FirExpressionWithSmartcastToNull
|
||||
|
||||
abstract override fun <D> transformTypeArguments(transformer: FirTransformer<D>, data: D): FirExpressionWithSmartcastToNull
|
||||
|
||||
abstract override fun <D> transformExplicitReceiver(transformer: FirTransformer<D>, data: D): FirExpressionWithSmartcastToNull
|
||||
|
||||
abstract override fun <D> transformDispatchReceiver(transformer: FirTransformer<D>, data: D): FirExpressionWithSmartcastToNull
|
||||
|
||||
abstract override fun <D> transformExtensionReceiver(transformer: FirTransformer<D>, data: D): FirExpressionWithSmartcastToNull
|
||||
}
|
||||
@@ -91,6 +91,7 @@ import org.jetbrains.kotlin.fir.expressions.FirComponentCall
|
||||
import org.jetbrains.kotlin.fir.expressions.FirCallableReferenceAccess
|
||||
import org.jetbrains.kotlin.fir.expressions.FirThisReceiverExpression
|
||||
import org.jetbrains.kotlin.fir.expressions.FirExpressionWithSmartcast
|
||||
import org.jetbrains.kotlin.fir.expressions.FirExpressionWithSmartcastToNull
|
||||
import org.jetbrains.kotlin.fir.expressions.FirSafeCallExpression
|
||||
import org.jetbrains.kotlin.fir.expressions.FirCheckedSafeCallSubject
|
||||
import org.jetbrains.kotlin.fir.expressions.FirGetClassCall
|
||||
@@ -480,6 +481,10 @@ abstract class FirTransformer<in D> : FirVisitor<FirElement, D>() {
|
||||
return transformElement(expressionWithSmartcast, data)
|
||||
}
|
||||
|
||||
open fun transformExpressionWithSmartcastToNull(expressionWithSmartcastToNull: FirExpressionWithSmartcastToNull, data: D): FirStatement {
|
||||
return transformElement(expressionWithSmartcastToNull, data)
|
||||
}
|
||||
|
||||
open fun transformSafeCallExpression(safeCallExpression: FirSafeCallExpression, data: D): FirStatement {
|
||||
return transformElement(safeCallExpression, data)
|
||||
}
|
||||
@@ -980,6 +985,10 @@ abstract class FirTransformer<in D> : FirVisitor<FirElement, D>() {
|
||||
return transformExpressionWithSmartcast(expressionWithSmartcast, data)
|
||||
}
|
||||
|
||||
final override fun visitExpressionWithSmartcastToNull(expressionWithSmartcastToNull: FirExpressionWithSmartcastToNull, data: D): FirStatement {
|
||||
return transformExpressionWithSmartcastToNull(expressionWithSmartcastToNull, data)
|
||||
}
|
||||
|
||||
final override fun visitSafeCallExpression(safeCallExpression: FirSafeCallExpression, data: D): FirStatement {
|
||||
return transformSafeCallExpression(safeCallExpression, data)
|
||||
}
|
||||
|
||||
@@ -91,6 +91,7 @@ import org.jetbrains.kotlin.fir.expressions.FirComponentCall
|
||||
import org.jetbrains.kotlin.fir.expressions.FirCallableReferenceAccess
|
||||
import org.jetbrains.kotlin.fir.expressions.FirThisReceiverExpression
|
||||
import org.jetbrains.kotlin.fir.expressions.FirExpressionWithSmartcast
|
||||
import org.jetbrains.kotlin.fir.expressions.FirExpressionWithSmartcastToNull
|
||||
import org.jetbrains.kotlin.fir.expressions.FirSafeCallExpression
|
||||
import org.jetbrains.kotlin.fir.expressions.FirCheckedSafeCallSubject
|
||||
import org.jetbrains.kotlin.fir.expressions.FirGetClassCall
|
||||
@@ -309,6 +310,8 @@ abstract class FirVisitor<out R, in D> {
|
||||
|
||||
open fun visitExpressionWithSmartcast(expressionWithSmartcast: FirExpressionWithSmartcast, data: D): R = visitElement(expressionWithSmartcast, data)
|
||||
|
||||
open fun visitExpressionWithSmartcastToNull(expressionWithSmartcastToNull: FirExpressionWithSmartcastToNull, data: D): R = visitElement(expressionWithSmartcastToNull, data)
|
||||
|
||||
open fun visitSafeCallExpression(safeCallExpression: FirSafeCallExpression, data: D): R = visitElement(safeCallExpression, data)
|
||||
|
||||
open fun visitCheckedSafeCallSubject(checkedSafeCallSubject: FirCheckedSafeCallSubject, data: D): R = visitElement(checkedSafeCallSubject, data)
|
||||
|
||||
@@ -91,6 +91,7 @@ import org.jetbrains.kotlin.fir.expressions.FirComponentCall
|
||||
import org.jetbrains.kotlin.fir.expressions.FirCallableReferenceAccess
|
||||
import org.jetbrains.kotlin.fir.expressions.FirThisReceiverExpression
|
||||
import org.jetbrains.kotlin.fir.expressions.FirExpressionWithSmartcast
|
||||
import org.jetbrains.kotlin.fir.expressions.FirExpressionWithSmartcastToNull
|
||||
import org.jetbrains.kotlin.fir.expressions.FirSafeCallExpression
|
||||
import org.jetbrains.kotlin.fir.expressions.FirCheckedSafeCallSubject
|
||||
import org.jetbrains.kotlin.fir.expressions.FirGetClassCall
|
||||
@@ -479,6 +480,10 @@ abstract class FirVisitorVoid : FirVisitor<Unit, Nothing?>() {
|
||||
visitElement(expressionWithSmartcast)
|
||||
}
|
||||
|
||||
open fun visitExpressionWithSmartcastToNull(expressionWithSmartcastToNull: FirExpressionWithSmartcastToNull) {
|
||||
visitElement(expressionWithSmartcastToNull)
|
||||
}
|
||||
|
||||
open fun visitSafeCallExpression(safeCallExpression: FirSafeCallExpression) {
|
||||
visitElement(safeCallExpression)
|
||||
}
|
||||
@@ -979,6 +984,10 @@ abstract class FirVisitorVoid : FirVisitor<Unit, Nothing?>() {
|
||||
visitExpressionWithSmartcast(expressionWithSmartcast)
|
||||
}
|
||||
|
||||
final override fun visitExpressionWithSmartcastToNull(expressionWithSmartcastToNull: FirExpressionWithSmartcastToNull, data: Nothing?) {
|
||||
visitExpressionWithSmartcastToNull(expressionWithSmartcastToNull)
|
||||
}
|
||||
|
||||
final override fun visitSafeCallExpression(safeCallExpression: FirSafeCallExpression, data: Nothing?) {
|
||||
visitSafeCallExpression(safeCallExpression)
|
||||
}
|
||||
|
||||
@@ -170,6 +170,10 @@ sealed class FirFakeSourceElementKind : FirSourceElementKind() {
|
||||
// for java annotations constructor implicit parameters are generated
|
||||
// with a fake source which refers to declared annotation methods
|
||||
object ImplicitAnnotationAnnotationConstructorParameter : FirFakeSourceElementKind()
|
||||
|
||||
// for the implicit field storing the delegated object for class delegation
|
||||
// with a fake source that refers to the KtExpression that creates the delegate
|
||||
object ClassDelegationField : FirFakeSourceElementKind()
|
||||
}
|
||||
|
||||
sealed class FirSourceElement {
|
||||
|
||||
@@ -57,6 +57,12 @@ inline val FirRegularClass.isFun get() = status.isFun
|
||||
inline val FirMemberDeclaration.modality get() = status.modality
|
||||
inline val FirMemberDeclaration.isAbstract get() = status.modality == Modality.ABSTRACT
|
||||
inline val FirMemberDeclaration.isOpen get() = status.modality == Modality.OPEN
|
||||
inline val FirMemberDeclaration.isFinal: Boolean
|
||||
get() {
|
||||
// member with unspecified modality is final
|
||||
val modality = status.modality ?: return true
|
||||
return modality == Modality.FINAL
|
||||
}
|
||||
|
||||
inline val FirMemberDeclaration.visibility: Visibility get() = status.visibility
|
||||
inline val FirMemberDeclaration.effectiveVisibility: EffectiveVisibility
|
||||
|
||||
@@ -50,7 +50,7 @@ inline val FirCall.resolvedArgumentMapping: Map<FirExpression, FirValueParameter
|
||||
else -> null
|
||||
}
|
||||
|
||||
inline val FirCall.argumentMapping: Map<FirExpression, FirValueParameter>?
|
||||
inline val FirCall.argumentMapping: LinkedHashMap<FirExpression, FirValueParameter>?
|
||||
get() = when (val argumentList = argumentList) {
|
||||
is FirResolvedArgumentList -> argumentList.mapping
|
||||
is FirPartiallyResolvedArgumentList -> argumentList.mapping
|
||||
|
||||
@@ -0,0 +1,26 @@
|
||||
/*
|
||||
* Copyright 2010-2021 JetBrains s.r.o. and Kotlin Programming Language contributors.
|
||||
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
|
||||
*/
|
||||
|
||||
package org.jetbrains.kotlin.fir.expressions.builder
|
||||
|
||||
import org.jetbrains.kotlin.fir.expressions.FirExpressionWithSmartcastToNull
|
||||
import org.jetbrains.kotlin.fir.expressions.FirQualifiedAccessExpression
|
||||
import org.jetbrains.kotlin.fir.expressions.impl.FirExpressionWithSmartcastToNullImpl
|
||||
import org.jetbrains.kotlin.fir.types.ConeKotlinType
|
||||
import org.jetbrains.kotlin.fir.types.FirTypeRef
|
||||
|
||||
class FirExpressionWithSmartcastToNullBuilder {
|
||||
lateinit var originalExpression: FirQualifiedAccessExpression
|
||||
lateinit var typeRef: FirTypeRef
|
||||
lateinit var typesFromSmartCast: Collection<ConeKotlinType>
|
||||
|
||||
fun build(): FirExpressionWithSmartcastToNull {
|
||||
return FirExpressionWithSmartcastToNullImpl(originalExpression, typeRef, typesFromSmartCast)
|
||||
}
|
||||
}
|
||||
|
||||
inline fun buildExpressionWithSmartcastToNull(init: FirExpressionWithSmartcastToNullBuilder.() -> Unit): FirExpressionWithSmartcastToNull {
|
||||
return FirExpressionWithSmartcastToNullBuilder().apply(init).build()
|
||||
}
|
||||
@@ -0,0 +1,88 @@
|
||||
/*
|
||||
* Copyright 2010-2021 JetBrains s.r.o. and Kotlin Programming Language contributors.
|
||||
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
|
||||
*/
|
||||
|
||||
package org.jetbrains.kotlin.fir.expressions.impl
|
||||
|
||||
import org.jetbrains.kotlin.fir.FirImplementationDetail
|
||||
import org.jetbrains.kotlin.fir.FirSourceElement
|
||||
import org.jetbrains.kotlin.fir.expressions.*
|
||||
import org.jetbrains.kotlin.fir.references.FirReference
|
||||
import org.jetbrains.kotlin.fir.types.ConeKotlinType
|
||||
import org.jetbrains.kotlin.fir.types.FirResolvedTypeRef
|
||||
import org.jetbrains.kotlin.fir.types.FirTypeProjection
|
||||
import org.jetbrains.kotlin.fir.types.FirTypeRef
|
||||
import org.jetbrains.kotlin.fir.visitors.FirTransformer
|
||||
import org.jetbrains.kotlin.fir.visitors.FirVisitor
|
||||
import org.jetbrains.kotlin.fir.visitors.transformSingle
|
||||
|
||||
class FirExpressionWithSmartcastToNullImpl(
|
||||
override var originalExpression: FirQualifiedAccessExpression,
|
||||
override val typeRef: FirTypeRef,
|
||||
override val typesFromSmartCast: Collection<ConeKotlinType>
|
||||
) : FirExpressionWithSmartcastToNull() {
|
||||
init {
|
||||
assert(originalExpression.typeRef is FirResolvedTypeRef)
|
||||
}
|
||||
|
||||
override val source: FirSourceElement? get() = originalExpression.source
|
||||
override val annotations: List<FirAnnotationCall> get() = originalExpression.annotations
|
||||
override val typeArguments: List<FirTypeProjection> get() = originalExpression.typeArguments
|
||||
override val explicitReceiver: FirExpression? get() = originalExpression.explicitReceiver
|
||||
override val dispatchReceiver: FirExpression get() = originalExpression.dispatchReceiver
|
||||
override val extensionReceiver: FirExpression get() = originalExpression.extensionReceiver
|
||||
override val calleeReference: FirReference get() = originalExpression.calleeReference
|
||||
override val originalType: FirTypeRef get() = originalExpression.typeRef
|
||||
|
||||
override fun <D> transformChildren(transformer: FirTransformer<D>, data: D): FirExpressionWithSmartcastToNull {
|
||||
originalExpression = originalExpression.transformSingle(transformer, data)
|
||||
return this
|
||||
}
|
||||
|
||||
override fun <R, D> acceptChildren(visitor: FirVisitor<R, D>, data: D) {
|
||||
originalExpression.accept(visitor, data)
|
||||
}
|
||||
|
||||
override fun <D> transformCalleeReference(transformer: FirTransformer<D>, data: D): FirExpressionWithSmartcastToNull {
|
||||
throw IllegalStateException()
|
||||
}
|
||||
|
||||
override fun <D> transformExplicitReceiver(transformer: FirTransformer<D>, data: D): FirExpressionWithSmartcastToNull {
|
||||
throw IllegalStateException()
|
||||
}
|
||||
|
||||
override fun <D> transformDispatchReceiver(transformer: FirTransformer<D>, data: D): FirExpressionWithSmartcastToNull {
|
||||
throw IllegalStateException()
|
||||
}
|
||||
|
||||
override fun <D> transformExtensionReceiver(transformer: FirTransformer<D>, data: D): FirExpressionWithSmartcastToNull {
|
||||
throw IllegalStateException()
|
||||
}
|
||||
|
||||
override fun <D> transformTypeArguments(transformer: FirTransformer<D>, data: D): FirExpressionWithSmartcastToNull {
|
||||
throw IllegalStateException()
|
||||
}
|
||||
|
||||
override fun <D> transformAnnotations(transformer: FirTransformer<D>, data: D): FirExpressionWithSmartcastToNull {
|
||||
throw IllegalStateException()
|
||||
}
|
||||
|
||||
override fun replaceTypeArguments(newTypeArguments: List<FirTypeProjection>) {
|
||||
throw IllegalStateException()
|
||||
}
|
||||
|
||||
override fun replaceCalleeReference(newCalleeReference: FirReference) {
|
||||
throw IllegalStateException()
|
||||
}
|
||||
|
||||
override fun replaceExplicitReceiver(newExplicitReceiver: FirExpression?) {
|
||||
throw IllegalStateException()
|
||||
}
|
||||
|
||||
override fun replaceTypeRef(newTypeRef: FirTypeRef) {}
|
||||
|
||||
@FirImplementationDetail
|
||||
override fun replaceSource(newSource: FirSourceElement?) {
|
||||
}
|
||||
}
|
||||
@@ -108,6 +108,7 @@ object FirTreeBuilder : AbstractFirTreeBuilder() {
|
||||
val callableReferenceAccess = element("CallableReferenceAccess", Expression, qualifiedAccessExpression)
|
||||
val thisReceiverExpression = element("ThisReceiverExpression", Expression, qualifiedAccessExpression)
|
||||
val expressionWithSmartcast = element("ExpressionWithSmartcast", Expression, qualifiedAccessExpression)
|
||||
val expressionWithSmartcastToNull = element("ExpressionWithSmartcastToNull", Expression, expressionWithSmartcast)
|
||||
val safeCallExpression = element("SafeCallExpression", Expression, expression)
|
||||
val checkedSafeCallSubject = element("CheckedSafeCallSubject", Expression, expression)
|
||||
val getClassCall = element("GetClassCall", Expression, expression, call)
|
||||
|
||||
@@ -156,6 +156,7 @@ object ImplementationConfigurator : AbstractFirTreeImplementationConfigurator()
|
||||
impl(qualifiedAccessExpression)
|
||||
|
||||
noImpl(expressionWithSmartcast)
|
||||
noImpl(expressionWithSmartcastToNull)
|
||||
|
||||
impl(getClassCall) {
|
||||
default("argument") {
|
||||
|
||||
@@ -459,6 +459,12 @@ object NodeConfigurator : AbstractFieldConfigurator<FirTreeBuilder>(FirTreeBuild
|
||||
+field("originalType", typeRef)
|
||||
}
|
||||
|
||||
expressionWithSmartcastToNull.configure {
|
||||
+field("originalExpression", qualifiedAccessExpression)
|
||||
+field("typesFromSmartCast", "Collection<ConeKotlinType>", null, customType = coneKotlinTypeType)
|
||||
+field("originalType", typeRef)
|
||||
}
|
||||
|
||||
safeCallExpression.configure {
|
||||
+field("receiver", expression).withTransform()
|
||||
// Special node that might be used as a reference to receiver of a safe call after null check
|
||||
|
||||
@@ -98,7 +98,7 @@ object JvmFileClassUtil {
|
||||
it.calleeExpression?.constructorReferenceExpression?.getReferencedName() == shortName
|
||||
}
|
||||
|
||||
private fun getLiteralStringFromAnnotation(annotation: KtAnnotationEntry): String? {
|
||||
fun getLiteralStringFromAnnotation(annotation: KtAnnotationEntry): String? {
|
||||
val argumentExpression = annotation.valueArguments.firstOrNull()?.getArgumentExpression() ?: return null
|
||||
val stringTemplate = argumentExpression as? KtStringTemplateExpression ?: return null
|
||||
val singleEntry = stringTemplate.entries.singleOrNull() as? KtLiteralStringTemplateEntry ?: return null
|
||||
|
||||
@@ -79,8 +79,9 @@ class VirtualFileKotlinClass private constructor(
|
||||
}
|
||||
|
||||
private fun logFileReadingErrorMessage(e: Throwable, file: VirtualFile): Throwable {
|
||||
LOG.warn(renderFileReadingErrorMessage(file), e)
|
||||
return e
|
||||
val errorMessage = renderFileReadingErrorMessage(file)
|
||||
LOG.warn(errorMessage, e)
|
||||
return IllegalStateException(errorMessage, e)
|
||||
}
|
||||
|
||||
private fun renderFileReadingErrorMessage(file: VirtualFile): String =
|
||||
|
||||
@@ -261,8 +261,8 @@ class ResolvedAtomCompleter(
|
||||
}
|
||||
}
|
||||
|
||||
val substitutedValueParameterTypes = descriptor.valueParameters.mapIndexed { i, valueParameter ->
|
||||
valueParameterTypes[i].substituteAndApproximate(substitutor).also {
|
||||
val substitutedValueParameterTypes = descriptor.valueParameters.mapIndexedNotNull { i, valueParameter ->
|
||||
valueParameterTypes.getOrNull(i)?.substituteAndApproximate(substitutor)?.also {
|
||||
if (valueParameter is ValueParameterDescriptorImpl && valueParameter.type.shouldBeUpdated()) {
|
||||
valueParameter.setOutType(it.approximatedType)
|
||||
}
|
||||
|
||||
@@ -16,6 +16,7 @@
|
||||
|
||||
package org.jetbrains.kotlin.resolve.diagnostics
|
||||
|
||||
import com.intellij.openapi.diagnostic.Logger
|
||||
import com.intellij.openapi.util.CompositeModificationTracker
|
||||
import com.intellij.psi.PsiElement
|
||||
import com.intellij.psi.util.CachedValueProvider
|
||||
@@ -48,8 +49,10 @@ class MutableDiagnosticsWithSuppression(
|
||||
override fun noSuppression() = readonlyView().noSuppression()
|
||||
|
||||
override fun setCallback(callback: DiagnosticSink.DiagnosticsCallback) {
|
||||
// TODO: [VD] temporary dirty patch, proper investigation is required
|
||||
// assert(diagnosticsCallback == null) { "diagnostic callback has been already registered" }
|
||||
diagnosticsCallback?.let {
|
||||
Logger.getInstance(MutableDiagnosticsWithSuppression::class.java).error("diagnostic callback has been already registered")
|
||||
return
|
||||
}
|
||||
diagnosticsCallback = callback
|
||||
delegateDiagnostics.setCallback(callback)
|
||||
}
|
||||
|
||||
@@ -35,7 +35,8 @@ class InitializersLowering(context: CommonBackendContext) : InitializersLowering
|
||||
|
||||
val irClass = container.constructedClass
|
||||
val instanceInitializerStatements = extractInitializers(irClass) {
|
||||
(it is IrField && !it.isStatic) || (it is IrAnonymousInitializer && !it.isStatic)
|
||||
(it is IrField && !it.isStatic && (container.isPrimary || !it.primaryConstructorParameter)) ||
|
||||
(it is IrAnonymousInitializer && !it.isStatic)
|
||||
}
|
||||
val block = IrBlockImpl(irClass.startOffset, irClass.endOffset, context.irBuiltIns.unitType, null, instanceInitializerStatements)
|
||||
// Check that the initializers contain no local classes. Deep-copying them is a disaster for code size, and liable to break randomly.
|
||||
@@ -54,6 +55,9 @@ class InitializersLowering(context: CommonBackendContext) : InitializersLowering
|
||||
}
|
||||
}
|
||||
|
||||
private val IrField.primaryConstructorParameter: Boolean
|
||||
get() = (initializer?.expression as? IrGetValue)?.origin == IrStatementOrigin.INITIALIZE_PROPERTY_FROM_PARAMETER
|
||||
|
||||
abstract class InitializersLoweringBase(open val context: CommonBackendContext) {
|
||||
protected fun extractInitializers(irClass: IrClass, filter: (IrDeclaration) -> Boolean) =
|
||||
// TODO What about fields that were added by lowerings? e.g. captured outer class or locals?
|
||||
|
||||
@@ -53,6 +53,8 @@ fun IrType.isTypeParameter() = classifierOrNull is IrTypeParameterSymbol
|
||||
|
||||
fun IrType.isInterface() = classOrNull?.owner?.kind == ClassKind.INTERFACE
|
||||
|
||||
fun IrType.isAnnotation() = classOrNull?.owner?.kind == ClassKind.ANNOTATION_CLASS
|
||||
|
||||
fun IrType.isFunctionOrKFunction() = isFunction() || isKFunction()
|
||||
|
||||
fun IrType.isSuspendFunctionOrKFunction() = isSuspendFunction() || isKSuspendFunction()
|
||||
@@ -141,8 +143,24 @@ private fun collectAllSupertypes(irType: IrSimpleType, result: MutableSet<IrSimp
|
||||
// for the class C, this function constructs:
|
||||
// { B<List<Z>>, A<List<List<Z>>, Any }
|
||||
// where Z is a type parameter of class C.
|
||||
fun getAllSubstitutedSupertypes(irClass: IrClass): MutableSet<IrSimpleType> {
|
||||
fun getAllSubstitutedSupertypes(irClass: IrClass): Set<IrSimpleType> {
|
||||
val result = HashSet<IrSimpleType>()
|
||||
collectAllSupertypes(irClass.defaultType, result)
|
||||
return result
|
||||
}
|
||||
|
||||
private fun collectAllSuperclasses(irClass: IrClass, set: MutableSet<IrClass>) {
|
||||
for (superType in irClass.superTypes) {
|
||||
val classifier = superType.classifierOrNull as? IrClassSymbol ?: continue
|
||||
val superClass = classifier.owner
|
||||
if (set.add(superClass)) {
|
||||
collectAllSuperclasses(superClass, set)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fun IrClass.getAllSuperclasses(): Set<IrClass> {
|
||||
val result = HashSet<IrClass>()
|
||||
collectAllSuperclasses(this, result)
|
||||
return result
|
||||
}
|
||||
|
||||
@@ -171,8 +171,7 @@ open class JvmIrCodegenFactory(
|
||||
val result = LinkedHashSet<ModuleDescriptor>()
|
||||
fun collectImpl(descriptor: ModuleDescriptor) {
|
||||
val dependencies = descriptor.allDependencyModules
|
||||
dependencies.forEach { if (it !in result) collectImpl(it) }
|
||||
result += dependencies
|
||||
dependencies.forEach { if (result.add(it)) collectImpl(it) }
|
||||
}
|
||||
collectImpl(this)
|
||||
return result.toList()
|
||||
|
||||
@@ -196,6 +196,7 @@ class JvmCachedDeclarations(
|
||||
isSuspend = target.isSuspend
|
||||
}.apply proxy@{
|
||||
parent = this@makeProxy
|
||||
copyAttributes(target)
|
||||
copyTypeParametersFrom(target)
|
||||
copyAnnotationsFrom(target)
|
||||
if (!isStatic) {
|
||||
|
||||
@@ -43,9 +43,7 @@ import org.jetbrains.kotlin.name.Name
|
||||
import org.jetbrains.kotlin.resolve.checkers.ExpectedActualDeclarationChecker
|
||||
import org.jetbrains.kotlin.types.TypeSystemCommonBackendContext
|
||||
import org.jetbrains.kotlin.types.model.KotlinTypeMarker
|
||||
import org.jetbrains.org.objectweb.asm.AnnotationVisitor
|
||||
import org.jetbrains.org.objectweb.asm.Type
|
||||
import org.jetbrains.org.objectweb.asm.TypePath
|
||||
import org.jetbrains.org.objectweb.asm.*
|
||||
import java.lang.annotation.RetentionPolicy
|
||||
|
||||
abstract class AnnotationCodegen(
|
||||
@@ -107,10 +105,10 @@ abstract class AnnotationCodegen(
|
||||
generateTypeAnnotations(annotated, typeForTypeAnnotations)
|
||||
}
|
||||
|
||||
abstract fun visitAnnotation(descr: String?, visible: Boolean): AnnotationVisitor
|
||||
abstract fun visitAnnotation(descr: String, visible: Boolean): AnnotationVisitor
|
||||
|
||||
open fun visitTypeAnnotation(
|
||||
descr: String?,
|
||||
descr: String,
|
||||
path: TypePath?,
|
||||
visible: Boolean,
|
||||
): AnnotationVisitor {
|
||||
@@ -287,6 +285,64 @@ abstract class AnnotationCodegen(
|
||||
}
|
||||
|
||||
companion object {
|
||||
|
||||
fun genAnnotationsOnTypeParametersAndBounds(
|
||||
context: JvmBackendContext,
|
||||
typeParameterContainer: IrTypeParametersContainer,
|
||||
classCodegen: ClassCodegen,
|
||||
referenceType: Int,
|
||||
boundType: Int,
|
||||
visitor: (typeRef: Int, typePath: TypePath?, descriptor: String, visible: Boolean) -> AnnotationVisitor
|
||||
) {
|
||||
if (context.state.target != JVM_1_6) {
|
||||
typeParameterContainer.typeParameters.forEachIndexed { index, typeParameter ->
|
||||
object : AnnotationCodegen(classCodegen, context, true) {
|
||||
override fun visitAnnotation(descr: String, visible: Boolean): AnnotationVisitor {
|
||||
|
||||
return visitor(
|
||||
TypeReference.newTypeParameterReference(referenceType, index).value,
|
||||
null,
|
||||
descr,
|
||||
visible
|
||||
)
|
||||
}
|
||||
|
||||
override fun visitTypeAnnotation(descr: String, path: TypePath?, visible: Boolean): AnnotationVisitor {
|
||||
throw RuntimeException(
|
||||
"Error during generation: type annotation shouldn't be presented on type parameter: " +
|
||||
"${ir2string(typeParameter)} in ${ir2string(typeParameterContainer)}"
|
||||
)
|
||||
}
|
||||
}.genAnnotations(typeParameter, null, null)
|
||||
|
||||
if (context.state.configuration.getBoolean(JVMConfigurationKeys.EMIT_JVM_TYPE_ANNOTATIONS)) {
|
||||
var superInterfaceIndex = 1
|
||||
typeParameter.superTypes.forEach { superType ->
|
||||
val isClassOrTypeParameter = !superType.isInterface() && !superType.isAnnotation()
|
||||
val superIndex = if (isClassOrTypeParameter) 0 else superInterfaceIndex++
|
||||
object : AnnotationCodegen(classCodegen, context, true) {
|
||||
override fun visitAnnotation(descr: String, visible: Boolean): AnnotationVisitor {
|
||||
throw RuntimeException(
|
||||
"Error during generation: only type annotations should be presented on type parameters bounds: " +
|
||||
"${ir2string(typeParameter)} in ${ir2string(typeParameter)}"
|
||||
)
|
||||
}
|
||||
|
||||
override fun visitTypeAnnotation(descr: String, path: TypePath?, visible: Boolean): AnnotationVisitor {
|
||||
return visitor(
|
||||
TypeReference.newTypeParameterBoundReference(boundType, index, superIndex).value,
|
||||
path,
|
||||
descr,
|
||||
visible
|
||||
)
|
||||
}
|
||||
}.generateTypeAnnotations(typeParameterContainer, superType)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun isInvisibleForNullabilityAnalysis(declaration: IrDeclaration): Boolean =
|
||||
when {
|
||||
declaration.origin.isSynthetic ->
|
||||
@@ -336,7 +392,7 @@ abstract class AnnotationCodegen(
|
||||
val IrConstructorCall.annotationClass get() = symbol.owner.parentAsClass
|
||||
}
|
||||
|
||||
private fun generateTypeAnnotations(
|
||||
internal fun generateTypeAnnotations(
|
||||
annotated: IrAnnotationContainer,
|
||||
type: IrType?
|
||||
) {
|
||||
|
||||
@@ -153,10 +153,21 @@ class ClassCodegen private constructor(
|
||||
}
|
||||
|
||||
object : AnnotationCodegen(this@ClassCodegen, context) {
|
||||
override fun visitAnnotation(descr: String?, visible: Boolean): AnnotationVisitor {
|
||||
override fun visitAnnotation(descr: String, visible: Boolean): AnnotationVisitor {
|
||||
return visitor.visitor.visitAnnotation(descr, visible)
|
||||
}
|
||||
}.genAnnotations(irClass, null, null)
|
||||
|
||||
AnnotationCodegen.genAnnotationsOnTypeParametersAndBounds(
|
||||
context,
|
||||
irClass,
|
||||
this,
|
||||
TypeReference.CLASS_TYPE_PARAMETER,
|
||||
TypeReference.CLASS_TYPE_PARAMETER_BOUND
|
||||
) { typeRef: Int, typePath: TypePath?, descriptor: String, visible: Boolean ->
|
||||
visitor.visitor.visitTypeAnnotation(typeRef, typePath, descriptor, visible)
|
||||
}
|
||||
|
||||
generateKotlinMetadataAnnotation()
|
||||
|
||||
generateInnerAndOuterClasses()
|
||||
@@ -306,11 +317,11 @@ class ClassCodegen private constructor(
|
||||
flags and (Opcodes.ACC_SYNTHETIC or Opcodes.ACC_ENUM) != 0 ||
|
||||
field.origin == JvmLoweredDeclarationOrigin.FIELD_FOR_STATIC_CALLABLE_REFERENCE_INSTANCE
|
||||
object : AnnotationCodegen(this@ClassCodegen, context, skipNullabilityAnnotations) {
|
||||
override fun visitAnnotation(descr: String?, visible: Boolean): AnnotationVisitor {
|
||||
override fun visitAnnotation(descr: String, visible: Boolean): AnnotationVisitor {
|
||||
return fv.visitAnnotation(descr, visible)
|
||||
}
|
||||
|
||||
override fun visitTypeAnnotation(descr: String?, path: TypePath?, visible: Boolean): AnnotationVisitor {
|
||||
override fun visitTypeAnnotation(descr: String, path: TypePath?, visible: Boolean): AnnotationVisitor {
|
||||
return fv.visitTypeAnnotation(TypeReference.newTypeReference(TypeReference.FIELD).value, path, descr, visible)
|
||||
}
|
||||
}.genAnnotations(field, fieldType, field.type)
|
||||
|
||||
@@ -144,6 +144,7 @@ private fun IrFunction.isStaticInlineClassReplacementDelegatingCall(): Boolean =
|
||||
|
||||
private val BRIDGE_ORIGINS = setOf(
|
||||
IrDeclarationOrigin.FUNCTION_FOR_DEFAULT_PARAMETER,
|
||||
JvmLoweredDeclarationOrigin.JVM_STATIC_WRAPPER,
|
||||
JvmLoweredDeclarationOrigin.JVM_OVERLOADS_WRAPPER,
|
||||
JvmLoweredDeclarationOrigin.SYNTHETIC_ACCESSOR,
|
||||
JvmLoweredDeclarationOrigin.SYNTHETIC_ACCESSOR_FOR_HIDDEN_CONSTRUCTOR,
|
||||
|
||||
@@ -16,8 +16,6 @@ import org.jetbrains.kotlin.backend.jvm.ir.erasedUpperBound
|
||||
import org.jetbrains.kotlin.backend.jvm.ir.isInlineClassType
|
||||
import org.jetbrains.kotlin.backend.jvm.lower.MultifileFacadeFileEntry
|
||||
import org.jetbrains.kotlin.backend.jvm.lower.constantValue
|
||||
import org.jetbrains.kotlin.backend.jvm.lower.inlineclasses.isInlineCallableReference
|
||||
import org.jetbrains.kotlin.backend.jvm.lower.inlineclasses.isMappedToPrimitive
|
||||
import org.jetbrains.kotlin.backend.jvm.lower.inlineclasses.requiresMangling
|
||||
import org.jetbrains.kotlin.backend.jvm.lower.inlineclasses.unboxInlineClass
|
||||
import org.jetbrains.kotlin.backend.jvm.lower.isMultifileBridge
|
||||
@@ -648,27 +646,16 @@ class ExpressionCodegen(
|
||||
val type = frameMap.typeOf(expression.symbol)
|
||||
mv.load(findLocalIndex(expression.symbol), type)
|
||||
unboxResultIfNeeded(expression)
|
||||
unboxInlineClassArgumentOfInlineCallableReference(expression)
|
||||
return MaterialValue(this, type, expression.type)
|
||||
}
|
||||
|
||||
// JVM_IR generates inline callable differently from the old backend:
|
||||
// it generates them as normal functions and not objects.
|
||||
// Thus, we need to unbox inline class argument with reference underlying type.
|
||||
private fun unboxInlineClassArgumentOfInlineCallableReference(arg: IrGetValue) {
|
||||
if (!arg.type.isInlineClassType()) return
|
||||
if (arg.type.isMappedToPrimitive) return
|
||||
if (!irFunction.isInlineCallableReference) return
|
||||
if (irFunction.extensionReceiverParameter?.symbol == arg.symbol) return
|
||||
if (arg.type.isNullable() && arg.type.makeNotNull().unboxInlineClass().isNullable()) return
|
||||
StackValue.unboxInlineClass(OBJECT_TYPE, arg.type.erasedUpperBound.defaultType, mv, typeMapper)
|
||||
}
|
||||
|
||||
// We do not mangle functions if Result is the only parameter of the function,
|
||||
// thus, if the function overrides generic parameter, its argument is boxed and there is no
|
||||
// bridge to unbox it. Instead, we unbox it in the non-mangled function manually.
|
||||
private fun unboxResultIfNeeded(arg: IrGetValue) {
|
||||
if (arg.type.erasedUpperBound.fqNameWhenAvailable != StandardNames.RESULT_FQ_NAME) return
|
||||
// Unlike inline callable reference arguments, nullable Result arguments are unboxed during coercion to not-null Result
|
||||
if (arg.type.isNullable()) return
|
||||
// Do not unbox arguments of lambda, but unbox arguments of callable references
|
||||
if (irFunction.origin == IrDeclarationOrigin.LOCAL_FUNCTION_FOR_LAMBDA) return
|
||||
if (!onlyResultInlineClassParameters()) return
|
||||
|
||||
@@ -79,16 +79,27 @@ class FunctionCodegen(
|
||||
if (irFunction.origin !in methodOriginsWithoutAnnotations) {
|
||||
val skipNullabilityAnnotations = flags and Opcodes.ACC_PRIVATE != 0 || flags and Opcodes.ACC_SYNTHETIC != 0
|
||||
object : AnnotationCodegen(classCodegen, context, skipNullabilityAnnotations) {
|
||||
override fun visitAnnotation(descr: String?, visible: Boolean): AnnotationVisitor {
|
||||
override fun visitAnnotation(descr: String, visible: Boolean): AnnotationVisitor {
|
||||
return methodVisitor.visitAnnotation(descr, visible)
|
||||
}
|
||||
|
||||
override fun visitTypeAnnotation(descr: String?, path: TypePath?, visible: Boolean): AnnotationVisitor {
|
||||
override fun visitTypeAnnotation(descr: String, path: TypePath?, visible: Boolean): AnnotationVisitor {
|
||||
return methodVisitor.visitTypeAnnotation(
|
||||
TypeReference.newTypeReference(TypeReference.METHOD_RETURN).value, path, descr, visible
|
||||
)
|
||||
}
|
||||
}.genAnnotations(irFunction, signature.asmMethod.returnType, irFunction.returnType)
|
||||
|
||||
AnnotationCodegen.genAnnotationsOnTypeParametersAndBounds(
|
||||
context,
|
||||
irFunction,
|
||||
classCodegen,
|
||||
TypeReference.METHOD_TYPE_PARAMETER,
|
||||
TypeReference.METHOD_TYPE_PARAMETER_BOUND
|
||||
) { typeRef: Int, typePath: TypePath?, descriptor: String, visible: Boolean ->
|
||||
methodVisitor.visitTypeAnnotation(typeRef, typePath, descriptor, visible)
|
||||
}
|
||||
|
||||
if (shouldGenerateAnnotationsOnValueParameters()) {
|
||||
generateParameterAnnotations(irFunction, methodVisitor, signature, classCodegen, context, skipNullabilityAnnotations)
|
||||
}
|
||||
@@ -218,7 +229,7 @@ class FunctionCodegen(
|
||||
private fun generateAnnotationDefaultValueIfNeeded(methodVisitor: MethodVisitor) {
|
||||
getAnnotationDefaultValueExpression()?.let { defaultValueExpression ->
|
||||
val annotationCodegen = object : AnnotationCodegen(classCodegen, context) {
|
||||
override fun visitAnnotation(descr: String?, visible: Boolean): AnnotationVisitor {
|
||||
override fun visitAnnotation(descr: String, visible: Boolean): AnnotationVisitor {
|
||||
return methodVisitor.visitAnnotationDefault()
|
||||
}
|
||||
}
|
||||
@@ -279,7 +290,7 @@ class FunctionCodegen(
|
||||
|
||||
if (annotated != null && !kind.isSkippedInGenericSignature && !annotated.isSyntheticMarkerParameter()) {
|
||||
object : AnnotationCodegen(innerClassConsumer, context, skipNullabilityAnnotations) {
|
||||
override fun visitAnnotation(descr: String?, visible: Boolean): AnnotationVisitor {
|
||||
override fun visitAnnotation(descr: String, visible: Boolean): AnnotationVisitor {
|
||||
return mv.visitParameterAnnotation(
|
||||
i - syntheticParameterCount,
|
||||
descr,
|
||||
@@ -287,7 +298,7 @@ class FunctionCodegen(
|
||||
)
|
||||
}
|
||||
|
||||
override fun visitTypeAnnotation(descr: String?, path: TypePath?, visible: Boolean): AnnotationVisitor {
|
||||
override fun visitTypeAnnotation(descr: String, path: TypePath?, visible: Boolean): AnnotationVisitor {
|
||||
return mv.visitTypeAnnotation(
|
||||
TypeReference.newFormalParameterReference(i - syntheticParameterCount).value,
|
||||
path, descr, visible
|
||||
|
||||
@@ -20,11 +20,11 @@ import org.jetbrains.kotlin.ir.declarations.*
|
||||
import org.jetbrains.kotlin.ir.descriptors.*
|
||||
import org.jetbrains.kotlin.ir.expressions.*
|
||||
import org.jetbrains.kotlin.ir.types.IrType
|
||||
import org.jetbrains.kotlin.ir.types.classOrNull
|
||||
import org.jetbrains.kotlin.ir.types.classifierOrFail
|
||||
import org.jetbrains.kotlin.ir.util.*
|
||||
import org.jetbrains.kotlin.resolve.jvm.AsmTypes
|
||||
import org.jetbrains.kotlin.resolve.jvm.jvmSignature.JvmMethodSignature
|
||||
import org.jetbrains.kotlin.types.KotlinType
|
||||
import org.jetbrains.kotlin.util.OperatorNameConventions
|
||||
import org.jetbrains.org.objectweb.asm.Type
|
||||
import org.jetbrains.org.objectweb.asm.commons.Method
|
||||
@@ -201,27 +201,33 @@ class IrExpressionLambdaImpl(
|
||||
|
||||
private val loweredMethod = codegen.methodSignatureMapper.mapAsmMethod(function)
|
||||
|
||||
val capturedParamsInDesc: List<Type> = if (isBoundCallableReference) {
|
||||
loweredMethod.argumentTypes.take(1)
|
||||
} else loweredMethod.argumentTypes.drop(if (isExtensionLambda) 1 else 0).take(capturedVars.size)
|
||||
private val captureParameterIndices: Pair<Int, Int>
|
||||
get() = when {
|
||||
isBoundCallableReference -> 0 to 1 // (bound receiver, real parameters...)
|
||||
isExtensionLambda -> 1 to capturedVars.size + 1 // (unbound receiver, captures..., real parameters...)
|
||||
else -> 0 to capturedVars.size // (captures..., real parameters...)
|
||||
}
|
||||
|
||||
val capturedParamsInDesc: List<Type> =
|
||||
captureParameterIndices.let { (from, to) -> loweredMethod.argumentTypes.take(to).drop(from) }
|
||||
|
||||
override val invokeMethod: Method = loweredMethod.let {
|
||||
Method(
|
||||
it.name,
|
||||
it.returnType,
|
||||
(if (isBoundCallableReference) it.argumentTypes.drop(1)
|
||||
else (if (isExtensionLambda) it.argumentTypes.take(1) else emptyList()) +
|
||||
it.argumentTypes.drop((if (isExtensionLambda) 1 else 0) + capturedVars.size)).toTypedArray()
|
||||
)
|
||||
val (startCapture, endCapture) = captureParameterIndices
|
||||
Method(it.name, it.returnType, (it.argumentTypes.take(startCapture) + it.argumentTypes.drop(endCapture)).toTypedArray())
|
||||
}
|
||||
|
||||
// Need the descriptor without captured parameters here.
|
||||
override val invokeMethodDescriptor: FunctionDescriptor = function.originalFunction.toIrBasedDescriptor()
|
||||
override val invokeMethodParameters: List<KotlinType?>
|
||||
get() {
|
||||
val allParameters = function.explicitParameters.map { it.type.toIrBasedKotlinType() }
|
||||
val (startCapture, endCapture) = captureParameterIndices
|
||||
return allParameters.take(startCapture) + allParameters.drop(endCapture)
|
||||
}
|
||||
|
||||
override val invokeMethodReturnType: KotlinType
|
||||
get() = function.returnType.toIrBasedKotlinType()
|
||||
|
||||
override val hasDispatchReceiver: Boolean = false
|
||||
|
||||
override fun getInlineSuspendLambdaViewDescriptor(): FunctionDescriptor = function.toIrBasedDescriptor()
|
||||
|
||||
override fun isCapturedSuspend(desc: CapturedParamDesc): Boolean =
|
||||
capturedParameters[desc]?.let { it.isInlineParameter() && it.type.isSuspendFunctionTypeOrSubtype() } == true
|
||||
}
|
||||
@@ -229,23 +235,20 @@ class IrExpressionLambdaImpl(
|
||||
class IrDefaultLambda(
|
||||
lambdaClassType: Type,
|
||||
capturedArgs: Array<Type>,
|
||||
private val irValueParameter: IrValueParameter,
|
||||
irValueParameter: IrValueParameter,
|
||||
offset: Int,
|
||||
needReification: Boolean
|
||||
) : DefaultLambda(
|
||||
lambdaClassType, capturedArgs, irValueParameter.toIrBasedDescriptor() as ValueParameterDescriptor, offset, needReification
|
||||
) {
|
||||
private val invoke =
|
||||
(irValueParameter.type.classifierOrFail.owner as IrClass).functions.single { it.name == OperatorNameConventions.INVOKE }
|
||||
|
||||
override fun mapAsmSignature(sourceCompiler: SourceCompilerForInline): Method {
|
||||
val invoke =
|
||||
irValueParameter.type.classOrNull!!.owner.declarations.filterIsInstance<IrFunction>().single { it.name.asString() == "invoke" }
|
||||
return (sourceCompiler as IrSourceCompilerForInline).codegen.context.methodSignatureMapper.mapSignatureSkipGeneric(invoke).asmMethod
|
||||
}
|
||||
override fun mapAsmSignature(sourceCompiler: SourceCompilerForInline, descriptor: FunctionDescriptor): Method =
|
||||
(sourceCompiler as IrSourceCompilerForInline).codegen.context.methodSignatureMapper.mapSignatureSkipGeneric(invoke).asmMethod
|
||||
|
||||
override fun findInvokeMethodDescriptor(): FunctionDescriptor =
|
||||
(irValueParameter.type.classifierOrFail.owner as IrClass).functions.single {
|
||||
it.name == OperatorNameConventions.INVOKE
|
||||
}.toIrBasedDescriptor()
|
||||
override fun findInvokeMethodDescriptor(isPropertyReference: Boolean): FunctionDescriptor =
|
||||
invoke.toIrBasedDescriptor()
|
||||
}
|
||||
|
||||
fun IrExpression.isInlineIrExpression() =
|
||||
|
||||
@@ -13,8 +13,6 @@ import org.jetbrains.kotlin.backend.common.lower.parentsWithSelf
|
||||
import org.jetbrains.kotlin.backend.jvm.JvmBackendContext
|
||||
import org.jetbrains.kotlin.backend.jvm.JvmLoweredDeclarationOrigin
|
||||
import org.jetbrains.kotlin.backend.jvm.ir.*
|
||||
import org.jetbrains.kotlin.backend.jvm.lower.inlineclasses.isInlineCallableReference
|
||||
import org.jetbrains.kotlin.backend.jvm.lower.inlineclasses.isMappedToPrimitive
|
||||
import org.jetbrains.kotlin.backend.jvm.lower.inlineclasses.unboxInlineClass
|
||||
import org.jetbrains.kotlin.backend.jvm.lower.suspendFunctionOriginal
|
||||
import org.jetbrains.kotlin.builtins.StandardNames
|
||||
@@ -62,7 +60,7 @@ class MethodSignatureMapper(private val context: JvmBackendContext) {
|
||||
fun mapFieldSignature(field: IrField): String? {
|
||||
val sw = BothSignatureWriter(BothSignatureWriter.Mode.TYPE)
|
||||
if (field.correspondingPropertySymbol?.owner?.isVar == true) {
|
||||
writeParameterType(sw, field.type, field, false)
|
||||
writeParameterType(sw, field.type, field)
|
||||
} else {
|
||||
mapReturnType(field, field.type, sw)
|
||||
}
|
||||
@@ -221,13 +219,6 @@ class MethodSignatureMapper(private val context: JvmBackendContext) {
|
||||
function.origin == JvmLoweredDeclarationOrigin.SYNTHETIC_INLINE_CLASS_MEMBER &&
|
||||
function.name.asString() == "box-impl"
|
||||
|
||||
private fun forceBoxedInlineClassParametersForInliner(function: IrDeclaration, type: IrType, isBoundReceiver: Boolean): Boolean {
|
||||
if (isBoundReceiver) return false
|
||||
if (function !is IrSimpleFunction) return false
|
||||
if (!function.isInlineCallableReference) return false
|
||||
return type.isInlineClassType() && !type.isMappedToPrimitive
|
||||
}
|
||||
|
||||
fun mapSignatureSkipGeneric(function: IrFunction): JvmMethodSignature =
|
||||
mapSignature(function, true)
|
||||
|
||||
@@ -252,7 +243,7 @@ class MethodSignatureMapper(private val context: JvmBackendContext) {
|
||||
|
||||
val receiverParameter = function.extensionReceiverParameter
|
||||
if (receiverParameter != null) {
|
||||
writeParameter(sw, JvmMethodParameterKind.RECEIVER, receiverParameter.type, function, true)
|
||||
writeParameter(sw, JvmMethodParameterKind.RECEIVER, receiverParameter.type, function)
|
||||
}
|
||||
|
||||
for (parameter in function.valueParameters) {
|
||||
@@ -265,7 +256,7 @@ class MethodSignatureMapper(private val context: JvmBackendContext) {
|
||||
if (shouldBoxSingleValueParameterForSpecialCaseOfRemove(function))
|
||||
parameter.type.makeNullable()
|
||||
else parameter.type
|
||||
writeParameter(sw, kind, type, function, parameter.symbol == function.extensionReceiverParameter?.symbol)
|
||||
writeParameter(sw, kind, type, function)
|
||||
}
|
||||
|
||||
sw.writeReturnType()
|
||||
@@ -331,19 +322,16 @@ class MethodSignatureMapper(private val context: JvmBackendContext) {
|
||||
sw: JvmSignatureWriter,
|
||||
kind: JvmMethodParameterKind,
|
||||
type: IrType,
|
||||
function: IrFunction,
|
||||
isReceiver: Boolean
|
||||
function: IrFunction
|
||||
) {
|
||||
sw.writeParameterType(kind)
|
||||
writeParameterType(sw, type, function, isReceiver)
|
||||
writeParameterType(sw, type, function)
|
||||
sw.writeParameterTypeEnd()
|
||||
}
|
||||
|
||||
private fun writeParameterType(sw: JvmSignatureWriter, type: IrType, declaration: IrDeclaration, isReceiver: Boolean) {
|
||||
private fun writeParameterType(sw: JvmSignatureWriter, type: IrType, declaration: IrDeclaration) {
|
||||
if (sw.skipGenericSignature()) {
|
||||
if (type.isInlineClassType() &&
|
||||
(declaration.isFromJava() || forceBoxedInlineClassParametersForInliner(declaration, type, isReceiver))
|
||||
) {
|
||||
if (type.isInlineClassType() && declaration.isFromJava()) {
|
||||
typeMapper.mapType(type, TypeMappingMode.GENERIC_ARGUMENT, sw)
|
||||
} else {
|
||||
typeMapper.mapType(type, TypeMappingMode.DEFAULT, sw)
|
||||
|
||||
@@ -8,12 +8,14 @@ package org.jetbrains.kotlin.backend.jvm.codegen
|
||||
import org.jetbrains.kotlin.backend.jvm.JvmLoweredDeclarationOrigin
|
||||
import org.jetbrains.kotlin.backend.jvm.ir.eraseTypeParameters
|
||||
import org.jetbrains.kotlin.backend.jvm.ir.erasedUpperBound
|
||||
import org.jetbrains.kotlin.backend.jvm.lower.inlineclasses.InlineClassAbi
|
||||
import org.jetbrains.kotlin.backend.jvm.lower.inlineclasses.*
|
||||
import org.jetbrains.kotlin.codegen.AsmUtil
|
||||
import org.jetbrains.kotlin.codegen.StackValue
|
||||
import org.jetbrains.kotlin.codegen.inline.v
|
||||
import org.jetbrains.kotlin.ir.declarations.IrTypeParameter
|
||||
import org.jetbrains.kotlin.ir.symbols.IrTypeParameterSymbol
|
||||
import org.jetbrains.kotlin.ir.types.*
|
||||
import org.jetbrains.kotlin.ir.util.defaultType
|
||||
import org.jetbrains.kotlin.ir.util.isTypeParameter
|
||||
import org.jetbrains.kotlin.ir.util.parentAsClass
|
||||
import org.jetbrains.kotlin.resolve.jvm.AsmTypes
|
||||
@@ -51,7 +53,17 @@ abstract class PromisedValue(val codegen: ExpressionCodegen, val type: Type, val
|
||||
}
|
||||
|
||||
!isFromTypeUnboxed && isToTypeUnboxed -> {
|
||||
StackValue.unboxInlineClass(type, erasedTargetType, mv, typeMapper)
|
||||
val irClass = codegen.irFunction.parentAsClass
|
||||
if (irClass.isInline && irClass.symbol == irType.classifierOrNull && !irType.isNullable()) {
|
||||
// Use getfield instead of unbox-impl inside inline classes
|
||||
codegen.v.getfield(
|
||||
typeMapper.classInternalName(irClass),
|
||||
irClass.inlineClassFieldName.asString(),
|
||||
typeMapper.mapType(irType).descriptor
|
||||
)
|
||||
} else {
|
||||
StackValue.unboxInlineClass(type, erasedTargetType, mv, typeMapper)
|
||||
}
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
@@ -28,6 +28,7 @@ import org.jetbrains.kotlin.ir.types.*
|
||||
import org.jetbrains.kotlin.ir.util.*
|
||||
import org.jetbrains.kotlin.ir.visitors.transformChildrenVoid
|
||||
import org.jetbrains.kotlin.load.java.JvmAnnotationNames
|
||||
import org.jetbrains.kotlin.name.FqName
|
||||
import org.jetbrains.kotlin.name.Name
|
||||
import org.jetbrains.kotlin.types.Variance
|
||||
import org.jetbrains.kotlin.utils.addIfNotNull
|
||||
@@ -59,6 +60,11 @@ internal class LambdaMetafactoryArgumentsBuilder(
|
||||
if (!reference.origin.isLambda && !samClass.isFromJava())
|
||||
return null
|
||||
|
||||
// Don't use JDK LambdaMetafactory for serializable lambdas
|
||||
// TODO implement support for serializable lambdas with LambdaMetafactory (requires additional code for deserialization)
|
||||
if (samClass.isInheritedFromSerializable())
|
||||
return null
|
||||
|
||||
val samMethod = samClass.getSingleAbstractMethod()
|
||||
?: throw AssertionError("SAM class has no single abstract method: ${samClass.render()}")
|
||||
|
||||
@@ -122,6 +128,12 @@ internal class LambdaMetafactoryArgumentsBuilder(
|
||||
return getLambdaMetafactoryArgsOrNullInner(reference, samMethod, samType, implFun)
|
||||
}
|
||||
|
||||
private val javaIoSerializableFqn =
|
||||
FqName("java.io").child(Name.identifier("Serializable"))
|
||||
|
||||
private fun IrClass.isInheritedFromSerializable(): Boolean =
|
||||
getAllSuperclasses().any { it.fqNameWhenAvailable == javaIoSerializableFqn }
|
||||
|
||||
private fun IrClass.requiresDelegationToDefaultImpls(): Boolean {
|
||||
for (irMemberFun in functions) {
|
||||
if (irMemberFun.modality == Modality.ABSTRACT)
|
||||
|
||||
@@ -167,7 +167,13 @@ internal class SamDelegatingLambdaBuilder(private val jvmContext: JvmBackendCont
|
||||
.irBlockBody {
|
||||
+irReturn(
|
||||
irCall(invokeFunction).also { invokeCall ->
|
||||
invokeCall.dispatchReceiver = irGet(tmp)
|
||||
// We need to cast receiver to the function type because it might have an imaginary type like KFunction2 which
|
||||
// is mapped to KFunction in the codegen by default, which has no 'invoke'. Looks like correct type arguments
|
||||
// are not needed here, so we use "raw" type for simplicity. If that stops working, we'll need to compute the
|
||||
// correct substitution of invocableFunctionClass by visiting tmp.type's hierarchy.
|
||||
val rawFunctionType = invocableFunctionClass.typeWith()
|
||||
|
||||
invokeCall.dispatchReceiver = irImplicitCast(irGet(tmp), rawFunctionType)
|
||||
var parameterIndex = 0
|
||||
invokeFunction.extensionReceiverParameter?.let {
|
||||
invokeCall.extensionReceiver = irGet(lambda.valueParameters[parameterIndex++])
|
||||
|
||||
@@ -174,11 +174,3 @@ val IrFunction.isInlineClassFieldGetter: Boolean
|
||||
|
||||
val IrFunction.isPrimaryInlineClassConstructor: Boolean
|
||||
get() = this is IrConstructor && isPrimary && constructedClass.isInline
|
||||
|
||||
val IrFunction.isInlineCallableReference: Boolean
|
||||
get() = origin == IrDeclarationOrigin.LOCAL_FUNCTION_FOR_LAMBDA && name.asString().contains("\$$STUB_FOR_INLINING")
|
||||
|
||||
val IrType.isMappedToPrimitive: Boolean
|
||||
get() = isInlineClassType() &&
|
||||
!(isNullable() && makeNotNull().unboxInlineClass().isNullable()) &&
|
||||
makeNotNull().unboxInlineClass().isPrimitiveType()
|
||||
|
||||
@@ -105,7 +105,7 @@ import static org.jetbrains.kotlin.lexer.KtTokens.*;
|
||||
IElementType tt = tt();
|
||||
if (recoverySet == null ||
|
||||
recoverySet.contains(tt) ||
|
||||
tt == LBRACE || tt == RBRACE || tt == LONG_TEMPLATE_ENTRY_END ||
|
||||
tt == LBRACE || tt == RBRACE ||
|
||||
(recoverySet.contains(EOL_OR_SEMICOLON) && (eof() || tt == SEMICOLON || myBuilder.newlineBeforeCurrentToken()))) {
|
||||
error(message);
|
||||
}
|
||||
|
||||
@@ -682,7 +682,7 @@ public class KotlinExpressionParsing extends AbstractKotlinParsing {
|
||||
else if (!parseLiteralConstant()) {
|
||||
ok = false;
|
||||
// TODO: better recovery if FIRST(element) did not match
|
||||
errorWithRecovery("Expecting an element", EXPRESSION_FOLLOW);
|
||||
errorWithRecovery("Expecting an element", TokenSet.orSet(EXPRESSION_FOLLOW, TokenSet.create(LONG_TEMPLATE_ENTRY_END)));
|
||||
}
|
||||
|
||||
return ok;
|
||||
|
||||
@@ -17,6 +17,8 @@
|
||||
package org.jetbrains.kotlin.psi;
|
||||
|
||||
import com.intellij.lang.ASTNode;
|
||||
import com.intellij.navigation.ItemPresentation;
|
||||
import com.intellij.navigation.ItemPresentationProviders;
|
||||
import com.intellij.psi.PsiElement;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
@@ -152,4 +154,9 @@ public class KtAnnotationEntry extends KtElementImplStub<KotlinAnnotationEntrySt
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ItemPresentation getPresentation() {
|
||||
return ItemPresentationProviders.getItemPresentation(this);
|
||||
}
|
||||
}
|
||||
|
||||
1
compiler/testData/cli/js-dce/dceHelp.out
vendored
1
compiler/testData/cli/js-dce/dceHelp.out
vendored
@@ -10,5 +10,6 @@ where possible options include:
|
||||
-nowarn Generate no warnings
|
||||
-verbose Enable verbose logging output
|
||||
-version Display compiler version
|
||||
-J<option> Pass an option directly to JVM
|
||||
@<argfile> Read compiler arguments and file paths from the given file
|
||||
OK
|
||||
|
||||
1
compiler/testData/cli/js/jsHelp.out
vendored
1
compiler/testData/cli/js/jsHelp.out
vendored
@@ -32,6 +32,7 @@ where possible options include:
|
||||
-nowarn Generate no warnings
|
||||
-verbose Enable verbose logging output
|
||||
-version Display compiler version
|
||||
-J<option> Pass an option directly to JVM
|
||||
@<argfile> Read compiler arguments and file paths from the given file
|
||||
|
||||
For details, see https://kotl.in/cli
|
||||
|
||||
2
compiler/testData/cli/jvm/firError.out
vendored
2
compiler/testData/cli/jvm/firError.out
vendored
@@ -1,7 +1,7 @@
|
||||
warning: ATTENTION!
|
||||
This build uses in-dev FIR:
|
||||
-Xuse-fir
|
||||
compiler/testData/cli/jvm/firError.kt:5:13: error: x must be initialized before access
|
||||
compiler/testData/cli/jvm/firError.kt:5:13: error: variable 'x' must be initialized
|
||||
println(x)
|
||||
^
|
||||
compiler/testData/cli/jvm/firError.kt:10:16: error: public subclass exposes its private-in-file supertype 'Private'
|
||||
|
||||
1
compiler/testData/cli/jvm/help.out
vendored
1
compiler/testData/cli/jvm/help.out
vendored
@@ -30,6 +30,7 @@ where possible options include:
|
||||
-nowarn Generate no warnings
|
||||
-verbose Enable verbose logging output
|
||||
-version Display compiler version
|
||||
-J<option> Pass an option directly to JVM
|
||||
@<argfile> Read compiler arguments and file paths from the given file
|
||||
|
||||
For details, see https://kotl.in/cli
|
||||
|
||||
79
compiler/testData/codegen/asmLike/typeAnnotations/classTypeParameter.kt
vendored
Normal file
79
compiler/testData/codegen/asmLike/typeAnnotations/classTypeParameter.kt
vendored
Normal file
@@ -0,0 +1,79 @@
|
||||
// IGNORE_BACKEND: JVM
|
||||
// KOTLIN_CONFIGURATION_FLAGS: +JVM.EMIT_JVM_TYPE_ANNOTATIONS
|
||||
// RENDER_ANNOTATIONS
|
||||
// TARGET_BACKEND: JVM
|
||||
// JVM_TARGET: 1.8
|
||||
package foo
|
||||
|
||||
@Target(AnnotationTarget.TYPE)
|
||||
annotation class TypeAnn(val name: String)
|
||||
|
||||
@Target( AnnotationTarget.TYPE_PARAMETER)
|
||||
annotation class TypeParameterAnn(val name: String)
|
||||
|
||||
@Target(AnnotationTarget.TYPE_PARAMETER)
|
||||
@Retention(AnnotationRetention.BINARY)
|
||||
annotation class TypeParameterAnnBinary
|
||||
|
||||
@Target(AnnotationTarget.TYPE_PARAMETER)
|
||||
@Retention(AnnotationRetention.SOURCE)
|
||||
annotation class TypeParameterAnnSource
|
||||
|
||||
interface SimpleInterface
|
||||
interface SimpleInterface2
|
||||
open class SimpleClass
|
||||
|
||||
interface GenericInterface<Z>
|
||||
open class GenericClass<Z>
|
||||
|
||||
@Suppress("UNSUPPORTED")
|
||||
class Simple<@TypeParameterAnn("T") @TypeParameterAnnBinary @TypeParameterAnnSource T> {
|
||||
fun test(p: T) : T {
|
||||
return p
|
||||
}
|
||||
}
|
||||
|
||||
class TypeBound<Y, T: @foo.TypeAnn("Y") Y> {
|
||||
fun test(p: T) : T {
|
||||
return p
|
||||
}
|
||||
}
|
||||
|
||||
class InterfaceBound<T: @foo.TypeAnn("Interface") SimpleInterface> {
|
||||
fun test(p: T) : T {
|
||||
return p
|
||||
}
|
||||
}
|
||||
|
||||
class ClassBound<T: @foo.TypeAnn("Class") SimpleClass> {
|
||||
fun test(p: T) : T {
|
||||
return p
|
||||
}
|
||||
}
|
||||
|
||||
class ClassBoundGeneric<T: @foo.TypeAnn("Class") GenericClass<@foo.TypeAnn("SimpleClass") SimpleClass>> {
|
||||
fun test(p: T) : T {
|
||||
return p
|
||||
}
|
||||
}
|
||||
|
||||
class InterfaceBoundGeneric<T: @foo.TypeAnn("Interface") GenericInterface<@foo.TypeAnn("SimpleInterface") SimpleInterface>> {
|
||||
fun test(p: T) : T {
|
||||
return p
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
class ClassInterfaceBound<T: @foo.TypeAnn("Class") SimpleClass> where T : @foo.TypeAnn("Interface") SimpleInterface, T : @foo.TypeAnn("Interface2") SimpleInterface2 {
|
||||
fun test(p: T) : T {
|
||||
return p
|
||||
}
|
||||
}
|
||||
|
||||
class InterfaceClassBound<T: @foo.TypeAnn("Interface") SimpleInterface > where T : @foo.TypeAnn("Class") SimpleClass, T : @foo.TypeAnn("Interface2") SimpleInterface2 {
|
||||
fun test(p: T) : T {
|
||||
return p
|
||||
}
|
||||
}
|
||||
|
||||
133
compiler/testData/codegen/asmLike/typeAnnotations/classTypeParameter.txt
vendored
Normal file
133
compiler/testData/codegen/asmLike/typeAnnotations/classTypeParameter.txt
vendored
Normal file
@@ -0,0 +1,133 @@
|
||||
<T:Lfoo/SimpleClass;>Ljava/lang/Object;
|
||||
public final class foo/ClassBound : java/lang/Object {
|
||||
@Lfoo/TypeAnn;([name="Class"]) : CLASS_TYPE_PARAMETER_BOUND 0, 0, null
|
||||
|
||||
public void <init>()
|
||||
|
||||
(TT;)TT;
|
||||
public final foo.SimpleClass test(foo.SimpleClass p)
|
||||
@Lorg/jetbrains/annotations/NotNull;([]) // invisible
|
||||
@Lorg/jetbrains/annotations/NotNull;([]) // invisible, parameter 0
|
||||
}
|
||||
|
||||
<T:Lfoo/GenericClass<Lfoo/SimpleClass;>;>Ljava/lang/Object;
|
||||
public final class foo/ClassBoundGeneric : java/lang/Object {
|
||||
@Lfoo/TypeAnn;([name="Class"]) : CLASS_TYPE_PARAMETER_BOUND 0, 0, null
|
||||
@Lfoo/TypeAnn;([name="SimpleClass"]) : CLASS_TYPE_PARAMETER_BOUND 0, 0, 0;
|
||||
|
||||
public void <init>()
|
||||
|
||||
(TT;)TT;
|
||||
public final foo.GenericClass test(foo.GenericClass p)
|
||||
@Lorg/jetbrains/annotations/NotNull;([]) // invisible
|
||||
@Lorg/jetbrains/annotations/NotNull;([]) // invisible, parameter 0
|
||||
}
|
||||
|
||||
<T:Lfoo/SimpleClass;:Lfoo/SimpleInterface;:Lfoo/SimpleInterface2;>Ljava/lang/Object;
|
||||
public final class foo/ClassInterfaceBound : java/lang/Object {
|
||||
@Lfoo/TypeAnn;([name="Class"]) : CLASS_TYPE_PARAMETER_BOUND 0, 0, null
|
||||
@Lfoo/TypeAnn;([name="Interface"]) : CLASS_TYPE_PARAMETER_BOUND 0, 1, null
|
||||
@Lfoo/TypeAnn;([name="Interface2"]) : CLASS_TYPE_PARAMETER_BOUND 0, 2, null
|
||||
|
||||
public void <init>()
|
||||
|
||||
(TT;)TT;
|
||||
public final foo.SimpleClass test(foo.SimpleClass p)
|
||||
@Lorg/jetbrains/annotations/NotNull;([]) // invisible
|
||||
@Lorg/jetbrains/annotations/NotNull;([]) // invisible, parameter 0
|
||||
}
|
||||
|
||||
<Z:Ljava/lang/Object;>Ljava/lang/Object;
|
||||
public class foo/GenericClass : java/lang/Object {
|
||||
public void <init>()
|
||||
}
|
||||
|
||||
<Z:Ljava/lang/Object;>Ljava/lang/Object;
|
||||
public abstract interface foo/GenericInterface : java/lang/Object {
|
||||
|
||||
}
|
||||
|
||||
<T::Lfoo/SimpleInterface;>Ljava/lang/Object;
|
||||
public final class foo/InterfaceBound : java/lang/Object {
|
||||
@Lfoo/TypeAnn;([name="Interface"]) : CLASS_TYPE_PARAMETER_BOUND 0, 1, null
|
||||
|
||||
public void <init>()
|
||||
|
||||
(TT;)TT;
|
||||
public final foo.SimpleInterface test(foo.SimpleInterface p)
|
||||
@Lorg/jetbrains/annotations/NotNull;([]) // invisible
|
||||
@Lorg/jetbrains/annotations/NotNull;([]) // invisible, parameter 0
|
||||
}
|
||||
|
||||
<T::Lfoo/GenericInterface<Lfoo/SimpleInterface;>;>Ljava/lang/Object;
|
||||
public final class foo/InterfaceBoundGeneric : java/lang/Object {
|
||||
@Lfoo/TypeAnn;([name="Interface"]) : CLASS_TYPE_PARAMETER_BOUND 0, 1, null
|
||||
@Lfoo/TypeAnn;([name="SimpleInterface"]) : CLASS_TYPE_PARAMETER_BOUND 0, 1, 0;
|
||||
|
||||
public void <init>()
|
||||
|
||||
(TT;)TT;
|
||||
public final foo.GenericInterface test(foo.GenericInterface p)
|
||||
@Lorg/jetbrains/annotations/NotNull;([]) // invisible
|
||||
@Lorg/jetbrains/annotations/NotNull;([]) // invisible, parameter 0
|
||||
}
|
||||
|
||||
<T:Lfoo/SimpleClass;:Lfoo/SimpleInterface;:Lfoo/SimpleInterface2;>Ljava/lang/Object;
|
||||
public final class foo/InterfaceClassBound : java/lang/Object {
|
||||
@Lfoo/TypeAnn;([name="Interface"]) : CLASS_TYPE_PARAMETER_BOUND 0, 1, null
|
||||
@Lfoo/TypeAnn;([name="Class"]) : CLASS_TYPE_PARAMETER_BOUND 0, 0, null
|
||||
@Lfoo/TypeAnn;([name="Interface2"]) : CLASS_TYPE_PARAMETER_BOUND 0, 2, null
|
||||
|
||||
public void <init>()
|
||||
|
||||
(TT;)TT;
|
||||
public final foo.SimpleClass test(foo.SimpleClass p)
|
||||
@Lorg/jetbrains/annotations/NotNull;([]) // invisible
|
||||
@Lorg/jetbrains/annotations/NotNull;([]) // invisible, parameter 0
|
||||
}
|
||||
|
||||
<T:Ljava/lang/Object;>Ljava/lang/Object;
|
||||
public final class foo/Simple : java/lang/Object {
|
||||
public void <init>()
|
||||
|
||||
(TT;)TT;
|
||||
public final java.lang.Object test(java.lang.Object p)
|
||||
}
|
||||
|
||||
public class foo/SimpleClass : java/lang/Object {
|
||||
public void <init>()
|
||||
}
|
||||
|
||||
public abstract interface foo/SimpleInterface : java/lang/Object {
|
||||
|
||||
}
|
||||
|
||||
public abstract interface foo/SimpleInterface2 : java/lang/Object {
|
||||
|
||||
}
|
||||
|
||||
public abstract interface foo/TypeAnn : java/lang/Object, java/lang/annotation/Annotation {
|
||||
public abstract java.lang.String name()
|
||||
}
|
||||
|
||||
<Y:Ljava/lang/Object;T::TY;>Ljava/lang/Object;
|
||||
public final class foo/TypeBound : java/lang/Object {
|
||||
@Lfoo/TypeAnn;([name="Y"]) : CLASS_TYPE_PARAMETER_BOUND 1, 0, null
|
||||
|
||||
public void <init>()
|
||||
|
||||
(TT;)TT;
|
||||
public final java.lang.Object test(java.lang.Object p)
|
||||
}
|
||||
|
||||
public abstract interface foo/TypeParameterAnn : java/lang/Object, java/lang/annotation/Annotation {
|
||||
public abstract java.lang.String name()
|
||||
}
|
||||
|
||||
public abstract interface foo/TypeParameterAnnBinary : java/lang/Object, java/lang/annotation/Annotation {
|
||||
|
||||
}
|
||||
|
||||
public abstract interface foo/TypeParameterAnnSource : java/lang/Object, java/lang/annotation/Annotation {
|
||||
|
||||
}
|
||||
@@ -1,5 +1,5 @@
|
||||
// KOTLIN_CONFIGURATION_FLAGS: +JVM.EMIT_JVM_TYPE_ANNOTATIONS
|
||||
// TYPE_ANNOTATIONS
|
||||
// RENDER_ANNOTATIONS
|
||||
// TARGET_BACKEND: JVM
|
||||
// JVM_TARGET: 1.8
|
||||
package foo
|
||||
|
||||
@@ -14,6 +14,7 @@ public abstract interface foo/Ann4 : java/lang/Object, java/lang/annotation/Anno
|
||||
|
||||
}
|
||||
|
||||
<T:Ljava/lang/Object;>Ljava/lang/Object;
|
||||
public final class foo/Bar : java/lang/Object {
|
||||
public void <init>()
|
||||
}
|
||||
@@ -21,40 +22,55 @@ public final class foo/Bar : java/lang/Object {
|
||||
public final class foo/Kotlin : java/lang/Object {
|
||||
public void <init>()
|
||||
|
||||
(Lfoo/Bar<Ljava/lang/String;>;)V
|
||||
public final void foo(foo.Bar s)
|
||||
@Lfoo/Ann;([]) : METHOD_FORMAL_PARAMETER 0, null
|
||||
@Lfoo/Ann2;([]) : METHOD_FORMAL_PARAMETER 0, 0;
|
||||
@Lorg/jetbrains/annotations/NotNull;([]) // invisible, parameter 0
|
||||
|
||||
()Lfoo/Bar<Ljava/lang/String;>;
|
||||
public final foo.Bar foo()
|
||||
@Lorg/jetbrains/annotations/Nullable;([]) // invisible
|
||||
@Lfoo/Ann;([]) : METHOD_RETURN, null
|
||||
@Lfoo/Ann2;([]) : METHOD_RETURN, 0;
|
||||
|
||||
<T:Ljava/lang/Object;>(TT;)V
|
||||
public final void foo(java.lang.Object s)
|
||||
@Lfoo/Ann;([]) : METHOD_FORMAL_PARAMETER 0, null
|
||||
|
||||
([Lfoo/Bar<Ljava/lang/String;>;)V
|
||||
public final void fooArray(foo.Bar[] s)
|
||||
@Lfoo/Ann;([]) : METHOD_FORMAL_PARAMETER 0, null
|
||||
@Lfoo/Ann2;([]) : METHOD_FORMAL_PARAMETER 0, [
|
||||
@Lfoo/Ann3;([]) : METHOD_FORMAL_PARAMETER 0, [0;
|
||||
@Lorg/jetbrains/annotations/NotNull;([]) // invisible, parameter 0
|
||||
|
||||
()[Lfoo/Bar<Ljava/lang/String;>;
|
||||
public final foo.Bar[] fooArray()
|
||||
@Lorg/jetbrains/annotations/Nullable;([]) // invisible
|
||||
@Lfoo/Ann;([]) : METHOD_RETURN, null
|
||||
@Lfoo/Ann2;([]) : METHOD_RETURN, [
|
||||
@Lfoo/Ann3;([]) : METHOD_RETURN, [0;
|
||||
|
||||
([[Lfoo/Bar<Ljava/lang/String;>;)V
|
||||
public final void fooArrayArray(foo.Bar[][] s)
|
||||
@Lfoo/Ann;([]) : METHOD_FORMAL_PARAMETER 0, null
|
||||
@Lfoo/Ann2;([]) : METHOD_FORMAL_PARAMETER 0, [
|
||||
@Lfoo/Ann3;([]) : METHOD_FORMAL_PARAMETER 0, [[
|
||||
@Lfoo/Ann4;([]) : METHOD_FORMAL_PARAMETER 0, [[0;
|
||||
@Lorg/jetbrains/annotations/NotNull;([]) // invisible, parameter 0
|
||||
|
||||
()[[Lfoo/Bar<Ljava/lang/String;>;
|
||||
public final foo.Bar[][] fooArrayArray()
|
||||
@Lorg/jetbrains/annotations/Nullable;([]) // invisible
|
||||
@Lfoo/Ann;([]) : METHOD_RETURN, null
|
||||
@Lfoo/Ann2;([]) : METHOD_RETURN, [
|
||||
@Lfoo/Ann3;([]) : METHOD_RETURN, [[
|
||||
@Lfoo/Ann4;([]) : METHOD_RETURN, [[0;
|
||||
|
||||
<T:Ljava/lang/Object;>(Lfoo/Bar<TT;>;)V
|
||||
public final void fooGeneric(foo.Bar s)
|
||||
@Lfoo/Ann;([]) : METHOD_FORMAL_PARAMETER 0, null
|
||||
@Lfoo/Ann2;([]) : METHOD_FORMAL_PARAMETER 0, 0;
|
||||
}
|
||||
@Lorg/jetbrains/annotations/NotNull;([]) // invisible, parameter 0
|
||||
}
|
||||
@@ -1,5 +1,5 @@
|
||||
// KOTLIN_CONFIGURATION_FLAGS: +JVM.EMIT_JVM_TYPE_ANNOTATIONS
|
||||
// TYPE_ANNOTATIONS
|
||||
// RENDER_ANNOTATIONS
|
||||
// TARGET_BACKEND: JVM
|
||||
// JVM_TARGET: 1.8
|
||||
package foo
|
||||
|
||||
@@ -2,12 +2,15 @@ public final class foo/Kotlin$foo$1 : java/lang/Object {
|
||||
void <init>()
|
||||
|
||||
public final foo.Kotlin foo()
|
||||
@Lorg/jetbrains/annotations/NotNull;([]) // invisible
|
||||
}
|
||||
|
||||
public final class foo/Kotlin : java/lang/Object {
|
||||
public void <init>(java.lang.String s, java.lang.String p)
|
||||
@Lfoo/TypeAnn;([name="1"]) : METHOD_FORMAL_PARAMETER 0, null
|
||||
@Lfoo/TypeAnn;([name="123"]) : METHOD_FORMAL_PARAMETER 1, null
|
||||
@Lorg/jetbrains/annotations/NotNull;([]) // invisible, parameter 0
|
||||
@Lorg/jetbrains/annotations/NotNull;([]) // invisible, parameter 1
|
||||
|
||||
private void <init>(java.lang.String s)
|
||||
@Lfoo/TypeAnn;([name="private"]) : METHOD_FORMAL_PARAMETER 0, null
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
// KOTLIN_CONFIGURATION_FLAGS: +JVM.EMIT_JVM_TYPE_ANNOTATIONS
|
||||
// TYPE_ANNOTATIONS
|
||||
// RENDER_ANNOTATIONS
|
||||
// TARGET_BACKEND: JVM
|
||||
// JVM_TARGET: 1.8
|
||||
package foo
|
||||
|
||||
@@ -2,9 +2,11 @@ public final class foo/Kotlin : java/lang/Object {
|
||||
public void <init>()
|
||||
|
||||
public final java.lang.Object foo(java.lang.String s, int x)
|
||||
@Lorg/jetbrains/annotations/Nullable;([]) // invisible
|
||||
@Lfoo/TypeAnn;([name="return"]) : METHOD_RETURN, null
|
||||
@Lfoo/TypeAnn;([name="1"]) : METHOD_FORMAL_PARAMETER 0, null
|
||||
@Lfoo/TypeAnn;([name="2"]) : METHOD_FORMAL_PARAMETER 1, null
|
||||
@Lorg/jetbrains/annotations/NotNull;([]) // invisible, parameter 0
|
||||
|
||||
public static java.lang.Object foo$default(foo.Kotlin p0, java.lang.String p1, int p2, int p3, java.lang.Object p4)
|
||||
}
|
||||
|
||||
23
compiler/testData/codegen/asmLike/typeAnnotations/dontEmit.kt
vendored
Normal file
23
compiler/testData/codegen/asmLike/typeAnnotations/dontEmit.kt
vendored
Normal file
@@ -0,0 +1,23 @@
|
||||
// KOTLIN_CONFIGURATION_FLAGS: -JVM.EMIT_JVM_TYPE_ANNOTATIONS
|
||||
// RENDER_ANNOTATIONS
|
||||
// TARGET_BACKEND: JVM
|
||||
// JVM_TARGET: 1.8
|
||||
package foo
|
||||
|
||||
@Target(AnnotationTarget.TYPE)
|
||||
annotation class TypeAnn(val name: String)
|
||||
|
||||
@Target(AnnotationTarget.TYPE_PARAMETER)
|
||||
annotation class TypeParameterAnn(val name: String)
|
||||
|
||||
|
||||
class Kotlin {
|
||||
|
||||
fun foo(s: @TypeAnn("1") String) {
|
||||
}
|
||||
|
||||
fun <T : @TypeAnn("Ant") Any> bar(p: T): T {
|
||||
return p
|
||||
}
|
||||
|
||||
}
|
||||
19
compiler/testData/codegen/asmLike/typeAnnotations/dontEmit.txt
vendored
Normal file
19
compiler/testData/codegen/asmLike/typeAnnotations/dontEmit.txt
vendored
Normal file
@@ -0,0 +1,19 @@
|
||||
public final class foo/Kotlin : java/lang/Object {
|
||||
public void <init>()
|
||||
|
||||
<T:Ljava/lang/Object;>(TT;)TT;
|
||||
public final java.lang.Object bar(java.lang.Object p)
|
||||
@Lorg/jetbrains/annotations/NotNull;([]) // invisible
|
||||
@Lorg/jetbrains/annotations/NotNull;([]) // invisible, parameter 0
|
||||
|
||||
public final void foo(java.lang.String s)
|
||||
@Lorg/jetbrains/annotations/NotNull;([]) // invisible, parameter 0
|
||||
}
|
||||
|
||||
public abstract interface foo/TypeAnn : java/lang/Object, java/lang/annotation/Annotation {
|
||||
public abstract java.lang.String name()
|
||||
}
|
||||
|
||||
public abstract interface foo/TypeParameterAnn : java/lang/Object, java/lang/annotation/Annotation {
|
||||
public abstract java.lang.String name()
|
||||
}
|
||||
@@ -1,6 +1,6 @@
|
||||
// IGNORE_BACKEND: JVM_IR
|
||||
// KOTLIN_CONFIGURATION_FLAGS: +JVM.EMIT_JVM_TYPE_ANNOTATIONS
|
||||
// TYPE_ANNOTATIONS
|
||||
// RENDER_ANNOTATIONS
|
||||
// TARGET_BACKEND: JVM
|
||||
// JVM_TARGET: 1.8
|
||||
package foo
|
||||
|
||||
@@ -1,9 +1,11 @@
|
||||
final class foo/Kotlin$A : foo/Kotlin {
|
||||
()V
|
||||
void <init>(java.lang.String $enum$name, int $enum$ordinal)
|
||||
|
||||
public final void foo()
|
||||
}
|
||||
|
||||
Ljava/lang/Enum<Lfoo/Kotlin;>;
|
||||
public class foo/Kotlin : java/lang/Enum {
|
||||
private final static foo.Kotlin[] $VALUES
|
||||
|
||||
@@ -11,6 +13,7 @@ public class foo/Kotlin : java/lang/Enum {
|
||||
|
||||
static void <clinit>()
|
||||
|
||||
(Ljava/lang/String;)V
|
||||
private void <init>(java.lang.String $enum$name, int $enum$ordinal, java.lang.String s)
|
||||
@Lfoo/TypeAnn;([]) : METHOD_FORMAL_PARAMETER 0, null
|
||||
|
||||
|
||||
16
compiler/testData/codegen/asmLike/typeAnnotations/enumClassConstructor_ir.kt
vendored
Normal file
16
compiler/testData/codegen/asmLike/typeAnnotations/enumClassConstructor_ir.kt
vendored
Normal file
@@ -0,0 +1,16 @@
|
||||
// IGNORE_BACKEND: JVM
|
||||
// KOTLIN_CONFIGURATION_FLAGS: +JVM.EMIT_JVM_TYPE_ANNOTATIONS
|
||||
// RENDER_ANNOTATIONS
|
||||
// TARGET_BACKEND: JVM
|
||||
// JVM_TARGET: 1.8
|
||||
package foo
|
||||
|
||||
|
||||
@Target(AnnotationTarget.TYPE)
|
||||
annotation class TypeAnn
|
||||
|
||||
enum class Kotlin (s: @TypeAnn String) {
|
||||
A("123") {
|
||||
fun foo() {}
|
||||
};
|
||||
}
|
||||
31
compiler/testData/codegen/asmLike/typeAnnotations/enumClassConstructor_ir.txt
vendored
Normal file
31
compiler/testData/codegen/asmLike/typeAnnotations/enumClassConstructor_ir.txt
vendored
Normal file
@@ -0,0 +1,31 @@
|
||||
final class foo/Kotlin$A : foo/Kotlin {
|
||||
()V
|
||||
void <init>(java.lang.String $enum$name, int $enum$ordinal)
|
||||
|
||||
public final void foo()
|
||||
}
|
||||
|
||||
Ljava/lang/Enum<Lfoo/Kotlin;>;
|
||||
public class foo/Kotlin : java/lang/Enum {
|
||||
private final static foo.Kotlin[] $VALUES
|
||||
|
||||
public final static foo.Kotlin A
|
||||
|
||||
private final static foo.Kotlin[] $values()
|
||||
|
||||
static void <clinit>()
|
||||
|
||||
(Ljava/lang/String;)V
|
||||
private void <init>(java.lang.String $enum$name, int $enum$ordinal, java.lang.String s)
|
||||
@Lfoo/TypeAnn;([]) : METHOD_FORMAL_PARAMETER 0, null
|
||||
|
||||
public void <init>(java.lang.String $enum$name, int $enum$ordinal, java.lang.String s, kotlin.jvm.internal.DefaultConstructorMarker $constructor_marker)
|
||||
|
||||
public static foo.Kotlin valueOf(java.lang.String value)
|
||||
|
||||
public static foo.Kotlin[] values()
|
||||
}
|
||||
|
||||
public abstract interface foo/TypeAnn : java/lang/Object, java/lang/annotation/Annotation {
|
||||
|
||||
}
|
||||
@@ -1,5 +1,5 @@
|
||||
// KOTLIN_CONFIGURATION_FLAGS: +JVM.EMIT_JVM_TYPE_ANNOTATIONS
|
||||
// TYPE_ANNOTATIONS
|
||||
// RENDER_ANNOTATIONS
|
||||
// TARGET_BACKEND: JVM
|
||||
// JVM_TARGET: 1.8
|
||||
package foo
|
||||
|
||||
@@ -4,6 +4,8 @@ public final class foo/Kotlin : java/lang/Object {
|
||||
public final void foo2(java.lang.String $this$foo2, java.lang.String s)
|
||||
@Lfoo/TypeAnn;([name="ext"]) : METHOD_FORMAL_PARAMETER 0, null
|
||||
@Lfoo/TypeAnn;([name="param"]) : METHOD_FORMAL_PARAMETER 1, null
|
||||
@Lorg/jetbrains/annotations/NotNull;([]) // invisible, parameter 0
|
||||
@Lorg/jetbrains/annotations/NotNull;([]) // invisible, parameter 1
|
||||
}
|
||||
|
||||
public abstract interface foo/TypeAnn : java/lang/Object, java/lang/annotation/Annotation {
|
||||
|
||||
62
compiler/testData/codegen/asmLike/typeAnnotations/functionTypeParameter.kt
vendored
Normal file
62
compiler/testData/codegen/asmLike/typeAnnotations/functionTypeParameter.kt
vendored
Normal file
@@ -0,0 +1,62 @@
|
||||
// IGNORE_BACKEND: JVM
|
||||
// KOTLIN_CONFIGURATION_FLAGS: +JVM.EMIT_JVM_TYPE_ANNOTATIONS
|
||||
// RENDER_ANNOTATIONS
|
||||
// TARGET_BACKEND: JVM
|
||||
// JVM_TARGET: 1.8
|
||||
package foo
|
||||
|
||||
@Target(AnnotationTarget.TYPE)
|
||||
annotation class TypeAnn(val name: String)
|
||||
|
||||
@Target(AnnotationTarget.TYPE)
|
||||
annotation class ClassTypeAnn(val name: String)
|
||||
|
||||
@Target(AnnotationTarget.TYPE)
|
||||
@Retention(AnnotationRetention.BINARY)
|
||||
annotation class TypeAnnBinary
|
||||
|
||||
@Target(AnnotationTarget.TYPE)
|
||||
@Retention(AnnotationRetention.SOURCE)
|
||||
annotation class TypeAnnSource
|
||||
|
||||
@Target( AnnotationTarget.TYPE_PARAMETER)
|
||||
annotation class TypeParameterAnn(val name: String)
|
||||
|
||||
@Target(AnnotationTarget.TYPE_PARAMETER)
|
||||
@Retention(AnnotationRetention.BINARY)
|
||||
annotation class TypeParameterAnnBinary
|
||||
|
||||
@Target(AnnotationTarget.TYPE_PARAMETER)
|
||||
@Retention(AnnotationRetention.SOURCE)
|
||||
annotation class TypeParameterAnnSource
|
||||
|
||||
interface Generic<Z>
|
||||
class GenericClass<Z>
|
||||
class B<Y>
|
||||
|
||||
class Kotlin {
|
||||
|
||||
fun <@TypeParameterAnn("TP1") @TypeParameterAnnBinary @TypeParameterAnnSource T, @TypeParameterAnn("TP2") @TypeParameterAnnBinary @TypeParameterAnnSource T2> typeParameter() {
|
||||
}
|
||||
|
||||
fun <@TypeParameterAnn("TP") T> genericParameterAndReturn(s: @TypeAnn("1") @TypeAnnBinary @TypeAnnSource T): @TypeAnn("2") @TypeAnnBinary @TypeAnnSource T {
|
||||
return s
|
||||
}
|
||||
|
||||
fun <@TypeParameterAnn("Y") Y, @TypeParameterAnn("T") T: @TypeAnn("Generic") @TypeAnnBinary @TypeAnnSource Generic<@TypeAnn("Generic Argument") @TypeAnnBinary @TypeAnnSource Y>> genericInterfaceBound() {
|
||||
}
|
||||
|
||||
fun <@TypeParameterAnn("Y") Y, @TypeParameterAnn("T") T: @TypeAnn("Generic") @TypeAnnBinary @TypeAnnSource GenericClass<@TypeAnn("Generic Argument") @TypeAnnBinary @TypeAnnSource Y>> genericClassBound() {
|
||||
}
|
||||
|
||||
fun <@TypeParameterAnn("Y") Y, @TypeParameterAnn("T") T: @TypeAnn("Generic") Generic<@TypeAnn("Generic Argument") Y>> whereClause() where T : @ClassTypeAnn("Any") Any {
|
||||
|
||||
}
|
||||
|
||||
fun <@TypeParameterAnn("Y") Y, @TypeParameterAnn("T") T: @TypeAnn("Y as Bound") @TypeAnnBinary @TypeAnnSource Y> typeParameterTypeParameterBound() {
|
||||
}
|
||||
|
||||
// Second annotation is missed: see KT-46483, remove this test after prohibition of such cases
|
||||
fun <@TypeParameterAnn("T") T: Any> whereClauseWithAnnotation() where @TypeParameterAnn("Additional") T : Generic<String> {
|
||||
}
|
||||
}
|
||||
98
compiler/testData/codegen/asmLike/typeAnnotations/functionTypeParameter.txt
vendored
Normal file
98
compiler/testData/codegen/asmLike/typeAnnotations/functionTypeParameter.txt
vendored
Normal file
@@ -0,0 +1,98 @@
|
||||
<Y:Ljava/lang/Object;>Ljava/lang/Object;
|
||||
public final class foo/B : java/lang/Object {
|
||||
public void <init>()
|
||||
}
|
||||
|
||||
public abstract interface foo/ClassTypeAnn : java/lang/Object, java/lang/annotation/Annotation {
|
||||
public abstract java.lang.String name()
|
||||
}
|
||||
|
||||
<Z:Ljava/lang/Object;>Ljava/lang/Object;
|
||||
public abstract interface foo/Generic : java/lang/Object {
|
||||
|
||||
}
|
||||
|
||||
<Z:Ljava/lang/Object;>Ljava/lang/Object;
|
||||
public final class foo/GenericClass : java/lang/Object {
|
||||
public void <init>()
|
||||
}
|
||||
|
||||
public final class foo/Kotlin : java/lang/Object {
|
||||
public void <init>()
|
||||
|
||||
<Y:Ljava/lang/Object;T:Lfoo/GenericClass<TY;>;>()V
|
||||
public final void genericClassBound()
|
||||
@Lfoo/TypeParameterAnn;([name="Y"]) : METHOD_TYPE_PARAMETER 0, null
|
||||
@Lfoo/TypeParameterAnn;([name="T"]) : METHOD_TYPE_PARAMETER 1, null
|
||||
@Lfoo/TypeAnn;([name="Generic"]) : METHOD_TYPE_PARAMETER_BOUND 1, 0, null
|
||||
@Lfoo/TypeAnn;([name="Generic Argument"]) : METHOD_TYPE_PARAMETER_BOUND 1, 0, 0;
|
||||
@Lfoo/TypeAnnBinary;([]) : METHOD_TYPE_PARAMETER_BOUND 1, 0, null // invisible
|
||||
@Lfoo/TypeAnnBinary;([]) : METHOD_TYPE_PARAMETER_BOUND 1, 0, 0; // invisible
|
||||
|
||||
<Y:Ljava/lang/Object;T::Lfoo/Generic<TY;>;>()V
|
||||
public final void genericInterfaceBound()
|
||||
@Lfoo/TypeParameterAnn;([name="Y"]) : METHOD_TYPE_PARAMETER 0, null
|
||||
@Lfoo/TypeParameterAnn;([name="T"]) : METHOD_TYPE_PARAMETER 1, null
|
||||
@Lfoo/TypeAnn;([name="Generic"]) : METHOD_TYPE_PARAMETER_BOUND 1, 1, null
|
||||
@Lfoo/TypeAnn;([name="Generic Argument"]) : METHOD_TYPE_PARAMETER_BOUND 1, 1, 0;
|
||||
@Lfoo/TypeAnnBinary;([]) : METHOD_TYPE_PARAMETER_BOUND 1, 1, null // invisible
|
||||
@Lfoo/TypeAnnBinary;([]) : METHOD_TYPE_PARAMETER_BOUND 1, 1, 0; // invisible
|
||||
|
||||
<T:Ljava/lang/Object;>(TT;)TT;
|
||||
public final java.lang.Object genericParameterAndReturn(java.lang.Object s)
|
||||
@Lfoo/TypeAnn;([name="2"]) : METHOD_RETURN, null
|
||||
@Lfoo/TypeParameterAnn;([name="TP"]) : METHOD_TYPE_PARAMETER 0, null
|
||||
@Lfoo/TypeAnn;([name="1"]) : METHOD_FORMAL_PARAMETER 0, null
|
||||
@Lfoo/TypeAnnBinary;([]) : METHOD_RETURN, null // invisible
|
||||
@Lfoo/TypeAnnBinary;([]) : METHOD_FORMAL_PARAMETER 0, null // invisible
|
||||
|
||||
<T:Ljava/lang/Object;T2:Ljava/lang/Object;>()V
|
||||
public final void typeParameter()
|
||||
@Lfoo/TypeParameterAnn;([name="TP1"]) : METHOD_TYPE_PARAMETER 0, null
|
||||
@Lfoo/TypeParameterAnn;([name="TP2"]) : METHOD_TYPE_PARAMETER 1, null
|
||||
@Lfoo/TypeParameterAnnBinary;([]) : METHOD_TYPE_PARAMETER 0, null // invisible
|
||||
@Lfoo/TypeParameterAnnBinary;([]) : METHOD_TYPE_PARAMETER 1, null // invisible
|
||||
|
||||
<Y:Ljava/lang/Object;T::TY;>()V
|
||||
public final void typeParameterTypeParameterBound()
|
||||
@Lfoo/TypeParameterAnn;([name="Y"]) : METHOD_TYPE_PARAMETER 0, null
|
||||
@Lfoo/TypeParameterAnn;([name="T"]) : METHOD_TYPE_PARAMETER 1, null
|
||||
@Lfoo/TypeAnn;([name="Y as Bound"]) : METHOD_TYPE_PARAMETER_BOUND 1, 0, null
|
||||
@Lfoo/TypeAnnBinary;([]) : METHOD_TYPE_PARAMETER_BOUND 1, 0, null // invisible
|
||||
|
||||
<Y:Ljava/lang/Object;T:Ljava/lang/Object;:Lfoo/Generic<TY;>;>()V
|
||||
public final void whereClause()
|
||||
@Lfoo/TypeParameterAnn;([name="Y"]) : METHOD_TYPE_PARAMETER 0, null
|
||||
@Lfoo/TypeParameterAnn;([name="T"]) : METHOD_TYPE_PARAMETER 1, null
|
||||
@Lfoo/TypeAnn;([name="Generic"]) : METHOD_TYPE_PARAMETER_BOUND 1, 1, null
|
||||
@Lfoo/TypeAnn;([name="Generic Argument"]) : METHOD_TYPE_PARAMETER_BOUND 1, 1, 0;
|
||||
@Lfoo/ClassTypeAnn;([name="Any"]) : METHOD_TYPE_PARAMETER_BOUND 1, 0, null
|
||||
|
||||
<T:Ljava/lang/Object;:Lfoo/Generic<Ljava/lang/String;>;>()V
|
||||
public final void whereClauseWithAnnotation()
|
||||
@Lfoo/TypeParameterAnn;([name="T"]) : METHOD_TYPE_PARAMETER 0, null
|
||||
}
|
||||
|
||||
public abstract interface foo/TypeAnn : java/lang/Object, java/lang/annotation/Annotation {
|
||||
public abstract java.lang.String name()
|
||||
}
|
||||
|
||||
public abstract interface foo/TypeAnnBinary : java/lang/Object, java/lang/annotation/Annotation {
|
||||
|
||||
}
|
||||
|
||||
public abstract interface foo/TypeAnnSource : java/lang/Object, java/lang/annotation/Annotation {
|
||||
|
||||
}
|
||||
|
||||
public abstract interface foo/TypeParameterAnn : java/lang/Object, java/lang/annotation/Annotation {
|
||||
public abstract java.lang.String name()
|
||||
}
|
||||
|
||||
public abstract interface foo/TypeParameterAnnBinary : java/lang/Object, java/lang/annotation/Annotation {
|
||||
|
||||
}
|
||||
|
||||
public abstract interface foo/TypeParameterAnnSource : java/lang/Object, java/lang/annotation/Annotation {
|
||||
|
||||
}
|
||||
@@ -1,6 +1,6 @@
|
||||
// IGNORE_BACKEND: JVM_IR
|
||||
// KOTLIN_CONFIGURATION_FLAGS: +JVM.EMIT_JVM_TYPE_ANNOTATIONS
|
||||
// TYPE_ANNOTATIONS
|
||||
// RENDER_ANNOTATIONS
|
||||
// TARGET_BACKEND: JVM
|
||||
// JVM_TARGET: 1.8
|
||||
package foo
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
Lkotlin/jvm/internal/Lambda;Lkotlin/jvm/functions/Function0<Ljava/lang/String;>;
|
||||
final class foo/Kotlin$foo4$1 : kotlin/jvm/internal/Lambda, kotlin/jvm/functions/Function0 {
|
||||
final foo.Kotlin this$0
|
||||
|
||||
@@ -6,6 +7,7 @@ final class foo/Kotlin$foo4$1 : kotlin/jvm/internal/Lambda, kotlin/jvm/functions
|
||||
public java.lang.Object invoke()
|
||||
|
||||
public final java.lang.String invoke()
|
||||
@Lorg/jetbrains/annotations/NotNull;([]) // invisible
|
||||
@Lfoo/TypeAnn;([name="2"]) : METHOD_RETURN, null
|
||||
@Lfoo/TypeAnnBinary;([]) : METHOD_RETURN, null // invisible
|
||||
}
|
||||
@@ -14,14 +16,17 @@ public final class foo/Kotlin : java/lang/Object {
|
||||
public void <init>()
|
||||
|
||||
public final java.lang.String foo2()
|
||||
@Lorg/jetbrains/annotations/NotNull;([]) // invisible
|
||||
@Lfoo/TypeAnn;([name="2"]) : METHOD_RETURN, null
|
||||
@Lfoo/TypeAnnBinary;([]) : METHOD_RETURN, null // invisible
|
||||
|
||||
public final java.lang.String foo3()
|
||||
@Lorg/jetbrains/annotations/NotNull;([]) // invisible
|
||||
@Lfoo/TypeAnn;([name="2"]) : METHOD_RETURN, null
|
||||
@Lfoo/TypeAnnBinary;([]) : METHOD_RETURN, null // invisible
|
||||
|
||||
public final java.lang.String foo4()
|
||||
@Lorg/jetbrains/annotations/NotNull;([]) // invisible
|
||||
@Lfoo/TypeAnn;([name="2"]) : METHOD_RETURN, null
|
||||
@Lfoo/TypeAnnBinary;([]) : METHOD_RETURN, null // invisible
|
||||
}
|
||||
|
||||
29
compiler/testData/codegen/asmLike/typeAnnotations/implicit_ir.kt
vendored
Normal file
29
compiler/testData/codegen/asmLike/typeAnnotations/implicit_ir.kt
vendored
Normal file
@@ -0,0 +1,29 @@
|
||||
// IGNORE_BACKEND: JVM
|
||||
// KOTLIN_CONFIGURATION_FLAGS: +JVM.EMIT_JVM_TYPE_ANNOTATIONS
|
||||
// RENDER_ANNOTATIONS
|
||||
// TARGET_BACKEND: JVM
|
||||
// JVM_TARGET: 1.8
|
||||
package foo
|
||||
|
||||
@Target(AnnotationTarget.TYPE)
|
||||
annotation class TypeAnn(val name: String)
|
||||
|
||||
@Target(AnnotationTarget.TYPE)
|
||||
@Retention(AnnotationRetention.BINARY)
|
||||
annotation class TypeAnnBinary
|
||||
|
||||
@Target(AnnotationTarget.TYPE)
|
||||
@Retention(AnnotationRetention.SOURCE)
|
||||
annotation class TypeAnnSource
|
||||
|
||||
class Kotlin {
|
||||
|
||||
fun foo2(): @TypeAnn("2") @TypeAnnBinary @TypeAnnSource String {
|
||||
return "OK"
|
||||
}
|
||||
|
||||
fun foo3() = foo2()
|
||||
|
||||
fun foo4() = { foo2() }()
|
||||
|
||||
}
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user