mirror of
https://github.com/jlengrand/kotlin.git
synced 2026-05-15 15:53:36 +00:00
Compare commits
133 Commits
build-1.5.
...
java6-Xint
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
d48a7a55c6 | ||
|
|
30639af5a3 | ||
|
|
3add3f091d | ||
|
|
4583e31991 | ||
|
|
f49fe26632 | ||
|
|
73ec5d27a6 | ||
|
|
ac0dc94800 | ||
|
|
789799ac17 | ||
|
|
1f837134bb | ||
|
|
e6e3c9b236 | ||
|
|
5f65b46dfc | ||
|
|
a36135baf1 | ||
|
|
974779e91b | ||
|
|
84334b087c | ||
|
|
62f7e8f71f | ||
|
|
96bd2c54f0 | ||
|
|
931a637bdd | ||
|
|
2165cc8f0d | ||
|
|
e06a60bda5 | ||
|
|
61d5595790 | ||
|
|
dfea915f92 | ||
|
|
81ce1da352 | ||
|
|
bcf47ddc94 | ||
|
|
e790fa8ac9 | ||
|
|
8b3769b88e | ||
|
|
a3ad03d1ad | ||
|
|
b43e5a5e7d | ||
|
|
6a5cf00d7a | ||
|
|
b61277df97 | ||
|
|
229085f3d1 | ||
|
|
f846dd8ea2 | ||
|
|
b1ab597616 | ||
|
|
3293a888ca | ||
|
|
48ef739525 | ||
|
|
825b77cc82 | ||
|
|
b72aa76415 | ||
|
|
a8186d19d6 | ||
|
|
9091ca7b51 | ||
|
|
be097244d4 | ||
|
|
b0d721c9d0 | ||
|
|
290d424111 | ||
|
|
ee45aa6b08 | ||
|
|
886ce055f5 | ||
|
|
5c2753b5d1 | ||
|
|
84c10079e4 | ||
|
|
1ff6dc1275 | ||
|
|
ecbae02f17 | ||
|
|
c6a2d85c87 | ||
|
|
6121d156a1 | ||
|
|
d934c97bf5 | ||
|
|
0b10f255d7 | ||
|
|
c5e6215d27 | ||
|
|
4c943e7cd1 | ||
|
|
8e1c420c9f | ||
|
|
de5dcfcbd8 | ||
|
|
94a94a557d | ||
|
|
89f8c5a651 | ||
|
|
78e20c1098 | ||
|
|
e927764aaf | ||
|
|
15b6a3c88c | ||
|
|
3e892d3184 | ||
|
|
65972fa64c | ||
|
|
1ba6845b59 | ||
|
|
e7275a7cb0 | ||
|
|
e0cc6d44a7 | ||
|
|
67d48d0150 | ||
|
|
96f0b53761 | ||
|
|
af35892007 | ||
|
|
639b7537da | ||
|
|
f5a53c82c5 | ||
|
|
fefc6f9b53 | ||
|
|
d3b1ee42be | ||
|
|
cc571a876a | ||
|
|
242d79ded6 | ||
|
|
b9018e8888 | ||
|
|
5dcaaf47cb | ||
|
|
91e47f1fd7 | ||
|
|
15e978dbd3 | ||
|
|
1dfcec3a93 | ||
|
|
aaffd73feb | ||
|
|
54b9f39b3a | ||
|
|
f4788b479c | ||
|
|
76c15e4444 | ||
|
|
bd7fb56a24 | ||
|
|
4a767c597e | ||
|
|
e942052eb6 | ||
|
|
758eb8f851 | ||
|
|
be22078bd1 | ||
|
|
d8c68aacdd | ||
|
|
fd5169186e | ||
|
|
31ed1ad5d9 | ||
|
|
84bd580f92 | ||
|
|
472ab09511 | ||
|
|
ac222fdb41 | ||
|
|
c0ad1c9b18 | ||
|
|
26cbb020db | ||
|
|
3ff22b67f7 | ||
|
|
d5be258291 | ||
|
|
9fd1cbd2e7 | ||
|
|
d486f7e188 | ||
|
|
0c427555cf | ||
|
|
0f317b01b4 | ||
|
|
0b37b2be6a | ||
|
|
ecde5414dc | ||
|
|
ee927a15a9 | ||
|
|
afbda75581 | ||
|
|
6356b9d501 | ||
|
|
5a11450d77 | ||
|
|
703a353d2e | ||
|
|
c5faf532f5 | ||
|
|
90066d7e50 | ||
|
|
7da47dcde8 | ||
|
|
ac7b459f2a | ||
|
|
5d0461c722 | ||
|
|
26b8e86fe1 | ||
|
|
af12b2fdf0 | ||
|
|
6a7770573c | ||
|
|
8a856e440e | ||
|
|
720edfa6aa | ||
|
|
ebf6ce133b | ||
|
|
3a22761d02 | ||
|
|
b6f35ac44d | ||
|
|
3387615d4a | ||
|
|
cdb04f9cd7 | ||
|
|
af1f57007a | ||
|
|
0b1884c994 | ||
|
|
166f0a597b | ||
|
|
b5f71bacaf | ||
|
|
9d1a6ebb18 | ||
|
|
d12a24418e | ||
|
|
a778cc673e | ||
|
|
157046153f | ||
|
|
01c14a709a |
@@ -234,17 +234,20 @@ private class TranslationResultMap(
|
||||
override fun dumpValue(value: TranslationResultValue): String =
|
||||
"Metadata: ${value.metadata.md5()}, Binary AST: ${value.binaryAst.md5()}, InlineData: ${value.inlineData.md5()}"
|
||||
|
||||
@Synchronized
|
||||
fun put(sourceFile: File, newMetadata: ByteArray, newBinaryAst: ByteArray, newInlineData: ByteArray) {
|
||||
storage[pathConverter.toPath(sourceFile)] =
|
||||
TranslationResultValue(metadata = newMetadata, binaryAst = newBinaryAst, inlineData = newInlineData)
|
||||
}
|
||||
|
||||
@Synchronized
|
||||
operator fun get(sourceFile: File): TranslationResultValue? =
|
||||
storage[pathConverter.toPath(sourceFile)]
|
||||
|
||||
fun keys(): Collection<File> =
|
||||
storage.keys.map { pathConverter.toFile(it) }
|
||||
|
||||
@Synchronized
|
||||
fun remove(sourceFile: File, changesCollector: ChangesCollector) {
|
||||
val path = pathConverter.toPath(sourceFile)
|
||||
val protoBytes = storage[path]!!.metadata
|
||||
@@ -378,6 +381,7 @@ private class InlineFunctionsMap(
|
||||
storageFile: File,
|
||||
private val pathConverter: FileToPathConverter
|
||||
) : BasicStringMap<Map<String, Long>>(storageFile, StringToLongMapExternalizer) {
|
||||
@Synchronized
|
||||
fun process(srcFile: File, newMap: Map<String, Long>, changesCollector: ChangesCollector) {
|
||||
val key = pathConverter.toPath(srcFile)
|
||||
val oldMap = storage[key] ?: emptyMap()
|
||||
@@ -395,6 +399,7 @@ private class InlineFunctionsMap(
|
||||
}
|
||||
}
|
||||
|
||||
@Synchronized
|
||||
fun remove(sourceFile: File) {
|
||||
storage.remove(pathConverter.toPath(sourceFile))
|
||||
}
|
||||
|
||||
@@ -47,10 +47,16 @@ abstract class BasicMap<K : Comparable<K>, V>(
|
||||
storage.flush(memoryCachesOnly)
|
||||
}
|
||||
|
||||
// avoid unsynchronized close
|
||||
fun close() {
|
||||
storage.close()
|
||||
}
|
||||
|
||||
@TestOnly
|
||||
fun closeForTest() {
|
||||
close()
|
||||
}
|
||||
|
||||
@TestOnly
|
||||
fun dump(): String {
|
||||
return with(StringBuilder()) {
|
||||
|
||||
@@ -34,7 +34,6 @@ class CachingLazyStorage<K, V>(
|
||||
) : LazyStorage<K, V> {
|
||||
private var storage: PersistentHashMap<K, V>? = null
|
||||
|
||||
@Synchronized
|
||||
private fun getStorageIfExists(): PersistentHashMap<K, V>? {
|
||||
if (storage != null) return storage
|
||||
|
||||
@@ -46,32 +45,36 @@ class CachingLazyStorage<K, V>(
|
||||
return null
|
||||
}
|
||||
|
||||
@Synchronized
|
||||
private fun getStorageOrCreateNew(): PersistentHashMap<K, V> {
|
||||
if (storage == null) {
|
||||
storage = createMap()
|
||||
}
|
||||
|
||||
return storage!!
|
||||
}
|
||||
|
||||
override val keys: Collection<K>
|
||||
@Synchronized
|
||||
get() = getStorageIfExists()?.allKeysWithExistingMapping ?: listOf()
|
||||
|
||||
@Synchronized
|
||||
override operator fun contains(key: K): Boolean =
|
||||
getStorageIfExists()?.containsMapping(key) ?: false
|
||||
|
||||
@Synchronized
|
||||
override operator fun get(key: K): V? =
|
||||
getStorageIfExists()?.get(key)
|
||||
|
||||
@Synchronized
|
||||
override operator fun set(key: K, value: V) {
|
||||
getStorageOrCreateNew().put(key, value)
|
||||
}
|
||||
|
||||
@Synchronized
|
||||
override fun remove(key: K) {
|
||||
getStorageIfExists()?.remove(key)
|
||||
}
|
||||
|
||||
@Synchronized
|
||||
override fun append(key: K, value: V) {
|
||||
getStorageOrCreateNew().appendData(key, { valueExternalizer.save(it, value) })
|
||||
}
|
||||
@@ -103,7 +106,11 @@ class CachingLazyStorage<K, V>(
|
||||
|
||||
@Synchronized
|
||||
override fun close() {
|
||||
storage?.close()
|
||||
try {
|
||||
storage?.close()
|
||||
} finally {
|
||||
storage = null
|
||||
}
|
||||
}
|
||||
|
||||
private fun createMap(): PersistentHashMap<K, V> = PersistentHashMap(storageFile, keyDescriptor, valueExternalizer)
|
||||
|
||||
@@ -28,6 +28,7 @@ internal open class ClassOneToManyMap(storageFile: File) : BasicStringMap<Collec
|
||||
storage.append(key.asString(), listOf(value.asString()))
|
||||
}
|
||||
|
||||
@Synchronized
|
||||
operator fun get(key: FqName): Collection<FqName> =
|
||||
storage[key.asString()]?.map(::FqName) ?: setOf()
|
||||
|
||||
|
||||
@@ -31,7 +31,6 @@ class NonCachingLazyStorage<K, V>(
|
||||
) : LazyStorage<K, V> {
|
||||
private var storage: PersistentHashMap<K, V>? = null
|
||||
|
||||
@Synchronized
|
||||
private fun getStorageIfExists(): PersistentHashMap<K, V>? {
|
||||
if (storage != null) return storage
|
||||
|
||||
@@ -43,7 +42,6 @@ class NonCachingLazyStorage<K, V>(
|
||||
return null
|
||||
}
|
||||
|
||||
@Synchronized
|
||||
private fun getStorageOrCreateNew(): PersistentHashMap<K, V> {
|
||||
if (storage == null) {
|
||||
storage = createMap()
|
||||
@@ -53,22 +51,28 @@ class NonCachingLazyStorage<K, V>(
|
||||
}
|
||||
|
||||
override val keys: Collection<K>
|
||||
@Synchronized
|
||||
get() = getStorageIfExists()?.allKeysWithExistingMapping ?: listOf()
|
||||
|
||||
@Synchronized
|
||||
override operator fun contains(key: K): Boolean =
|
||||
getStorageIfExists()?.containsMapping(key) ?: false
|
||||
|
||||
@Synchronized
|
||||
override operator fun get(key: K): V? =
|
||||
getStorageIfExists()?.get(key)
|
||||
|
||||
@Synchronized
|
||||
override operator fun set(key: K, value: V) {
|
||||
getStorageOrCreateNew().put(key, value)
|
||||
}
|
||||
|
||||
@Synchronized
|
||||
override fun remove(key: K) {
|
||||
getStorageIfExists()?.remove(key)
|
||||
}
|
||||
|
||||
@Synchronized
|
||||
override fun append(key: K, value: V) {
|
||||
getStorageOrCreateNew().appendData(key) { dataOutput -> valueExternalizer.save(dataOutput, value) }
|
||||
}
|
||||
@@ -100,7 +104,11 @@ class NonCachingLazyStorage<K, V>(
|
||||
|
||||
@Synchronized
|
||||
override fun close() {
|
||||
storage?.close()
|
||||
try {
|
||||
storage?.close()
|
||||
} finally {
|
||||
storage = null
|
||||
}
|
||||
}
|
||||
|
||||
private fun createMap(): PersistentHashMap<K, V> =
|
||||
|
||||
@@ -1135,7 +1135,7 @@ fun Project.configureJvmProject(javaHome: String, javaVersion: String) {
|
||||
}
|
||||
|
||||
tasks.withType<KotlinCompile> {
|
||||
kotlinOptions.jdkHome = javaHome
|
||||
kotlinOptions.jdkHome = javaHome.takeUnless { kotlinBuildProperties.suppressJdkHomeWarning }
|
||||
kotlinOptions.jvmTarget = javaVersion
|
||||
kotlinOptions.freeCompilerArgs += "-Xjvm-default=compatibility"
|
||||
}
|
||||
|
||||
@@ -20,3 +20,5 @@ val KotlinBuildProperties.jarCompression: Boolean get() = getBoolean("kotlin.bui
|
||||
val KotlinBuildProperties.ignoreTestFailures: Boolean get() = getBoolean("ignoreTestFailures", isTeamcityBuild)
|
||||
|
||||
val KotlinBuildProperties.disableWerror: Boolean get() = getBoolean("kotlin.build.disable.werror", false)
|
||||
|
||||
val KotlinBuildProperties.suppressJdkHomeWarning: Boolean get() = getBoolean("kotlin.suppress.jdkHome.warning", false)
|
||||
|
||||
@@ -34,10 +34,10 @@ import org.jetbrains.kotlin.name.Name;
|
||||
import org.jetbrains.kotlin.resolve.AnnotationChecker;
|
||||
import org.jetbrains.kotlin.resolve.DescriptorUtils;
|
||||
import org.jetbrains.kotlin.resolve.InlineClassesUtilsKt;
|
||||
import org.jetbrains.kotlin.resolve.checkers.ExpectedActualDeclarationChecker;
|
||||
import org.jetbrains.kotlin.resolve.constants.*;
|
||||
import org.jetbrains.kotlin.resolve.descriptorUtil.DescriptorUtilsKt;
|
||||
import org.jetbrains.kotlin.resolve.jvm.annotations.JvmAnnotationUtilKt;
|
||||
import org.jetbrains.kotlin.resolve.multiplatform.OptionalAnnotationUtil;
|
||||
import org.jetbrains.kotlin.types.FlexibleType;
|
||||
import org.jetbrains.kotlin.types.FlexibleTypesKt;
|
||||
import org.jetbrains.kotlin.types.KotlinType;
|
||||
@@ -376,7 +376,7 @@ public abstract class AnnotationCodegen {
|
||||
// We do not generate annotations whose classes are optional (annotated with `@OptionalExpectation`) because if an annotation entry
|
||||
// is resolved to the expected declaration, this means that annotation has no actual class, and thus should not be generated.
|
||||
// (Otherwise we would've resolved the entry to the actual annotation class.)
|
||||
if (ExpectedActualDeclarationChecker.isOptionalAnnotationClass(classDescriptor)) {
|
||||
if (OptionalAnnotationUtil.isOptionalAnnotationClass(classDescriptor)) {
|
||||
return null;
|
||||
}
|
||||
|
||||
|
||||
@@ -35,9 +35,9 @@ import org.jetbrains.kotlin.progress.ProgressIndicatorAndCompilationCanceledStat
|
||||
import org.jetbrains.kotlin.psi.*;
|
||||
import org.jetbrains.kotlin.psi.psiUtil.PsiUtilsKt;
|
||||
import org.jetbrains.kotlin.resolve.BindingContext;
|
||||
import org.jetbrains.kotlin.resolve.checkers.ExpectedActualDeclarationChecker;
|
||||
import org.jetbrains.kotlin.resolve.jvm.diagnostics.JvmDeclarationOriginKt;
|
||||
import org.jetbrains.kotlin.resolve.lazy.descriptors.PackageDescriptorUtilKt;
|
||||
import org.jetbrains.kotlin.resolve.multiplatform.OptionalAnnotationUtil;
|
||||
import org.jetbrains.kotlin.utils.KotlinExceptionWithAttachments;
|
||||
import org.jetbrains.org.objectweb.asm.Type;
|
||||
|
||||
@@ -91,8 +91,8 @@ public class PackageCodegenImpl implements PackageCodegen {
|
||||
if (declaration instanceof KtClassOrObject) {
|
||||
ClassDescriptor descriptor = state.getBindingContext().get(BindingContext.CLASS, declaration);
|
||||
if (PsiUtilsKt.hasExpectModifier(declaration)) {
|
||||
if (descriptor != null && ExpectedActualDeclarationChecker.shouldGenerateExpectClass(descriptor)) {
|
||||
assert ExpectedActualDeclarationChecker.isOptionalAnnotationClass(descriptor) :
|
||||
if (descriptor != null && OptionalAnnotationUtil.shouldGenerateExpectClass(descriptor)) {
|
||||
assert OptionalAnnotationUtil.isOptionalAnnotationClass(descriptor) :
|
||||
"Expect class should be generated only if it's an optional annotation: " + descriptor;
|
||||
state.getFactory().getPackagePartRegistry().getOptionalAnnotations().add(descriptor);
|
||||
}
|
||||
|
||||
@@ -189,7 +189,7 @@ fun ResolvedCall<*>.replaceSuspensionFunctionWithRealDescriptor(
|
||||
Pair(it, typeArguments[candidateDescriptor.typeParameters[it.index]]!!.asTypeProjection())
|
||||
}.toMap()
|
||||
|
||||
newCall.setResultingSubstitutor(
|
||||
newCall.setSubstitutor(
|
||||
TypeConstructorSubstitution.createByParametersMap(newTypeArguments).buildSubstitutor()
|
||||
)
|
||||
|
||||
|
||||
@@ -19,14 +19,12 @@ package org.jetbrains.kotlin.codegen.optimization.boxing
|
||||
import org.jetbrains.kotlin.codegen.optimization.common.findPreviousOrNull
|
||||
import org.jetbrains.kotlin.codegen.optimization.transformer.MethodTransformer
|
||||
import org.jetbrains.org.objectweb.asm.Opcodes
|
||||
import org.jetbrains.org.objectweb.asm.tree.AbstractInsnNode
|
||||
import org.jetbrains.org.objectweb.asm.tree.InsnList
|
||||
import org.jetbrains.org.objectweb.asm.tree.InsnNode
|
||||
import org.jetbrains.org.objectweb.asm.tree.MethodNode
|
||||
import org.jetbrains.org.objectweb.asm.tree.*
|
||||
|
||||
class StackPeepholeOptimizationsTransformer : MethodTransformer() {
|
||||
override fun transform(internalClassName: String, methodNode: MethodNode) {
|
||||
while (transformOnce(methodNode)) {
|
||||
while (true) {
|
||||
if (!transformOnce(methodNode)) break
|
||||
}
|
||||
}
|
||||
|
||||
@@ -115,20 +113,26 @@ class StackPeepholeOptimizationsTransformer : MethodTransformer() {
|
||||
opcode == Opcodes.DUP
|
||||
|
||||
private fun AbstractInsnNode.isPurePushOfSize1(): Boolean =
|
||||
opcode in Opcodes.ACONST_NULL..Opcodes.FCONST_2 ||
|
||||
opcode in Opcodes.BIPUSH..Opcodes.ILOAD ||
|
||||
opcode == Opcodes.FLOAD ||
|
||||
opcode == Opcodes.ALOAD ||
|
||||
isUnitInstance()
|
||||
!isLdcOfSize2() && (
|
||||
opcode in Opcodes.ACONST_NULL..Opcodes.FCONST_2 ||
|
||||
opcode in Opcodes.BIPUSH..Opcodes.ILOAD ||
|
||||
opcode == Opcodes.FLOAD ||
|
||||
opcode == Opcodes.ALOAD ||
|
||||
isUnitInstance()
|
||||
)
|
||||
|
||||
private fun AbstractInsnNode.isEliminatedByPop2() =
|
||||
isPurePushOfSize2() ||
|
||||
opcode == Opcodes.DUP2
|
||||
|
||||
private fun AbstractInsnNode.isPurePushOfSize2(): Boolean =
|
||||
opcode == Opcodes.LCONST_0 || opcode == Opcodes.LCONST_1 ||
|
||||
isLdcOfSize2() ||
|
||||
opcode == Opcodes.LCONST_0 || opcode == Opcodes.LCONST_1 ||
|
||||
opcode == Opcodes.DCONST_0 || opcode == Opcodes.DCONST_1 ||
|
||||
opcode == Opcodes.LLOAD ||
|
||||
opcode == Opcodes.DLOAD
|
||||
|
||||
private fun AbstractInsnNode.isLdcOfSize2(): Boolean =
|
||||
opcode == Opcodes.LDC && this is LdcInsnNode && (this.cst is Double || this.cst is Long)
|
||||
}
|
||||
|
||||
|
||||
@@ -29,4 +29,7 @@ class JvmCodegenStringTable @JvmOverloads constructor(
|
||||
ClassId(fqName.parent(), FqName.topLevel(fqName.shortName()), true)
|
||||
}
|
||||
}
|
||||
|
||||
override val isLocalClassIdReplacementKeptGeneric: Boolean
|
||||
get() = true
|
||||
}
|
||||
|
||||
@@ -13,7 +13,6 @@ plugins {
|
||||
dependencies {
|
||||
compileOnly(intellijCoreDep()) { includeJars("intellij-core", "guava", rootProject = rootProject) }
|
||||
|
||||
testApi(intellijDep())
|
||||
testApi(projectTests(":compiler:test-infrastructure"))
|
||||
testApi(projectTests(":compiler:test-infrastructure-utils"))
|
||||
testApi(projectTests(":compiler:tests-compiler-utils"))
|
||||
|
||||
@@ -492,11 +492,11 @@ digraph nullability_kt {
|
||||
176 [label="Access variable R|/Q.data|"];
|
||||
177 [label="Access variable R|<local>/q|"];
|
||||
178 [label="Access variable R|/Q.data|"];
|
||||
179 [label="Access variable <Inapplicable(UNSAFE_CALL): /MyData.s>#"];
|
||||
179 [label="Access variable <Inapplicable(UNSTABLE_SMARTCAST): /MyData.s>#"];
|
||||
180 [label="Access variable R|<local>/q|"];
|
||||
181 [label="Access variable R|/Q.data|"];
|
||||
182 [label="Access variable <Inapplicable(UNSAFE_CALL): /MyData.s>#"];
|
||||
183 [label="Function call: R|<local>/q|.R|/Q.data|.<Inapplicable(UNSAFE_CALL): /MyData.s>#.R|kotlin/Int.inc|()"];
|
||||
182 [label="Access variable <Inapplicable(UNSTABLE_SMARTCAST): /MyData.s>#"];
|
||||
183 [label="Function call: R|<local>/q|.R|/Q.data|.<Inapplicable(UNSTABLE_SMARTCAST): /MyData.s>#.R|kotlin/Int.inc|()"];
|
||||
184 [label="Exit block"];
|
||||
}
|
||||
185 [label="Exit when branch result"];
|
||||
@@ -566,11 +566,11 @@ digraph nullability_kt {
|
||||
208 [label="Access variable R|/Q.data|"];
|
||||
209 [label="Access variable R|<local>/q|"];
|
||||
210 [label="Access variable R|/Q.data|"];
|
||||
211 [label="Access variable <Inapplicable(UNSAFE_CALL): /MyData.s>#"];
|
||||
211 [label="Access variable <Inapplicable(UNSTABLE_SMARTCAST): /MyData.s>#"];
|
||||
212 [label="Access variable R|<local>/q|"];
|
||||
213 [label="Access variable R|/Q.data|"];
|
||||
214 [label="Access variable <Inapplicable(UNSAFE_CALL): /MyData.s>#"];
|
||||
215 [label="Function call: R|<local>/q|.R|/Q.data|.<Inapplicable(UNSAFE_CALL): /MyData.s>#.R|kotlin/Int.inc|()"];
|
||||
214 [label="Access variable <Inapplicable(UNSTABLE_SMARTCAST): /MyData.s>#"];
|
||||
215 [label="Function call: R|<local>/q|.R|/Q.data|.<Inapplicable(UNSTABLE_SMARTCAST): /MyData.s>#.R|kotlin/Int.inc|()"];
|
||||
216 [label="Exit block"];
|
||||
}
|
||||
217 [label="Exit function test_6" style="filled" fillcolor=red];
|
||||
@@ -1280,11 +1280,11 @@ digraph nullability_kt {
|
||||
490 [label="Access variable R|/QImplWithCustomGetter.data|"];
|
||||
491 [label="Access variable R|<local>/q|"];
|
||||
492 [label="Access variable R|/QImplWithCustomGetter.data|"];
|
||||
493 [label="Access variable <Inapplicable(UNSAFE_CALL): /MyData.s>#"];
|
||||
493 [label="Access variable <Inapplicable(UNSTABLE_SMARTCAST): /MyData.s>#"];
|
||||
494 [label="Access variable R|<local>/q|"];
|
||||
495 [label="Access variable R|/QImplWithCustomGetter.data|"];
|
||||
496 [label="Access variable <Inapplicable(UNSAFE_CALL): /MyData.s>#"];
|
||||
497 [label="Function call: R|<local>/q|.R|/QImplWithCustomGetter.data|.<Inapplicable(UNSAFE_CALL): /MyData.s>#.R|kotlin/Int.inc|()"];
|
||||
496 [label="Access variable <Inapplicable(UNSTABLE_SMARTCAST): /MyData.s>#"];
|
||||
497 [label="Function call: R|<local>/q|.R|/QImplWithCustomGetter.data|.<Inapplicable(UNSTABLE_SMARTCAST): /MyData.s>#.R|kotlin/Int.inc|()"];
|
||||
498 [label="Exit block"];
|
||||
}
|
||||
499 [label="Exit when branch result"];
|
||||
@@ -1363,11 +1363,11 @@ digraph nullability_kt {
|
||||
524 [label="Access variable R|/QImplMutable.data|"];
|
||||
525 [label="Access variable R|<local>/q|"];
|
||||
526 [label="Access variable R|/QImplMutable.data|"];
|
||||
527 [label="Access variable <Inapplicable(UNSAFE_CALL): /MyData.s>#"];
|
||||
527 [label="Access variable <Inapplicable(UNSTABLE_SMARTCAST): /MyData.s>#"];
|
||||
528 [label="Access variable R|<local>/q|"];
|
||||
529 [label="Access variable R|/QImplMutable.data|"];
|
||||
530 [label="Access variable <Inapplicable(UNSAFE_CALL): /MyData.s>#"];
|
||||
531 [label="Function call: R|<local>/q|.R|/QImplMutable.data|.<Inapplicable(UNSAFE_CALL): /MyData.s>#.R|kotlin/Int.inc|()"];
|
||||
530 [label="Access variable <Inapplicable(UNSTABLE_SMARTCAST): /MyData.s>#"];
|
||||
531 [label="Function call: R|<local>/q|.R|/QImplMutable.data|.<Inapplicable(UNSTABLE_SMARTCAST): /MyData.s>#.R|kotlin/Int.inc|()"];
|
||||
532 [label="Exit block"];
|
||||
}
|
||||
533 [label="Exit when branch result"];
|
||||
|
||||
@@ -102,8 +102,8 @@ FILE: nullability.kt
|
||||
when () {
|
||||
!=(R|<local>/q|?.{ $subj$.R|/Q.data| }?.{ $subj$.R|/MyData.s| }?.{ $subj$.R|kotlin/Int.inc|() }, Null(null)) -> {
|
||||
R|<local>/q|.R|/Q.data|
|
||||
R|<local>/q|.R|/Q.data|.<Inapplicable(UNSAFE_CALL): /MyData.s>#
|
||||
R|<local>/q|.R|/Q.data|.<Inapplicable(UNSAFE_CALL): /MyData.s>#.R|kotlin/Int.inc|()
|
||||
R|<local>/q|.R|/Q.data|.<Inapplicable(UNSTABLE_SMARTCAST): /MyData.s>#
|
||||
R|<local>/q|.R|/Q.data|.<Inapplicable(UNSTABLE_SMARTCAST): /MyData.s>#.R|kotlin/Int.inc|()
|
||||
}
|
||||
}
|
||||
|
||||
@@ -111,8 +111,8 @@ FILE: nullability.kt
|
||||
public final fun test_6(q: R|Q?|): R|kotlin/Unit| {
|
||||
R|<local>/q|?.{ $subj$.R|/Q.data| }?.{ $subj$.R|/MyData.s| }?.{ $subj$.R|kotlin/Int.inc|() } ?: ^test_6 Unit
|
||||
R|<local>/q|.R|/Q.data|
|
||||
R|<local>/q|.R|/Q.data|.<Inapplicable(UNSAFE_CALL): /MyData.s>#
|
||||
R|<local>/q|.R|/Q.data|.<Inapplicable(UNSAFE_CALL): /MyData.s>#.R|kotlin/Int.inc|()
|
||||
R|<local>/q|.R|/Q.data|.<Inapplicable(UNSTABLE_SMARTCAST): /MyData.s>#
|
||||
R|<local>/q|.R|/Q.data|.<Inapplicable(UNSTABLE_SMARTCAST): /MyData.s>#.R|kotlin/Int.inc|()
|
||||
}
|
||||
public final fun test_7(q: R|Q?|): R|kotlin/Unit| {
|
||||
when () {
|
||||
@@ -216,8 +216,8 @@ FILE: nullability.kt
|
||||
when () {
|
||||
!=(R|<local>/q|?.{ $subj$.R|/QImplWithCustomGetter.data| }?.{ $subj$.R|/MyData.s| }?.{ $subj$.R|kotlin/Int.inc|() }, Null(null)) -> {
|
||||
R|<local>/q|.R|/QImplWithCustomGetter.data|
|
||||
R|<local>/q|.R|/QImplWithCustomGetter.data|.<Inapplicable(UNSAFE_CALL): /MyData.s>#
|
||||
R|<local>/q|.R|/QImplWithCustomGetter.data|.<Inapplicable(UNSAFE_CALL): /MyData.s>#.R|kotlin/Int.inc|()
|
||||
R|<local>/q|.R|/QImplWithCustomGetter.data|.<Inapplicable(UNSTABLE_SMARTCAST): /MyData.s>#
|
||||
R|<local>/q|.R|/QImplWithCustomGetter.data|.<Inapplicable(UNSTABLE_SMARTCAST): /MyData.s>#.R|kotlin/Int.inc|()
|
||||
}
|
||||
}
|
||||
|
||||
@@ -226,8 +226,8 @@ FILE: nullability.kt
|
||||
when () {
|
||||
!=(R|<local>/q|?.{ $subj$.R|/QImplMutable.data| }?.{ $subj$.R|/MyData.s| }?.{ $subj$.R|kotlin/Int.inc|() }, Null(null)) -> {
|
||||
R|<local>/q|.R|/QImplMutable.data|
|
||||
R|<local>/q|.R|/QImplMutable.data|.<Inapplicable(UNSAFE_CALL): /MyData.s>#
|
||||
R|<local>/q|.R|/QImplMutable.data|.<Inapplicable(UNSAFE_CALL): /MyData.s>#.R|kotlin/Int.inc|()
|
||||
R|<local>/q|.R|/QImplMutable.data|.<Inapplicable(UNSTABLE_SMARTCAST): /MyData.s>#
|
||||
R|<local>/q|.R|/QImplMutable.data|.<Inapplicable(UNSTABLE_SMARTCAST): /MyData.s>#.R|kotlin/Int.inc|()
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -67,8 +67,8 @@ fun test_5(q: Q?) {
|
||||
// `q.data` is a property that has an open getter, so we can NOT smartcast it to non-nullable MyData.
|
||||
if (q?.data?.s?.inc() != null) {
|
||||
q.data // good
|
||||
q.data<!UNSAFE_CALL!>.<!>s // should be bad
|
||||
q.data<!UNSAFE_CALL!>.<!>s.inc() // should be bad
|
||||
<!SMARTCAST_IMPOSSIBLE!>q.data<!>.s // should be bad
|
||||
<!SMARTCAST_IMPOSSIBLE!>q.data<!>.s.inc() // should be bad
|
||||
}
|
||||
}
|
||||
|
||||
@@ -76,8 +76,8 @@ fun test_6(q: Q?) {
|
||||
// `q.data` is a property that has an open getter, so we can NOT smartcast it to non-nullable MyData.
|
||||
q?.data?.s?.inc() ?: return
|
||||
q.data // good
|
||||
q.data<!UNSAFE_CALL!>.<!>s // should be bad
|
||||
q.data<!UNSAFE_CALL!>.<!>s.inc() // should be bad
|
||||
<!SMARTCAST_IMPOSSIBLE!>q.data<!>.s // should be bad
|
||||
<!SMARTCAST_IMPOSSIBLE!>q.data<!>.s.inc() // should be bad
|
||||
}
|
||||
|
||||
fun test_7(q: Q?) {
|
||||
@@ -162,8 +162,8 @@ fun test_12(q: QImplWithCustomGetter?) {
|
||||
// `q.data` is a property that has an open getter, so we can NOT smartcast it to non-nullable MyData.
|
||||
if (q?.data?.s?.inc() != null) {
|
||||
q.data // good
|
||||
q.data<!UNSAFE_CALL!>.<!>s // should be bad
|
||||
q.data<!UNSAFE_CALL!>.<!>s.inc() // should be bad
|
||||
<!SMARTCAST_IMPOSSIBLE!>q.data<!>.s // should be bad
|
||||
<!SMARTCAST_IMPOSSIBLE!>q.data<!>.s.inc() // should be bad
|
||||
}
|
||||
}
|
||||
|
||||
@@ -171,7 +171,7 @@ fun test_13(q: QImplMutable?) {
|
||||
// `q.data` is a property that is mutable, so we can NOT smartcast it to non-nullable MyData.
|
||||
if (q?.data?.s?.inc() != null) {
|
||||
q.data // good
|
||||
q.data<!UNSAFE_CALL!>.<!>s // should be bad
|
||||
q.data<!UNSAFE_CALL!>.<!>s.inc() // should be bad
|
||||
<!SMARTCAST_IMPOSSIBLE!>q.data<!>.s // should be bad
|
||||
<!SMARTCAST_IMPOSSIBLE!>q.data<!>.s.inc() // should be bad
|
||||
}
|
||||
}
|
||||
|
||||
@@ -20,7 +20,7 @@ FILE: KtFirCompositeScope.kt
|
||||
public final fun getAllNames(): R|kotlin/collections/Set<kotlin/String>| {
|
||||
^getAllNames R|/withValidityAssertion|<R|kotlin/collections/Set<kotlin/String>|>(<L> = withValidityAssertion@fun <anonymous>(): R|kotlin/collections/Set<kotlin/String>| <inline=Inline, kind=UNKNOWN> {
|
||||
^ R|/buildSet|<R|kotlin/String|>(<L> = buildSet@fun R|kotlin/collections/MutableSet<kotlin/String>|.<anonymous>(): R|kotlin/Unit| <inline=Inline, kind=UNKNOWN> {
|
||||
this@R|/KtFirCompositeScope|.R|/KtFirCompositeScope.subScopes|.R|kotlin/collections/flatMapTo|<R|KtScope|, R|kotlin/String|, R|kotlin/collections/MutableCollection<in kotlin/String>|>(this@R|special/anonymous|, <L> = flatMapTo@fun <anonymous>(it: R|KtScope|): R|kotlin/collections/Iterable<kotlin/String>| <inline=Inline, kind=UNKNOWN> {
|
||||
this@R|/KtFirCompositeScope|.R|/KtFirCompositeScope.subScopes|.R|kotlin/collections/flatMapTo|<R|KtScope|, R|kotlin/String|, R|kotlin/collections/MutableSet<kotlin/String>|>(this@R|special/anonymous|, <L> = flatMapTo@fun <anonymous>(it: R|KtScope|): R|kotlin/collections/Iterable<kotlin/String>| <inline=Inline, kind=UNKNOWN> {
|
||||
^ R|<local>/it|.R|/KtScope.getAllNames|()
|
||||
}
|
||||
)
|
||||
|
||||
@@ -990,9 +990,21 @@ public class FirOldFrontendDiagnosticsTestGenerated extends AbstractFirDiagnosti
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("AnnotationForClassTypeParameter.kt")
|
||||
public void testAnnotationForClassTypeParameter() throws Exception {
|
||||
runTest("compiler/testData/diagnostics/tests/annotations/AnnotationForClassTypeParameter.kt");
|
||||
@TestMetadata("AnnotationForClassTypeParameter_15.kt")
|
||||
public void testAnnotationForClassTypeParameter_15() throws Exception {
|
||||
runTest("compiler/testData/diagnostics/tests/annotations/AnnotationForClassTypeParameter_15.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("AnnotationForClassTypeParameter_16.kt")
|
||||
public void testAnnotationForClassTypeParameter_16() throws Exception {
|
||||
runTest("compiler/testData/diagnostics/tests/annotations/AnnotationForClassTypeParameter_16.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("AnnotationForClassTypeParameter_typeUseFlag.kt")
|
||||
public void testAnnotationForClassTypeParameter_typeUseFlag() throws Exception {
|
||||
runTest("compiler/testData/diagnostics/tests/annotations/AnnotationForClassTypeParameter_typeUseFlag.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -1343,6 +1355,12 @@ public class FirOldFrontendDiagnosticsTestGenerated extends AbstractFirDiagnosti
|
||||
runTest("compiler/testData/diagnostics/tests/annotations/RecursivelyIncorrectlyAnnotatedParameter.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("requireKotlin.kt")
|
||||
public void testRequireKotlin() throws Exception {
|
||||
runTest("compiler/testData/diagnostics/tests/annotations/requireKotlin.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("RetentionsOfAnnotationWithExpressionTarget_after.kt")
|
||||
public void testRetentionsOfAnnotationWithExpressionTarget_after() throws Exception {
|
||||
@@ -12632,6 +12650,12 @@ public class FirOldFrontendDiagnosticsTestGenerated extends AbstractFirDiagnosti
|
||||
KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("compiler/testData/diagnostics/tests/inference/builderInference"), Pattern.compile("^(.+)\\.kt$"), Pattern.compile("^(.+)\\.fir\\.kts?$"), true);
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("labaledCall.kt")
|
||||
public void testLabaledCall() throws Exception {
|
||||
runTest("compiler/testData/diagnostics/tests/inference/builderInference/labaledCall.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("simpleLambdaInCallWithAnotherLambdaWithBuilderInference.kt")
|
||||
public void testSimpleLambdaInCallWithAnotherLambdaWithBuilderInference() throws Exception {
|
||||
@@ -12668,17 +12692,115 @@ public class FirOldFrontendDiagnosticsTestGenerated extends AbstractFirDiagnosti
|
||||
runTest("compiler/testData/diagnostics/tests/inference/builderInference/specialCallsWithCallableReferencesErrorType.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("specialCallsWithCallableReferencesErrorTypeUnrestricted.kt")
|
||||
public void testSpecialCallsWithCallableReferencesErrorTypeUnrestricted() throws Exception {
|
||||
runTest("compiler/testData/diagnostics/tests/inference/builderInference/specialCallsWithCallableReferencesErrorTypeUnrestricted.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("specialCallsWithCallableReferencesNonStrictOnlyInputTypes.kt")
|
||||
public void testSpecialCallsWithCallableReferencesNonStrictOnlyInputTypes() throws Exception {
|
||||
runTest("compiler/testData/diagnostics/tests/inference/builderInference/specialCallsWithCallableReferencesNonStrictOnlyInputTypes.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("specialCallsWithCallableReferencesUnrestricted.kt")
|
||||
public void testSpecialCallsWithCallableReferencesUnrestricted() throws Exception {
|
||||
runTest("compiler/testData/diagnostics/tests/inference/builderInference/specialCallsWithCallableReferencesUnrestricted.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("specialCallsWithLambdas.kt")
|
||||
public void testSpecialCallsWithLambdas() throws Exception {
|
||||
runTest("compiler/testData/diagnostics/tests/inference/builderInference/specialCallsWithLambdas.kt");
|
||||
}
|
||||
|
||||
@Nested
|
||||
@TestMetadata("compiler/testData/diagnostics/tests/inference/builderInference/constraints")
|
||||
@TestDataPath("$PROJECT_ROOT")
|
||||
public class Constraints {
|
||||
@Test
|
||||
public void testAllFilesPresentInConstraints() throws Exception {
|
||||
KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("compiler/testData/diagnostics/tests/inference/builderInference/constraints"), Pattern.compile("^(.+)\\.kt$"), Pattern.compile("^(.+)\\.fir\\.kts?$"), true);
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("violating.kt")
|
||||
public void testViolating() throws Exception {
|
||||
runTest("compiler/testData/diagnostics/tests/inference/builderInference/constraints/violating.kt");
|
||||
}
|
||||
}
|
||||
|
||||
@Nested
|
||||
@TestMetadata("compiler/testData/diagnostics/tests/inference/builderInference/stubTypes")
|
||||
@TestDataPath("$PROJECT_ROOT")
|
||||
public class StubTypes {
|
||||
@Test
|
||||
public void testAllFilesPresentInStubTypes() throws Exception {
|
||||
KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("compiler/testData/diagnostics/tests/inference/builderInference/stubTypes"), Pattern.compile("^(.+)\\.kt$"), Pattern.compile("^(.+)\\.fir\\.kts?$"), true);
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("capturedTypes.kt")
|
||||
public void testCapturedTypes() throws Exception {
|
||||
runTest("compiler/testData/diagnostics/tests/inference/builderInference/stubTypes/capturedTypes.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("commonSuperType.kt")
|
||||
public void testCommonSuperType() throws Exception {
|
||||
runTest("compiler/testData/diagnostics/tests/inference/builderInference/stubTypes/commonSuperType.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("commonSuperTypeContravariant.kt")
|
||||
public void testCommonSuperTypeContravariant() throws Exception {
|
||||
runTest("compiler/testData/diagnostics/tests/inference/builderInference/stubTypes/commonSuperTypeContravariant.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("commonSuperTypeCovariant.kt")
|
||||
public void testCommonSuperTypeCovariant() throws Exception {
|
||||
runTest("compiler/testData/diagnostics/tests/inference/builderInference/stubTypes/commonSuperTypeCovariant.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("commonSuperTypeInvariant.kt")
|
||||
public void testCommonSuperTypeInvariant() throws Exception {
|
||||
runTest("compiler/testData/diagnostics/tests/inference/builderInference/stubTypes/commonSuperTypeInvariant.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("commonSuperTypeNullable.kt")
|
||||
public void testCommonSuperTypeNullable() throws Exception {
|
||||
runTest("compiler/testData/diagnostics/tests/inference/builderInference/stubTypes/commonSuperTypeNullable.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("intersect.kt")
|
||||
public void testIntersect() throws Exception {
|
||||
runTest("compiler/testData/diagnostics/tests/inference/builderInference/stubTypes/intersect.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("memberScope.kt")
|
||||
public void testMemberScope() throws Exception {
|
||||
runTest("compiler/testData/diagnostics/tests/inference/builderInference/stubTypes/memberScope.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("nullability.kt")
|
||||
public void testNullability() throws Exception {
|
||||
runTest("compiler/testData/diagnostics/tests/inference/builderInference/stubTypes/nullability.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("renderingStubTypes.kt")
|
||||
public void testRenderingStubTypes() throws Exception {
|
||||
runTest("compiler/testData/diagnostics/tests/inference/builderInference/stubTypes/renderingStubTypes.kt");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Nested
|
||||
@@ -32230,6 +32352,48 @@ public class FirOldFrontendDiagnosticsTestGenerated extends AbstractFirDiagnosti
|
||||
public void testCompleteIrrelevantCalls() throws Exception {
|
||||
runTest("compiler/testData/diagnostics/testsWithStdLib/builderInference/completeIrrelevantCalls.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("incorrectCalls.kt")
|
||||
public void testIncorrectCalls() throws Exception {
|
||||
runTest("compiler/testData/diagnostics/testsWithStdLib/builderInference/incorrectCalls.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("incorrectCallsWithRestrictions.kt")
|
||||
public void testIncorrectCallsWithRestrictions() throws Exception {
|
||||
runTest("compiler/testData/diagnostics/testsWithStdLib/builderInference/incorrectCallsWithRestrictions.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("inferCoroutineTypeInOldVersion.kt")
|
||||
public void testInferCoroutineTypeInOldVersion() throws Exception {
|
||||
runTest("compiler/testData/diagnostics/testsWithStdLib/builderInference/inferCoroutineTypeInOldVersion.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("resolveUsualCallWithBuilderInference.kt")
|
||||
public void testResolveUsualCallWithBuilderInference() throws Exception {
|
||||
runTest("compiler/testData/diagnostics/testsWithStdLib/builderInference/resolveUsualCallWithBuilderInference.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("resolveUsualCallWithBuilderInferenceWithRestrictions.kt")
|
||||
public void testResolveUsualCallWithBuilderInferenceWithRestrictions() throws Exception {
|
||||
runTest("compiler/testData/diagnostics/testsWithStdLib/builderInference/resolveUsualCallWithBuilderInferenceWithRestrictions.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("useInferenceInformationFromExtension.kt")
|
||||
public void testUseInferenceInformationFromExtension() throws Exception {
|
||||
runTest("compiler/testData/diagnostics/testsWithStdLib/builderInference/useInferenceInformationFromExtension.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("useInferenceInformationFromExtensionWithRestrictions.kt")
|
||||
public void testUseInferenceInformationFromExtensionWithRestrictions() throws Exception {
|
||||
runTest("compiler/testData/diagnostics/testsWithStdLib/builderInference/useInferenceInformationFromExtensionWithRestrictions.kt");
|
||||
}
|
||||
}
|
||||
|
||||
@Nested
|
||||
@@ -33420,18 +33584,6 @@ public class FirOldFrontendDiagnosticsTestGenerated extends AbstractFirDiagnosti
|
||||
runTest("compiler/testData/diagnostics/testsWithStdLib/coroutines/inference/extensionsWithNonValuableConstraints_1_2.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("incorrectCalls.kt")
|
||||
public void testIncorrectCalls() throws Exception {
|
||||
runTest("compiler/testData/diagnostics/testsWithStdLib/coroutines/inference/incorrectCalls.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("inferCoroutineTypeInOldVersion.kt")
|
||||
public void testInferCoroutineTypeInOldVersion() throws Exception {
|
||||
runTest("compiler/testData/diagnostics/testsWithStdLib/coroutines/inference/inferCoroutineTypeInOldVersion.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("inferenceFromMethodInsideLocalVariable.kt")
|
||||
public void testInferenceFromMethodInsideLocalVariable() throws Exception {
|
||||
@@ -33576,12 +33728,6 @@ public class FirOldFrontendDiagnosticsTestGenerated extends AbstractFirDiagnosti
|
||||
runTest("compiler/testData/diagnostics/testsWithStdLib/coroutines/inference/recursiveGenerators2.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("resolveUsualCallWithBuilderInference.kt")
|
||||
public void testResolveUsualCallWithBuilderInference() throws Exception {
|
||||
runTest("compiler/testData/diagnostics/testsWithStdLib/coroutines/inference/resolveUsualCallWithBuilderInference.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("returnTypeInference.kt")
|
||||
public void testReturnTypeInference() throws Exception {
|
||||
@@ -33630,12 +33776,6 @@ public class FirOldFrontendDiagnosticsTestGenerated extends AbstractFirDiagnosti
|
||||
runTest("compiler/testData/diagnostics/testsWithStdLib/coroutines/inference/typeFromReceiver.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("useInferenceInformationFromExtension.kt")
|
||||
public void testUseInferenceInformationFromExtension() throws Exception {
|
||||
runTest("compiler/testData/diagnostics/testsWithStdLib/coroutines/inference/useInferenceInformationFromExtension.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("variableCallInsideBuilderFunction.kt")
|
||||
public void testVariableCallInsideBuilderFunction() throws Exception {
|
||||
|
||||
@@ -990,9 +990,21 @@ public class FirOldFrontendDiagnosticsWithLightTreeTestGenerated extends Abstrac
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("AnnotationForClassTypeParameter.kt")
|
||||
public void testAnnotationForClassTypeParameter() throws Exception {
|
||||
runTest("compiler/testData/diagnostics/tests/annotations/AnnotationForClassTypeParameter.kt");
|
||||
@TestMetadata("AnnotationForClassTypeParameter_15.kt")
|
||||
public void testAnnotationForClassTypeParameter_15() throws Exception {
|
||||
runTest("compiler/testData/diagnostics/tests/annotations/AnnotationForClassTypeParameter_15.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("AnnotationForClassTypeParameter_16.kt")
|
||||
public void testAnnotationForClassTypeParameter_16() throws Exception {
|
||||
runTest("compiler/testData/diagnostics/tests/annotations/AnnotationForClassTypeParameter_16.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("AnnotationForClassTypeParameter_typeUseFlag.kt")
|
||||
public void testAnnotationForClassTypeParameter_typeUseFlag() throws Exception {
|
||||
runTest("compiler/testData/diagnostics/tests/annotations/AnnotationForClassTypeParameter_typeUseFlag.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -1343,6 +1355,12 @@ public class FirOldFrontendDiagnosticsWithLightTreeTestGenerated extends Abstrac
|
||||
runTest("compiler/testData/diagnostics/tests/annotations/RecursivelyIncorrectlyAnnotatedParameter.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("requireKotlin.kt")
|
||||
public void testRequireKotlin() throws Exception {
|
||||
runTest("compiler/testData/diagnostics/tests/annotations/requireKotlin.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("RetentionsOfAnnotationWithExpressionTarget_after.kt")
|
||||
public void testRetentionsOfAnnotationWithExpressionTarget_after() throws Exception {
|
||||
@@ -12632,6 +12650,12 @@ public class FirOldFrontendDiagnosticsWithLightTreeTestGenerated extends Abstrac
|
||||
KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("compiler/testData/diagnostics/tests/inference/builderInference"), Pattern.compile("^(.+)\\.kt$"), Pattern.compile("^(.+)\\.fir\\.kts?$"), true);
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("labaledCall.kt")
|
||||
public void testLabaledCall() throws Exception {
|
||||
runTest("compiler/testData/diagnostics/tests/inference/builderInference/labaledCall.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("simpleLambdaInCallWithAnotherLambdaWithBuilderInference.kt")
|
||||
public void testSimpleLambdaInCallWithAnotherLambdaWithBuilderInference() throws Exception {
|
||||
@@ -12668,17 +12692,115 @@ public class FirOldFrontendDiagnosticsWithLightTreeTestGenerated extends Abstrac
|
||||
runTest("compiler/testData/diagnostics/tests/inference/builderInference/specialCallsWithCallableReferencesErrorType.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("specialCallsWithCallableReferencesErrorTypeUnrestricted.kt")
|
||||
public void testSpecialCallsWithCallableReferencesErrorTypeUnrestricted() throws Exception {
|
||||
runTest("compiler/testData/diagnostics/tests/inference/builderInference/specialCallsWithCallableReferencesErrorTypeUnrestricted.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("specialCallsWithCallableReferencesNonStrictOnlyInputTypes.kt")
|
||||
public void testSpecialCallsWithCallableReferencesNonStrictOnlyInputTypes() throws Exception {
|
||||
runTest("compiler/testData/diagnostics/tests/inference/builderInference/specialCallsWithCallableReferencesNonStrictOnlyInputTypes.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("specialCallsWithCallableReferencesUnrestricted.kt")
|
||||
public void testSpecialCallsWithCallableReferencesUnrestricted() throws Exception {
|
||||
runTest("compiler/testData/diagnostics/tests/inference/builderInference/specialCallsWithCallableReferencesUnrestricted.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("specialCallsWithLambdas.kt")
|
||||
public void testSpecialCallsWithLambdas() throws Exception {
|
||||
runTest("compiler/testData/diagnostics/tests/inference/builderInference/specialCallsWithLambdas.kt");
|
||||
}
|
||||
|
||||
@Nested
|
||||
@TestMetadata("compiler/testData/diagnostics/tests/inference/builderInference/constraints")
|
||||
@TestDataPath("$PROJECT_ROOT")
|
||||
public class Constraints {
|
||||
@Test
|
||||
public void testAllFilesPresentInConstraints() throws Exception {
|
||||
KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("compiler/testData/diagnostics/tests/inference/builderInference/constraints"), Pattern.compile("^(.+)\\.kt$"), Pattern.compile("^(.+)\\.fir\\.kts?$"), true);
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("violating.kt")
|
||||
public void testViolating() throws Exception {
|
||||
runTest("compiler/testData/diagnostics/tests/inference/builderInference/constraints/violating.kt");
|
||||
}
|
||||
}
|
||||
|
||||
@Nested
|
||||
@TestMetadata("compiler/testData/diagnostics/tests/inference/builderInference/stubTypes")
|
||||
@TestDataPath("$PROJECT_ROOT")
|
||||
public class StubTypes {
|
||||
@Test
|
||||
public void testAllFilesPresentInStubTypes() throws Exception {
|
||||
KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("compiler/testData/diagnostics/tests/inference/builderInference/stubTypes"), Pattern.compile("^(.+)\\.kt$"), Pattern.compile("^(.+)\\.fir\\.kts?$"), true);
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("capturedTypes.kt")
|
||||
public void testCapturedTypes() throws Exception {
|
||||
runTest("compiler/testData/diagnostics/tests/inference/builderInference/stubTypes/capturedTypes.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("commonSuperType.kt")
|
||||
public void testCommonSuperType() throws Exception {
|
||||
runTest("compiler/testData/diagnostics/tests/inference/builderInference/stubTypes/commonSuperType.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("commonSuperTypeContravariant.kt")
|
||||
public void testCommonSuperTypeContravariant() throws Exception {
|
||||
runTest("compiler/testData/diagnostics/tests/inference/builderInference/stubTypes/commonSuperTypeContravariant.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("commonSuperTypeCovariant.kt")
|
||||
public void testCommonSuperTypeCovariant() throws Exception {
|
||||
runTest("compiler/testData/diagnostics/tests/inference/builderInference/stubTypes/commonSuperTypeCovariant.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("commonSuperTypeInvariant.kt")
|
||||
public void testCommonSuperTypeInvariant() throws Exception {
|
||||
runTest("compiler/testData/diagnostics/tests/inference/builderInference/stubTypes/commonSuperTypeInvariant.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("commonSuperTypeNullable.kt")
|
||||
public void testCommonSuperTypeNullable() throws Exception {
|
||||
runTest("compiler/testData/diagnostics/tests/inference/builderInference/stubTypes/commonSuperTypeNullable.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("intersect.kt")
|
||||
public void testIntersect() throws Exception {
|
||||
runTest("compiler/testData/diagnostics/tests/inference/builderInference/stubTypes/intersect.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("memberScope.kt")
|
||||
public void testMemberScope() throws Exception {
|
||||
runTest("compiler/testData/diagnostics/tests/inference/builderInference/stubTypes/memberScope.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("nullability.kt")
|
||||
public void testNullability() throws Exception {
|
||||
runTest("compiler/testData/diagnostics/tests/inference/builderInference/stubTypes/nullability.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("renderingStubTypes.kt")
|
||||
public void testRenderingStubTypes() throws Exception {
|
||||
runTest("compiler/testData/diagnostics/tests/inference/builderInference/stubTypes/renderingStubTypes.kt");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Nested
|
||||
@@ -32230,6 +32352,48 @@ public class FirOldFrontendDiagnosticsWithLightTreeTestGenerated extends Abstrac
|
||||
public void testCompleteIrrelevantCalls() throws Exception {
|
||||
runTest("compiler/testData/diagnostics/testsWithStdLib/builderInference/completeIrrelevantCalls.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("incorrectCalls.kt")
|
||||
public void testIncorrectCalls() throws Exception {
|
||||
runTest("compiler/testData/diagnostics/testsWithStdLib/builderInference/incorrectCalls.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("incorrectCallsWithRestrictions.kt")
|
||||
public void testIncorrectCallsWithRestrictions() throws Exception {
|
||||
runTest("compiler/testData/diagnostics/testsWithStdLib/builderInference/incorrectCallsWithRestrictions.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("inferCoroutineTypeInOldVersion.kt")
|
||||
public void testInferCoroutineTypeInOldVersion() throws Exception {
|
||||
runTest("compiler/testData/diagnostics/testsWithStdLib/builderInference/inferCoroutineTypeInOldVersion.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("resolveUsualCallWithBuilderInference.kt")
|
||||
public void testResolveUsualCallWithBuilderInference() throws Exception {
|
||||
runTest("compiler/testData/diagnostics/testsWithStdLib/builderInference/resolveUsualCallWithBuilderInference.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("resolveUsualCallWithBuilderInferenceWithRestrictions.kt")
|
||||
public void testResolveUsualCallWithBuilderInferenceWithRestrictions() throws Exception {
|
||||
runTest("compiler/testData/diagnostics/testsWithStdLib/builderInference/resolveUsualCallWithBuilderInferenceWithRestrictions.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("useInferenceInformationFromExtension.kt")
|
||||
public void testUseInferenceInformationFromExtension() throws Exception {
|
||||
runTest("compiler/testData/diagnostics/testsWithStdLib/builderInference/useInferenceInformationFromExtension.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("useInferenceInformationFromExtensionWithRestrictions.kt")
|
||||
public void testUseInferenceInformationFromExtensionWithRestrictions() throws Exception {
|
||||
runTest("compiler/testData/diagnostics/testsWithStdLib/builderInference/useInferenceInformationFromExtensionWithRestrictions.kt");
|
||||
}
|
||||
}
|
||||
|
||||
@Nested
|
||||
@@ -33420,18 +33584,6 @@ public class FirOldFrontendDiagnosticsWithLightTreeTestGenerated extends Abstrac
|
||||
runTest("compiler/testData/diagnostics/testsWithStdLib/coroutines/inference/extensionsWithNonValuableConstraints_1_2.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("incorrectCalls.kt")
|
||||
public void testIncorrectCalls() throws Exception {
|
||||
runTest("compiler/testData/diagnostics/testsWithStdLib/coroutines/inference/incorrectCalls.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("inferCoroutineTypeInOldVersion.kt")
|
||||
public void testInferCoroutineTypeInOldVersion() throws Exception {
|
||||
runTest("compiler/testData/diagnostics/testsWithStdLib/coroutines/inference/inferCoroutineTypeInOldVersion.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("inferenceFromMethodInsideLocalVariable.kt")
|
||||
public void testInferenceFromMethodInsideLocalVariable() throws Exception {
|
||||
@@ -33576,12 +33728,6 @@ public class FirOldFrontendDiagnosticsWithLightTreeTestGenerated extends Abstrac
|
||||
runTest("compiler/testData/diagnostics/testsWithStdLib/coroutines/inference/recursiveGenerators2.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("resolveUsualCallWithBuilderInference.kt")
|
||||
public void testResolveUsualCallWithBuilderInference() throws Exception {
|
||||
runTest("compiler/testData/diagnostics/testsWithStdLib/coroutines/inference/resolveUsualCallWithBuilderInference.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("returnTypeInference.kt")
|
||||
public void testReturnTypeInference() throws Exception {
|
||||
@@ -33630,12 +33776,6 @@ public class FirOldFrontendDiagnosticsWithLightTreeTestGenerated extends Abstrac
|
||||
runTest("compiler/testData/diagnostics/testsWithStdLib/coroutines/inference/typeFromReceiver.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("useInferenceInformationFromExtension.kt")
|
||||
public void testUseInferenceInformationFromExtension() throws Exception {
|
||||
runTest("compiler/testData/diagnostics/testsWithStdLib/coroutines/inference/useInferenceInformationFromExtension.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("variableCallInsideBuilderFunction.kt")
|
||||
public void testVariableCallInsideBuilderFunction() throws Exception {
|
||||
|
||||
@@ -465,6 +465,12 @@ object DIAGNOSTICS_LIST : DiagnosticList("FirErrors") {
|
||||
parameter<Variance>("variance")
|
||||
parameter<ConeKotlinType>("containingType")
|
||||
}
|
||||
|
||||
val SMARTCAST_IMPOSSIBLE by error<KtExpression> {
|
||||
parameter<ConeKotlinType>("desiredType")
|
||||
parameter<FirExpression>("subject")
|
||||
parameter<String>("description")
|
||||
}
|
||||
}
|
||||
|
||||
val REFLECTION by object : DiagnosticGroup("Reflection") {
|
||||
|
||||
@@ -303,6 +303,7 @@ object FirErrors {
|
||||
val INCOMPATIBLE_TYPES_WARNING by warning2<KtElement, ConeKotlinType, ConeKotlinType>()
|
||||
val TYPE_VARIANCE_CONFLICT by error4<PsiElement, FirTypeParameterSymbol, Variance, Variance, ConeKotlinType>(SourceElementPositioningStrategies.DECLARATION_SIGNATURE_OR_DEFAULT)
|
||||
val TYPE_VARIANCE_CONFLICT_IN_EXPANDED_TYPE by error4<PsiElement, FirTypeParameterSymbol, Variance, Variance, ConeKotlinType>(SourceElementPositioningStrategies.DECLARATION_SIGNATURE_OR_DEFAULT)
|
||||
val SMARTCAST_IMPOSSIBLE by error3<KtExpression, ConeKotlinType, FirExpression, String>()
|
||||
|
||||
// Reflection
|
||||
val EXTENSION_IN_CLASS_REFERENCE_NOT_ALLOWED by error1<KtExpression, FirCallableDeclaration<*>>(SourceElementPositioningStrategies.REFERENCE_BY_QUALIFIED)
|
||||
|
||||
@@ -156,30 +156,34 @@ object FirReturnsImpliesAnalyzer : FirControlFlowChecker() {
|
||||
variableStorage: VariableStorage,
|
||||
flow: Flow,
|
||||
context: CheckerContext
|
||||
): MutableTypeStatements? = when (this) {
|
||||
is ConeBinaryLogicExpression -> {
|
||||
val left = left.buildTypeStatements(function, logicSystem, variableStorage, flow, context)
|
||||
val right = right.buildTypeStatements(function, logicSystem, variableStorage, flow, context)
|
||||
if (left != null && right != null) {
|
||||
if (kind == LogicOperationKind.AND) {
|
||||
left.apply { mergeTypeStatements(right) }
|
||||
} else logicSystem.orForTypeStatements(left, right)
|
||||
} else (left ?: right)
|
||||
}
|
||||
is ConeIsInstancePredicate -> {
|
||||
): MutableTypeStatements? {
|
||||
fun buildTypeStatements(arg: ConeValueParameterReference, exactType: Boolean, type: ConeKotlinType): MutableTypeStatements? {
|
||||
val fir = function.getParameterSymbol(arg.parameterIndex, context).fir
|
||||
val realVar = variableStorage.getOrCreateRealVariable(flow, fir.symbol, fir)
|
||||
realVar?.to(simpleTypeStatement(realVar, !isNegated, type))?.let { mutableMapOf(it) }
|
||||
?.takeIf {
|
||||
it.stability == PropertyStability.STABLE_VALUE ||
|
||||
// TODO: consider removing the part below
|
||||
it.stability == PropertyStability.LOCAL_VAR
|
||||
}
|
||||
return realVar?.to(simpleTypeStatement(realVar, exactType, type))?.let { mutableMapOf(it) }
|
||||
}
|
||||
is ConeIsNullPredicate -> {
|
||||
val fir = function.getParameterSymbol(arg.parameterIndex, context).fir
|
||||
val realVar = variableStorage.getOrCreateRealVariable(flow, fir.symbol, fir)
|
||||
realVar?.to(simpleTypeStatement(realVar, isNegated, context.session.builtinTypes.anyType.type))?.let { mutableMapOf(it) }
|
||||
}
|
||||
is ConeLogicalNot -> arg.buildTypeStatements(function, logicSystem, variableStorage, flow, context)
|
||||
?.mapValuesTo(mutableMapOf()) { (_, value) -> value.invert() }
|
||||
return when (this) {
|
||||
is ConeBinaryLogicExpression -> {
|
||||
val left = left.buildTypeStatements(function, logicSystem, variableStorage, flow, context)
|
||||
val right = right.buildTypeStatements(function, logicSystem, variableStorage, flow, context)
|
||||
if (left != null && right != null) {
|
||||
if (kind == LogicOperationKind.AND) {
|
||||
left.apply { mergeTypeStatements(right) }
|
||||
} else logicSystem.orForTypeStatements(left, right)
|
||||
} else (left ?: right)
|
||||
}
|
||||
is ConeIsInstancePredicate -> buildTypeStatements(arg, !isNegated, type)
|
||||
is ConeIsNullPredicate -> buildTypeStatements(arg, isNegated, context.session.builtinTypes.anyType.type)
|
||||
is ConeLogicalNot -> arg.buildTypeStatements(function, logicSystem, variableStorage, flow, context)
|
||||
?.mapValuesTo(mutableMapOf()) { (_, value) -> value.invert() }
|
||||
|
||||
else -> null
|
||||
else -> null
|
||||
}
|
||||
}
|
||||
|
||||
private fun ConeKotlinType.isInapplicableWith(operation: Operation, session: FirSession): Boolean {
|
||||
|
||||
@@ -11,6 +11,7 @@ import org.jetbrains.kotlin.fir.FirSourceElement
|
||||
import org.jetbrains.kotlin.fir.analysis.checkers.ConstantArgumentKind
|
||||
import org.jetbrains.kotlin.fir.analysis.checkers.checkConstantArguments
|
||||
import org.jetbrains.kotlin.fir.analysis.checkers.context.CheckerContext
|
||||
import org.jetbrains.kotlin.fir.analysis.checkers.findSingleArgumentByName
|
||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.DiagnosticReporter
|
||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirDiagnosticFactory0
|
||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors
|
||||
@@ -20,17 +21,18 @@ import org.jetbrains.kotlin.fir.expressions.*
|
||||
import org.jetbrains.kotlin.fir.languageVersionSettings
|
||||
import org.jetbrains.kotlin.fir.resolve.fqName
|
||||
import org.jetbrains.kotlin.name.FqName
|
||||
import org.jetbrains.kotlin.name.Name
|
||||
import org.jetbrains.kotlin.psi.KtExpression
|
||||
import org.jetbrains.kotlin.resolve.RequireKotlinConstants
|
||||
|
||||
object FirAnnotationArgumentChecker : FirAnnotationCallChecker() {
|
||||
private val versionArgumentName = Name.identifier("version")
|
||||
private val deprecatedSinceKotlinFqName = FqName("kotlin.DeprecatedSinceKotlin")
|
||||
private val sinceKotlinFqName = FqName("kotlin.SinceKotlin")
|
||||
|
||||
private val annotationFqNamesWithVersion = setOf(
|
||||
FqName("kotlin.internal.RequireKotlin"),
|
||||
RequireKotlinConstants.FQ_NAME,
|
||||
sinceKotlinFqName,
|
||||
deprecatedSinceKotlinFqName
|
||||
)
|
||||
|
||||
override fun check(expression: FirAnnotationCall, context: CheckerContext, reporter: DiagnosticReporter) {
|
||||
@@ -38,10 +40,11 @@ object FirAnnotationArgumentChecker : FirAnnotationCallChecker() {
|
||||
val fqName = expression.fqName(context.session)
|
||||
for ((arg, _) in argumentMapping) {
|
||||
val argExpression = (arg as? FirNamedArgumentExpression)?.expression ?: arg
|
||||
checkAnnotationArgumentWithSubElements(argExpression, fqName, context.session, reporter, context)
|
||||
checkAnnotationArgumentWithSubElements(argExpression, context.session, reporter, context)
|
||||
?.let { reporter.reportOn(argExpression.source, it, context) }
|
||||
}
|
||||
|
||||
checkAnnotationsWithVersion(fqName, expression, context, reporter)
|
||||
checkDeprecatedSinceKotlin(expression.source, fqName, argumentMapping, context, reporter)
|
||||
|
||||
val args = expression.argumentList.arguments
|
||||
@@ -54,7 +57,6 @@ object FirAnnotationArgumentChecker : FirAnnotationCallChecker() {
|
||||
|
||||
private fun checkAnnotationArgumentWithSubElements(
|
||||
expression: FirExpression,
|
||||
fqName: FqName?,
|
||||
session: FirSession,
|
||||
reporter: DiagnosticReporter,
|
||||
context: CheckerContext
|
||||
@@ -66,7 +68,7 @@ object FirAnnotationArgumentChecker : FirAnnotationCallChecker() {
|
||||
for (arg in args.arguments) {
|
||||
val sourceForReport = arg.source
|
||||
|
||||
when (val err = checkAnnotationArgumentWithSubElements(arg, fqName, session, reporter, context)) {
|
||||
when (val err = checkAnnotationArgumentWithSubElements(arg, session, reporter, context)) {
|
||||
null -> {
|
||||
//DO NOTHING
|
||||
}
|
||||
@@ -86,12 +88,12 @@ object FirAnnotationArgumentChecker : FirAnnotationCallChecker() {
|
||||
is FirVarargArgumentsExpression -> {
|
||||
for (arg in expression.arguments) {
|
||||
val unwrappedArg = if (arg is FirSpreadArgumentExpression) arg.expression else arg
|
||||
checkAnnotationArgumentWithSubElements(unwrappedArg, fqName, session, reporter, context)
|
||||
checkAnnotationArgumentWithSubElements(unwrappedArg, session, reporter, context)
|
||||
?.let { reporter.reportOn(unwrappedArg.source, it, context) }
|
||||
}
|
||||
}
|
||||
else -> {
|
||||
val error = when (checkConstantArguments(expression, session)) {
|
||||
return when (checkConstantArguments(expression, session)) {
|
||||
ConstantArgumentKind.NOT_CONST -> FirErrors.ANNOTATION_ARGUMENT_MUST_BE_CONST
|
||||
ConstantArgumentKind.ENUM_NOT_CONST -> FirErrors.ANNOTATION_ARGUMENT_MUST_BE_ENUM_CONST
|
||||
ConstantArgumentKind.NOT_KCLASS_LITERAL -> FirErrors.ANNOTATION_ARGUMENT_MUST_BE_KCLASS_LITERAL
|
||||
@@ -103,33 +105,47 @@ object FirAnnotationArgumentChecker : FirAnnotationCallChecker() {
|
||||
if (expression is FirFunctionCall) checkArgumentList(expression.argumentList)
|
||||
else null
|
||||
}
|
||||
if (error != null) {
|
||||
return error
|
||||
} else if (annotationFqNamesWithVersion.contains(fqName)) {
|
||||
val argSource = expression.source
|
||||
if (argSource != null) {
|
||||
val stringValue = (expression as? FirConstExpression<*>)?.value as? String
|
||||
if (stringValue != null) {
|
||||
if (!stringValue.matches(RequireKotlinConstants.VERSION_REGEX)) {
|
||||
reporter.reportOn(argSource, FirErrors.ILLEGAL_KOTLIN_VERSION_STRING_VALUE, context)
|
||||
} else if (fqName == sinceKotlinFqName) {
|
||||
val version = ApiVersion.parse(stringValue)
|
||||
val specified = context.session.languageVersionSettings.apiVersion
|
||||
if (version != null && version > specified) {
|
||||
reporter.report(
|
||||
FirErrors.NEWER_VERSION_IN_SINCE_KOTLIN.on(argSource, specified.versionString),
|
||||
context
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return null
|
||||
}
|
||||
|
||||
private fun parseVersionExpressionOrReport(
|
||||
expression: FirExpression,
|
||||
context: CheckerContext,
|
||||
reporter: DiagnosticReporter
|
||||
): ApiVersion? {
|
||||
val constantExpression = (expression as? FirConstExpression<*>)
|
||||
?: ((expression as? FirNamedArgumentExpression)?.expression as? FirConstExpression<*>) ?: return null
|
||||
val stringValue = constantExpression.value as? String ?: return null
|
||||
if (!stringValue.matches(RequireKotlinConstants.VERSION_REGEX)) {
|
||||
reporter.reportOn(expression.source, FirErrors.ILLEGAL_KOTLIN_VERSION_STRING_VALUE, context)
|
||||
return null
|
||||
}
|
||||
val version = ApiVersion.parse(stringValue)
|
||||
if (version == null) {
|
||||
reporter.reportOn(expression.source, FirErrors.ILLEGAL_KOTLIN_VERSION_STRING_VALUE, context)
|
||||
}
|
||||
return version
|
||||
}
|
||||
|
||||
private fun checkAnnotationsWithVersion(
|
||||
fqName: FqName?,
|
||||
annotationCall: FirAnnotationCall,
|
||||
context: CheckerContext,
|
||||
reporter: DiagnosticReporter
|
||||
) {
|
||||
if (!annotationFqNamesWithVersion.contains(fqName)) return
|
||||
val versionExpression = annotationCall.findSingleArgumentByName(versionArgumentName) ?: return
|
||||
val version = parseVersionExpressionOrReport(versionExpression, context, reporter) ?: return
|
||||
if (fqName == sinceKotlinFqName) {
|
||||
val specified = context.session.languageVersionSettings.apiVersion
|
||||
if (version > specified) {
|
||||
reporter.reportOn(versionExpression.source, FirErrors.NEWER_VERSION_IN_SINCE_KOTLIN, specified.versionString, context)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun checkDeprecatedSinceKotlin(
|
||||
source: FirSourceElement?,
|
||||
fqName: FqName?,
|
||||
@@ -150,12 +166,8 @@ object FirAnnotationArgumentChecker : FirAnnotationCallChecker() {
|
||||
for (argument in argumentMapping) {
|
||||
val identifier = argument.value.name.identifier
|
||||
if (identifier == "warningSince" || identifier == "errorSince" || identifier == "hiddenSince") {
|
||||
val argKey = argument.key
|
||||
val constExpression = (argKey as? FirConstExpression<*>)
|
||||
?: ((argKey as? FirNamedArgumentExpression)?.expression as? FirConstExpression<*>)
|
||||
val stringValue = constExpression?.value as? String
|
||||
if (stringValue != null) {
|
||||
val version = ApiVersion.parse(stringValue)
|
||||
val version = parseVersionExpressionOrReport(argument.key, context, reporter)
|
||||
if (version != null) {
|
||||
when (identifier) {
|
||||
"warningSince" -> warningSince = version
|
||||
"errorSince" -> errorSince = version
|
||||
|
||||
@@ -10,13 +10,16 @@ import org.jetbrains.kotlin.fir.analysis.checkers.isSubtypeForTypeMismatch
|
||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.DiagnosticReporter
|
||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.NULL_FOR_NONNULL_TYPE
|
||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.RETURN_TYPE_MISMATCH
|
||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.SMARTCAST_IMPOSSIBLE
|
||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.reportOn
|
||||
import org.jetbrains.kotlin.fir.declarations.FirSimpleFunction
|
||||
import org.jetbrains.kotlin.fir.expressions.FirExpressionWithSmartcast
|
||||
import org.jetbrains.kotlin.fir.expressions.FirReturnExpression
|
||||
import org.jetbrains.kotlin.fir.expressions.FirWhenExpression
|
||||
import org.jetbrains.kotlin.fir.expressions.isExhaustive
|
||||
import org.jetbrains.kotlin.fir.typeContext
|
||||
import org.jetbrains.kotlin.fir.types.*
|
||||
import org.jetbrains.kotlin.types.SmartcastStability
|
||||
|
||||
object FirFunctionReturnTypeMismatchChecker : FirReturnExpressionChecker() {
|
||||
override fun check(expression: FirReturnExpression, context: CheckerContext, reporter: DiagnosticReporter) {
|
||||
@@ -36,10 +39,23 @@ object FirFunctionReturnTypeMismatchChecker : FirReturnExpressionChecker() {
|
||||
if (resultExpression.isNullLiteral && functionReturnType.nullability == ConeNullability.NOT_NULL) {
|
||||
reporter.reportOn(resultExpression.source, NULL_FOR_NONNULL_TYPE, context)
|
||||
} else {
|
||||
reporter.report(
|
||||
RETURN_TYPE_MISMATCH.on(returnExpressionSource, functionReturnType, returnExpressionType, targetElement),
|
||||
context
|
||||
)
|
||||
if (resultExpression is FirExpressionWithSmartcast && resultExpression.smartcastStability != SmartcastStability.STABLE_VALUE &&
|
||||
isSubtypeForTypeMismatch(typeContext, subtype = resultExpression.smartcastType.coneType, supertype = functionReturnType)
|
||||
) {
|
||||
reporter.reportOn(
|
||||
returnExpressionSource,
|
||||
SMARTCAST_IMPOSSIBLE,
|
||||
functionReturnType,
|
||||
resultExpression,
|
||||
resultExpression.smartcastStability.description,
|
||||
context
|
||||
)
|
||||
} else {
|
||||
reporter.report(
|
||||
RETURN_TYPE_MISMATCH.on(returnExpressionSource, functionReturnType, returnExpressionType, targetElement),
|
||||
context
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -273,6 +273,7 @@ import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.SEALED_SUPERTYPE_
|
||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.SECONDARY_CONSTRUCTOR_WITH_BODY_INSIDE_INLINE_CLASS
|
||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.SETTER_VISIBILITY_INCONSISTENT_WITH_PROPERTY_VISIBILITY
|
||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.SINGLETON_IN_SUPERTYPE
|
||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.SMARTCAST_IMPOSSIBLE
|
||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.SUPERCLASS_NOT_ACCESSIBLE_FROM_INTERFACE
|
||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.SUPERTYPES_FOR_ANNOTATION_CLASS
|
||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.SUPERTYPE_APPEARS_TWICE
|
||||
@@ -634,6 +635,13 @@ class FirDefaultErrorMessages : DefaultErrorMessages.Extension {
|
||||
map.put(UPPER_BOUND_IS_EXTENSION_FUNCTION_TYPE, "Extension function type can not be used as an upper bound")
|
||||
map.put(INCOMPATIBLE_TYPES, "Incompatible types: {0} and {1}", RENDER_TYPE, RENDER_TYPE)
|
||||
map.put(INCOMPATIBLE_TYPES_WARNING, "Potentially incompatible types: {0} and {1}", RENDER_TYPE, RENDER_TYPE)
|
||||
map.put(
|
||||
SMARTCAST_IMPOSSIBLE,
|
||||
"Smart cast to ''{0}'' is impossible, because ''{1}'' is a {2}",
|
||||
RENDER_TYPE,
|
||||
FIR,
|
||||
TO_STRING
|
||||
)
|
||||
|
||||
map.put(
|
||||
TYPE_VARIANCE_CONFLICT,
|
||||
|
||||
@@ -46,6 +46,15 @@ private fun ConeDiagnostic.toFirDiagnostic(
|
||||
val candidate = candidates.first { it.currentApplicability == CandidateApplicability.UNSAFE_CALL }
|
||||
val unsafeCall = candidate.diagnostics.firstIsInstance<UnsafeCall>()
|
||||
mapUnsafeCallError(candidate, unsafeCall, source, qualifiedAccessSource)
|
||||
} else if (this.applicability == CandidateApplicability.UNSTABLE_SMARTCAST) {
|
||||
val unstableSmartcast =
|
||||
this.candidates.first { it.currentApplicability == CandidateApplicability.UNSTABLE_SMARTCAST }.diagnostics.firstIsInstance<UnstableSmartCast>()
|
||||
FirErrors.SMARTCAST_IMPOSSIBLE.on(
|
||||
unstableSmartcast.argument.source,
|
||||
unstableSmartcast.targetType,
|
||||
unstableSmartcast.argument,
|
||||
unstableSmartcast.argument.smartcastStability.description
|
||||
)
|
||||
} else {
|
||||
FirErrors.NONE_APPLICABLE.on(source, this.candidates.map { it.symbol })
|
||||
}
|
||||
@@ -134,8 +143,8 @@ private fun mapInapplicableCandidateError(
|
||||
source: FirSourceElement,
|
||||
qualifiedAccessSource: FirSourceElement?,
|
||||
): List<FirDiagnostic<FirSourceElement>> {
|
||||
// TODO: Need to distinguish SMARTCAST_IMPOSSIBLE
|
||||
return diagnostic.candidate.diagnostics.filter { it.applicability == diagnostic.applicability }.mapNotNull { rootCause ->
|
||||
val genericDiagnostic = FirErrors.INAPPLICABLE_CANDIDATE.on(source, diagnostic.candidate.symbol)
|
||||
val diagnostics = diagnostic.candidate.diagnostics.filter { it.applicability == diagnostic.applicability }.mapNotNull { rootCause ->
|
||||
when (rootCause) {
|
||||
is VarargArgumentOutsideParentheses -> FirErrors.VARARG_OUTSIDE_PARENTHESES.on(
|
||||
rootCause.argument.source ?: qualifiedAccessSource
|
||||
@@ -166,9 +175,21 @@ private fun mapInapplicableCandidateError(
|
||||
is InfixCallOfNonInfixFunction -> FirErrors.INFIX_MODIFIER_REQUIRED.on(source, rootCause.function)
|
||||
is OperatorCallOfNonOperatorFunction ->
|
||||
FirErrors.OPERATOR_MODIFIER_REQUIRED.on(source, rootCause.function, rootCause.function.fir.name.asString())
|
||||
else -> null
|
||||
is UnstableSmartCast -> FirErrors.SMARTCAST_IMPOSSIBLE.on(
|
||||
rootCause.argument.source,
|
||||
rootCause.targetType,
|
||||
rootCause.argument,
|
||||
rootCause.argument.smartcastStability.description
|
||||
)
|
||||
else -> genericDiagnostic
|
||||
}
|
||||
}.ifEmpty { listOf(FirErrors.INAPPLICABLE_CANDIDATE.on(source, diagnostic.candidate.symbol)) }
|
||||
}.distinct()
|
||||
return if (diagnostics.size > 1) {
|
||||
// If there are more specific diagnostics, filter out the generic diagnostic.
|
||||
diagnostics.filter { it != genericDiagnostic }
|
||||
} else {
|
||||
diagnostics
|
||||
}
|
||||
}
|
||||
|
||||
@OptIn(ExperimentalStdlibApi::class)
|
||||
|
||||
@@ -17,10 +17,6 @@ dependencies {
|
||||
|
||||
compileOnly(intellijCoreDep()) { includeJars("intellij-core") }
|
||||
|
||||
testCompileOnly(intellijDep())
|
||||
|
||||
testRuntimeOnly(intellijDep())
|
||||
|
||||
testCompileOnly(project(":kotlin-test:kotlin-test-jvm"))
|
||||
testCompileOnly(project(":kotlin-test:kotlin-test-junit"))
|
||||
testApi(projectTests(":compiler:test-infrastructure"))
|
||||
@@ -39,6 +35,33 @@ dependencies {
|
||||
|
||||
testCompileOnly(intellijCoreDep()) { includeJars("intellij-core") }
|
||||
testRuntimeOnly(intellijCoreDep()) { includeJars("intellij-core") }
|
||||
|
||||
testRuntimeOnly(intellijDep()) {
|
||||
includeJars(
|
||||
"jps-model",
|
||||
"extensions",
|
||||
"util",
|
||||
"platform-api",
|
||||
"platform-impl",
|
||||
"idea",
|
||||
"guava",
|
||||
"trove4j",
|
||||
"asm-all",
|
||||
"log4j",
|
||||
"jdom",
|
||||
"streamex",
|
||||
"bootstrap",
|
||||
"jna",
|
||||
rootProject = rootProject
|
||||
)
|
||||
}
|
||||
|
||||
Platform[202] {
|
||||
testRuntimeOnly(intellijDep()) { includeJars("intellij-deps-fastutil-8.3.1-1") }
|
||||
}
|
||||
Platform[203].orHigher {
|
||||
testRuntimeOnly(intellijDep()) { includeJars("intellij-deps-fastutil-8.3.1-3") }
|
||||
}
|
||||
}
|
||||
|
||||
val generationRoot = projectDir.resolve("tests-gen")
|
||||
|
||||
@@ -31,6 +31,7 @@ import org.jetbrains.kotlin.ir.util.classId
|
||||
import org.jetbrains.kotlin.ir.util.coerceToUnitIfNeeded
|
||||
import org.jetbrains.kotlin.ir.util.parentAsClass
|
||||
import org.jetbrains.kotlin.types.AbstractTypeChecker
|
||||
import org.jetbrains.kotlin.types.SmartcastStability
|
||||
|
||||
class Fir2IrImplicitCastInserter(
|
||||
private val components: Fir2IrComponents,
|
||||
@@ -274,7 +275,11 @@ class Fir2IrImplicitCastInserter(
|
||||
}
|
||||
|
||||
override fun visitExpressionWithSmartcast(expressionWithSmartcast: FirExpressionWithSmartcast, data: IrElement): IrExpression {
|
||||
return implicitCastOrExpression(data as IrExpression, expressionWithSmartcast.typeRef)
|
||||
return if (expressionWithSmartcast.smartcastStability == SmartcastStability.STABLE_VALUE) {
|
||||
implicitCastOrExpression(data as IrExpression, expressionWithSmartcast.typeRef)
|
||||
} else {
|
||||
data as IrExpression
|
||||
}
|
||||
}
|
||||
|
||||
override fun visitExpressionWithSmartcastToNull(
|
||||
|
||||
@@ -2446,6 +2446,12 @@ public class FirBlackBoxCodegenTestGenerated extends AbstractFirBlackBoxCodegenT
|
||||
KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("compiler/testData/codegen/box/callableReference"), Pattern.compile("^(.+)\\.kt$"), null, TargetBackend.JVM_IR, true);
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("arrayConstructor.kt")
|
||||
public void testArrayConstructor() throws Exception {
|
||||
runTest("compiler/testData/codegen/box/callableReference/arrayConstructor.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("arrayConstructorArgument.kt")
|
||||
public void testArrayConstructorArgument() throws Exception {
|
||||
@@ -15282,6 +15288,12 @@ public class FirBlackBoxCodegenTestGenerated extends AbstractFirBlackBoxCodegenT
|
||||
runTest("compiler/testData/codegen/box/extensionProperties/inClassWithSetter.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("kt46952.kt")
|
||||
public void testKt46952() throws Exception {
|
||||
runTest("compiler/testData/codegen/box/extensionProperties/kt46952.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("kt9897.kt")
|
||||
public void testKt9897() throws Exception {
|
||||
@@ -17587,18 +17599,78 @@ public class FirBlackBoxCodegenTestGenerated extends AbstractFirBlackBoxCodegenT
|
||||
runTest("compiler/testData/codegen/box/inference/builderInference/callableReferencesProperCompletion.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("capturedTypes.kt")
|
||||
public void testCapturedTypes() throws Exception {
|
||||
runTest("compiler/testData/codegen/box/inference/builderInference/capturedTypes.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("commonSuperType.kt")
|
||||
public void testCommonSuperType() throws Exception {
|
||||
runTest("compiler/testData/codegen/box/inference/builderInference/commonSuperType.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("commonSuperTypeContravariant.kt")
|
||||
public void testCommonSuperTypeContravariant() throws Exception {
|
||||
runTest("compiler/testData/codegen/box/inference/builderInference/commonSuperTypeContravariant.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("commonSuperTypeCovariant.kt")
|
||||
public void testCommonSuperTypeCovariant() throws Exception {
|
||||
runTest("compiler/testData/codegen/box/inference/builderInference/commonSuperTypeCovariant.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("commonSuperTypeInvariant.kt")
|
||||
public void testCommonSuperTypeInvariant() throws Exception {
|
||||
runTest("compiler/testData/codegen/box/inference/builderInference/commonSuperTypeInvariant.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("commonSuperTypeNullable.kt")
|
||||
public void testCommonSuperTypeNullable() throws Exception {
|
||||
runTest("compiler/testData/codegen/box/inference/builderInference/commonSuperTypeNullable.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("intersect.kt")
|
||||
public void testIntersect() throws Exception {
|
||||
runTest("compiler/testData/codegen/box/inference/builderInference/intersect.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("kt41164.kt")
|
||||
public void testKt41164() throws Exception {
|
||||
runTest("compiler/testData/codegen/box/inference/builderInference/kt41164.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("labaledCall.kt")
|
||||
public void testLabaledCall() throws Exception {
|
||||
runTest("compiler/testData/codegen/box/inference/builderInference/labaledCall.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("lackOfNullCheckOnNullableInsideBuild.kt")
|
||||
public void testLackOfNullCheckOnNullableInsideBuild() throws Exception {
|
||||
runTest("compiler/testData/codegen/box/inference/builderInference/lackOfNullCheckOnNullableInsideBuild.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("memberScope.kt")
|
||||
public void testMemberScope() throws Exception {
|
||||
runTest("compiler/testData/codegen/box/inference/builderInference/memberScope.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("nullability.kt")
|
||||
public void testNullability() throws Exception {
|
||||
runTest("compiler/testData/codegen/box/inference/builderInference/nullability.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("propagateInferenceSessionIntoDeclarationAnalyzers.kt")
|
||||
public void testPropagateInferenceSessionIntoDeclarationAnalyzers() throws Exception {
|
||||
@@ -17617,6 +17689,18 @@ public class FirBlackBoxCodegenTestGenerated extends AbstractFirBlackBoxCodegenT
|
||||
runTest("compiler/testData/codegen/box/inference/builderInference/specialCallsWithCallableReferencesDontCareTypeInBlockExpression.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("specialCallsWithCallableReferencesDontCareTypeInBlockExression.kt")
|
||||
public void testSpecialCallsWithCallableReferencesDontCareTypeInBlockExression() throws Exception {
|
||||
runTest("compiler/testData/codegen/box/inference/builderInference/specialCallsWithCallableReferencesDontCareTypeInBlockExression.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("specialCallsWithCallableReferencesDontRewriteAtSlice.kt")
|
||||
public void testSpecialCallsWithCallableReferencesDontRewriteAtSlice() throws Exception {
|
||||
runTest("compiler/testData/codegen/box/inference/builderInference/specialCallsWithCallableReferencesDontRewriteAtSlice.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("specialCallsWithCallableReferencesErrorType.kt")
|
||||
public void testSpecialCallsWithCallableReferencesErrorType() throws Exception {
|
||||
@@ -17682,6 +17766,12 @@ public class FirBlackBoxCodegenTestGenerated extends AbstractFirBlackBoxCodegenT
|
||||
public void testTopDownCompletionWithTwoBuilderInferenceCalls() throws Exception {
|
||||
runTest("compiler/testData/codegen/box/inference/builderInference/topDownCompletionWithTwoBuilderInferenceCalls.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("withExpectedType.kt")
|
||||
public void testWithExpectedType() throws Exception {
|
||||
runTest("compiler/testData/codegen/box/inference/builderInference/withExpectedType.kt");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -21133,6 +21223,12 @@ public class FirBlackBoxCodegenTestGenerated extends AbstractFirBlackBoxCodegenT
|
||||
runTest("compiler/testData/codegen/box/invokedynamic/sam/genericLambdaSignature.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("inlineOnly.kt")
|
||||
public void testInlineOnly() throws Exception {
|
||||
runTest("compiler/testData/codegen/box/invokedynamic/sam/inlineOnly.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("insideInitBlock.kt")
|
||||
public void testInsideInitBlock() throws Exception {
|
||||
@@ -27908,6 +28004,18 @@ public class FirBlackBoxCodegenTestGenerated extends AbstractFirBlackBoxCodegenT
|
||||
runTest("compiler/testData/codegen/box/primitiveTypes/kt446.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("kt46864_double.kt")
|
||||
public void testKt46864_double() throws Exception {
|
||||
runTest("compiler/testData/codegen/box/primitiveTypes/kt46864_double.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("kt46864_long.kt")
|
||||
public void testKt46864_long() throws Exception {
|
||||
runTest("compiler/testData/codegen/box/primitiveTypes/kt46864_long.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("kt518.kt")
|
||||
public void testKt518() throws Exception {
|
||||
@@ -40552,6 +40660,12 @@ public class FirBlackBoxCodegenTestGenerated extends AbstractFirBlackBoxCodegenT
|
||||
public void testKt46578_propertyRef() throws Exception {
|
||||
runTest("compiler/testData/codegen/box/syntheticAccessors/protectedJavaFieldAccessor/kt46578_propertyRef.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("kt46900_jkk_inheritance.kt")
|
||||
public void testKt46900_jkk_inheritance() throws Exception {
|
||||
runTest("compiler/testData/codegen/box/syntheticAccessors/protectedJavaFieldAccessor/kt46900_jkk_inheritance.kt");
|
||||
}
|
||||
}
|
||||
|
||||
@Nested
|
||||
|
||||
@@ -131,7 +131,7 @@ class JvmMappedScope(
|
||||
|
||||
// NOTE: No-arg constructors
|
||||
@OptIn(ExperimentalStdlibApi::class)
|
||||
private val additionalHiddenConstructors = buildSet {
|
||||
private val additionalHiddenConstructors = buildSet<String> {
|
||||
// kotlin.text.String pseudo-constructors should be used instead of java.lang.String constructors
|
||||
listOf(
|
||||
"",
|
||||
|
||||
@@ -10,7 +10,10 @@ import org.jetbrains.kotlin.builtins.functions.FunctionClassKind
|
||||
import org.jetbrains.kotlin.descriptors.ClassKind
|
||||
import org.jetbrains.kotlin.fir.*
|
||||
import org.jetbrains.kotlin.fir.declarations.*
|
||||
import org.jetbrains.kotlin.fir.diagnostics.*
|
||||
import org.jetbrains.kotlin.fir.diagnostics.ConeDiagnostic
|
||||
import org.jetbrains.kotlin.fir.diagnostics.ConeSimpleDiagnostic
|
||||
import org.jetbrains.kotlin.fir.diagnostics.ConeStubDiagnostic
|
||||
import org.jetbrains.kotlin.fir.diagnostics.DiagnosticKind
|
||||
import org.jetbrains.kotlin.fir.expressions.*
|
||||
import org.jetbrains.kotlin.fir.expressions.builder.*
|
||||
import org.jetbrains.kotlin.fir.references.FirErrorNamedReference
|
||||
@@ -23,12 +26,12 @@ import org.jetbrains.kotlin.fir.resolve.calls.ImplicitDispatchReceiverValue
|
||||
import org.jetbrains.kotlin.fir.resolve.diagnostics.ConeUnresolvedNameError
|
||||
import org.jetbrains.kotlin.fir.resolve.inference.inferenceComponents
|
||||
import org.jetbrains.kotlin.fir.resolve.inference.isBuiltinFunctionalType
|
||||
import org.jetbrains.kotlin.fir.resolve.providers.*
|
||||
import org.jetbrains.kotlin.fir.resolve.providers.getSymbolByTypeRef
|
||||
import org.jetbrains.kotlin.fir.resolve.transformers.body.resolve.resultType
|
||||
import org.jetbrains.kotlin.fir.resolve.transformers.ensureResolved
|
||||
import org.jetbrains.kotlin.fir.scopes.impl.delegatedWrapperData
|
||||
import org.jetbrains.kotlin.fir.scopes.impl.importedFromObjectData
|
||||
import org.jetbrains.kotlin.fir.symbols.*
|
||||
import org.jetbrains.kotlin.fir.symbols.AbstractFirBasedSymbol
|
||||
import org.jetbrains.kotlin.fir.symbols.impl.*
|
||||
import org.jetbrains.kotlin.fir.types.*
|
||||
import org.jetbrains.kotlin.fir.types.builder.buildErrorTypeRef
|
||||
@@ -36,6 +39,7 @@ import org.jetbrains.kotlin.fir.types.builder.buildResolvedTypeRef
|
||||
import org.jetbrains.kotlin.fir.types.impl.ConeClassLikeTypeImpl
|
||||
import org.jetbrains.kotlin.name.*
|
||||
import org.jetbrains.kotlin.resolve.ForbiddenNamedArgumentsTarget
|
||||
import org.jetbrains.kotlin.types.SmartcastStability
|
||||
|
||||
fun List<FirQualifierPart>.toTypeProjections(): Array<ConeTypeProjection> =
|
||||
asReversed().flatMap { it.typeArgumentList.typeArguments.map { typeArgument -> typeArgument.toConeTypeProjection() } }.toTypedArray()
|
||||
@@ -246,7 +250,8 @@ private fun BodyResolveComponents.typeFromSymbol(symbol: AbstractFirBasedSymbol<
|
||||
fun BodyResolveComponents.transformQualifiedAccessUsingSmartcastInfo(
|
||||
qualifiedAccessExpression: FirQualifiedAccessExpression
|
||||
): FirQualifiedAccessExpression {
|
||||
val typesFromSmartCast = dataFlowAnalyzer.getTypeUsingSmartcastInfo(qualifiedAccessExpression) ?: return qualifiedAccessExpression
|
||||
val (stability, 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.
|
||||
@@ -267,9 +272,11 @@ fun BodyResolveComponents.transformQualifiedAccessUsingSmartcastInfo(
|
||||
return buildExpressionWithSmartcastToNull {
|
||||
originalExpression = qualifiedAccessExpression
|
||||
// TODO: Use Nothing? during resolution?
|
||||
typeRef = intersectedTypeRefWithoutNullableNothing
|
||||
smartcastType = intersectedTypeRefWithoutNullableNothing
|
||||
// NB: Nothing? in types from smartcast in DFA is recorded here (and the expression kind itself).
|
||||
this.typesFromSmartCast = typesFromSmartCast
|
||||
// TODO: differentiate capture local variable
|
||||
this.smartcastStability = stability.impliedSmartcastStability ?: SmartcastStability.STABLE_VALUE
|
||||
}
|
||||
}
|
||||
val allTypes = typesFromSmartCast.also {
|
||||
@@ -285,8 +292,10 @@ fun BodyResolveComponents.transformQualifiedAccessUsingSmartcastInfo(
|
||||
}
|
||||
return buildExpressionWithSmartcast {
|
||||
originalExpression = qualifiedAccessExpression
|
||||
typeRef = intersectedTypeRef
|
||||
smartcastType = intersectedTypeRef
|
||||
this.typesFromSmartCast = typesFromSmartCast
|
||||
// TODO: differentiate capture local variable
|
||||
this.smartcastStability = stability.impliedSmartcastStability ?: SmartcastStability.STABLE_VALUE
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -10,9 +10,11 @@ import org.jetbrains.kotlin.fir.declarations.FirAnonymousObject
|
||||
import org.jetbrains.kotlin.fir.declarations.FirClass
|
||||
import org.jetbrains.kotlin.fir.declarations.FirRegularClass
|
||||
import org.jetbrains.kotlin.fir.declarations.FirResolvePhase
|
||||
import org.jetbrains.kotlin.fir.expressions.FirExpressionWithSmartcast
|
||||
import org.jetbrains.kotlin.fir.resolve.substitution.substitutorByMap
|
||||
import org.jetbrains.kotlin.fir.resolve.transformers.ensureResolved
|
||||
import org.jetbrains.kotlin.fir.scopes.FakeOverrideTypeCalculator
|
||||
import org.jetbrains.kotlin.fir.scopes.FirUnstableSmartcastTypeScope
|
||||
import org.jetbrains.kotlin.fir.scopes.FirTypeScope
|
||||
import org.jetbrains.kotlin.fir.scopes.impl.FirScopeWithFakeOverrideTypeCalculator
|
||||
import org.jetbrains.kotlin.fir.scopes.impl.FirStandardOverrideChecker
|
||||
@@ -25,6 +27,25 @@ import org.jetbrains.kotlin.fir.types.*
|
||||
import org.jetbrains.kotlin.fir.types.impl.ConeClassLikeTypeImpl
|
||||
import org.jetbrains.kotlin.fir.types.impl.ConeTypeParameterTypeImpl
|
||||
import org.jetbrains.kotlin.name.ClassId
|
||||
import org.jetbrains.kotlin.types.SmartcastStability
|
||||
|
||||
fun FirExpressionWithSmartcast.smartcastScope(
|
||||
useSiteSession: FirSession,
|
||||
scopeSession: ScopeSession
|
||||
): FirTypeScope? {
|
||||
val smartcastType = smartcastType.coneType
|
||||
val smartcastScope = smartcastType.scope(useSiteSession, scopeSession, FakeOverrideTypeCalculator.DoNothing)
|
||||
if (smartcastStability == SmartcastStability.STABLE_VALUE) {
|
||||
return smartcastScope
|
||||
}
|
||||
val originalScope = originalType.coneType.scope(useSiteSession, scopeSession, FakeOverrideTypeCalculator.DoNothing)
|
||||
?: return smartcastScope
|
||||
|
||||
if (smartcastScope == null) {
|
||||
return originalScope
|
||||
}
|
||||
return FirUnstableSmartcastTypeScope(smartcastType, smartcastScope, originalScope)
|
||||
}
|
||||
|
||||
fun ConeKotlinType.scope(
|
||||
useSiteSession: FirSession,
|
||||
|
||||
@@ -30,9 +30,9 @@ import org.jetbrains.kotlin.name.Name
|
||||
import org.jetbrains.kotlin.name.StandardClassIds
|
||||
import org.jetbrains.kotlin.resolve.calls.inference.ConstraintSystemBuilder
|
||||
import org.jetbrains.kotlin.resolve.calls.inference.addSubtypeConstraintIfCompatible
|
||||
import org.jetbrains.kotlin.resolve.calls.inference.model.ConstraintPosition
|
||||
import org.jetbrains.kotlin.resolve.calls.inference.model.SimpleConstraintSystemConstraintPosition
|
||||
import org.jetbrains.kotlin.types.AbstractTypeChecker
|
||||
import org.jetbrains.kotlin.types.SmartcastStability
|
||||
import org.jetbrains.kotlin.types.model.CaptureStatus
|
||||
import org.jetbrains.kotlin.types.model.TypeSystemCommonSuperTypesContext
|
||||
import org.jetbrains.kotlin.utils.addToStdlib.runIf
|
||||
@@ -358,17 +358,7 @@ private fun checkApplicabilityForArgumentType(
|
||||
) {
|
||||
if (expectedType == null) return
|
||||
|
||||
fun unstableSmartCastOrSubtypeError(
|
||||
unstableType: ConeKotlinType?,
|
||||
actualExpectedType: ConeKotlinType,
|
||||
position: ConstraintPosition
|
||||
): ResolutionDiagnostic {
|
||||
if (unstableType != null) {
|
||||
if (csBuilder.addSubtypeConstraintIfCompatible(unstableType, actualExpectedType, position)) {
|
||||
return UnstableSmartCast.ResolutionError(argument, unstableType)
|
||||
}
|
||||
}
|
||||
|
||||
fun subtypeError(actualExpectedType: ConeKotlinType): ResolutionDiagnostic {
|
||||
if (argument.isNullLiteral && actualExpectedType.nullability == ConeNullability.NOT_NULL) {
|
||||
return NullForNotNullType(argument)
|
||||
}
|
||||
@@ -406,14 +396,17 @@ private fun checkApplicabilityForArgumentType(
|
||||
}
|
||||
|
||||
if (!csBuilder.addSubtypeConstraintIfCompatible(argumentType, expectedType, position)) {
|
||||
val smartcastExpression = argument as? FirExpressionWithSmartcast
|
||||
if (smartcastExpression != null && smartcastExpression.smartcastStability != SmartcastStability.STABLE_VALUE) {
|
||||
val unstableType = smartcastExpression.smartcastType.coneType
|
||||
if (csBuilder.addSubtypeConstraintIfCompatible(unstableType, expectedType, position)) {
|
||||
sink.reportDiagnostic(UnstableSmartCast(smartcastExpression, expectedType))
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
if (!isReceiver) {
|
||||
sink.reportDiagnosticIfNotNull(
|
||||
unstableSmartCastOrSubtypeError(
|
||||
unstableType = null, // TODO: handle unstable smartcasts
|
||||
expectedType,
|
||||
position
|
||||
)
|
||||
)
|
||||
sink.reportDiagnosticIfNotNull(subtypeError(expectedType))
|
||||
return
|
||||
}
|
||||
|
||||
|
||||
@@ -8,6 +8,7 @@ package org.jetbrains.kotlin.fir.resolve.calls
|
||||
import org.jetbrains.kotlin.fir.FirSession
|
||||
import org.jetbrains.kotlin.fir.diagnostics.ConeIntermediateDiagnostic
|
||||
import org.jetbrains.kotlin.fir.expressions.FirExpression
|
||||
import org.jetbrains.kotlin.fir.expressions.FirExpressionWithSmartcast
|
||||
import org.jetbrains.kotlin.fir.expressions.FirThisReceiverExpression
|
||||
import org.jetbrains.kotlin.fir.expressions.builder.buildExpressionWithSmartcast
|
||||
import org.jetbrains.kotlin.fir.expressions.builder.buildThisReceiverExpression
|
||||
@@ -16,6 +17,7 @@ import org.jetbrains.kotlin.fir.renderWithType
|
||||
import org.jetbrains.kotlin.fir.resolve.ScopeSession
|
||||
import org.jetbrains.kotlin.fir.resolve.constructType
|
||||
import org.jetbrains.kotlin.fir.resolve.scope
|
||||
import org.jetbrains.kotlin.fir.resolve.smartcastScope
|
||||
import org.jetbrains.kotlin.fir.resolvedTypeFromPrototype
|
||||
import org.jetbrains.kotlin.fir.scopes.FakeOverrideTypeCalculator
|
||||
import org.jetbrains.kotlin.fir.scopes.FirTypeScope
|
||||
@@ -27,6 +29,7 @@ import org.jetbrains.kotlin.fir.types.ConeKotlinType
|
||||
import org.jetbrains.kotlin.fir.types.builder.buildResolvedTypeRef
|
||||
import org.jetbrains.kotlin.fir.types.coneType
|
||||
import org.jetbrains.kotlin.fir.types.coneTypeSafe
|
||||
import org.jetbrains.kotlin.types.SmartcastStability
|
||||
|
||||
interface Receiver
|
||||
|
||||
@@ -56,7 +59,11 @@ abstract class AbstractExplicitReceiverValue<E : FirExpression> : AbstractExplic
|
||||
|
||||
class ExpressionReceiverValue(
|
||||
override val explicitReceiver: FirExpression
|
||||
) : AbstractExplicitReceiverValue<FirExpression>(), ReceiverValue
|
||||
) : AbstractExplicitReceiverValue<FirExpression>(), ReceiverValue {
|
||||
override fun scope(useSiteSession: FirSession, scopeSession: ScopeSession): FirTypeScope? =
|
||||
(receiverExpression as? FirExpressionWithSmartcast)?.smartcastScope(useSiteSession, scopeSession)
|
||||
?: type.scope(useSiteSession, scopeSession, FakeOverrideTypeCalculator.DoNothing)
|
||||
}
|
||||
|
||||
sealed class ImplicitReceiverValue<S : AbstractFirBasedSymbol<*>>(
|
||||
val boundSymbol: S,
|
||||
@@ -89,8 +96,9 @@ sealed class ImplicitReceiverValue<S : AbstractFirBasedSymbol<*>>(
|
||||
} else {
|
||||
buildExpressionWithSmartcast {
|
||||
originalExpression = originalReceiverExpression
|
||||
typeRef = originalReceiverExpression.typeRef.resolvedTypeFromPrototype(type)
|
||||
smartcastType = originalReceiverExpression.typeRef.resolvedTypeFromPrototype(type)
|
||||
typesFromSmartCast = listOf(type)
|
||||
smartcastStability = SmartcastStability.STABLE_VALUE
|
||||
}
|
||||
}
|
||||
implicitScope = type.scope(useSiteSession, scopeSession, FakeOverrideTypeCalculator.DoNothing)
|
||||
|
||||
@@ -8,6 +8,7 @@ package org.jetbrains.kotlin.fir.resolve.calls
|
||||
import org.jetbrains.kotlin.fir.declarations.FirFunction
|
||||
import org.jetbrains.kotlin.fir.declarations.FirValueParameter
|
||||
import org.jetbrains.kotlin.fir.expressions.FirExpression
|
||||
import org.jetbrains.kotlin.fir.expressions.FirExpressionWithSmartcast
|
||||
import org.jetbrains.kotlin.fir.expressions.FirNamedArgumentExpression
|
||||
import org.jetbrains.kotlin.fir.symbols.impl.FirNamedFunctionSymbol
|
||||
import org.jetbrains.kotlin.fir.types.ConeKotlinType
|
||||
@@ -74,21 +75,7 @@ object LowerPriorityToPreserveCompatibilityDiagnostic : ResolutionDiagnostic(RES
|
||||
|
||||
object CandidateChosenUsingOverloadResolutionByLambdaAnnotation : ResolutionDiagnostic(RESOLVED)
|
||||
|
||||
sealed class UnstableSmartCast(
|
||||
val argument: FirExpression,
|
||||
val targetType: ConeKotlinType,
|
||||
applicability: CandidateApplicability
|
||||
) : ResolutionDiagnostic(applicability) {
|
||||
class ResolutionError(
|
||||
argument: FirExpression,
|
||||
targetType: ConeKotlinType,
|
||||
) : UnstableSmartCast(argument, targetType, MAY_THROW_RUNTIME_ERROR)
|
||||
|
||||
class DiagnosticError(
|
||||
argument: FirExpression,
|
||||
targetType: ConeKotlinType,
|
||||
) : UnstableSmartCast(argument, targetType, RESOLVED_WITH_ERROR)
|
||||
}
|
||||
class UnstableSmartCast(val argument: FirExpressionWithSmartcast, val targetType: ConeKotlinType) : ResolutionDiagnostic(UNSTABLE_SMARTCAST)
|
||||
|
||||
class ArgumentTypeMismatch(
|
||||
val expectedType: ConeKotlinType,
|
||||
|
||||
@@ -26,6 +26,8 @@ import org.jetbrains.kotlin.name.FqName
|
||||
import org.jetbrains.kotlin.name.Name
|
||||
import org.jetbrains.kotlin.resolve.calls.tasks.ExplicitReceiverKind.*
|
||||
import org.jetbrains.kotlin.types.AbstractNullabilityChecker
|
||||
import org.jetbrains.kotlin.types.AbstractTypeChecker
|
||||
import org.jetbrains.kotlin.types.SmartcastStability
|
||||
|
||||
abstract class ResolutionStage {
|
||||
abstract suspend fun check(candidate: Candidate, callInfo: CallInfo, sink: CheckerSink, context: ResolutionContext)
|
||||
@@ -105,6 +107,19 @@ object CheckDispatchReceiver : ResolutionStage() {
|
||||
}
|
||||
}
|
||||
|
||||
if (explicitReceiverExpression is FirExpressionWithSmartcast && explicitReceiverExpression.smartcastStability != SmartcastStability.STABLE_VALUE) {
|
||||
val expectedDispatchReceiverType = (candidate.symbol.fir as? FirCallableMemberDeclaration)?.dispatchReceiverType
|
||||
if (expectedDispatchReceiverType != null &&
|
||||
!AbstractTypeChecker.isSubtypeOf(
|
||||
context.session.typeContext,
|
||||
explicitReceiverExpression.originalType.coneType,
|
||||
expectedDispatchReceiverType
|
||||
)
|
||||
) {
|
||||
sink.yieldDiagnostic(UnstableSmartCast(explicitReceiverExpression, expectedDispatchReceiverType))
|
||||
}
|
||||
}
|
||||
|
||||
val dispatchReceiverValueType = candidate.dispatchReceiverValue?.type ?: return
|
||||
|
||||
if (!AbstractNullabilityChecker.isSubtypeOfAny(context.session.typeContext, dispatchReceiverValueType)) {
|
||||
|
||||
@@ -16,24 +16,27 @@ import org.jetbrains.kotlin.fir.declarations.*
|
||||
import org.jetbrains.kotlin.fir.expressions.*
|
||||
import org.jetbrains.kotlin.fir.references.FirControlFlowGraphReference
|
||||
import org.jetbrains.kotlin.fir.references.FirResolvedNamedReference
|
||||
import org.jetbrains.kotlin.fir.resolve.*
|
||||
import org.jetbrains.kotlin.fir.resolve.PersistentImplicitReceiverStack
|
||||
import org.jetbrains.kotlin.fir.resolve.ResolutionMode
|
||||
import org.jetbrains.kotlin.fir.resolve.dfa.cfg.*
|
||||
import org.jetbrains.kotlin.fir.resolve.dfa.contracts.buildContractFir
|
||||
import org.jetbrains.kotlin.fir.resolve.dfa.contracts.createArgumentsMapping
|
||||
import org.jetbrains.kotlin.fir.resolve.fullyExpandedType
|
||||
import org.jetbrains.kotlin.fir.resolve.inference.inferenceComponents
|
||||
import org.jetbrains.kotlin.fir.resolve.substitution.ConeSubstitutor
|
||||
import org.jetbrains.kotlin.fir.resolve.substitution.ConeSubstitutorByMap
|
||||
import org.jetbrains.kotlin.fir.resolve.toSymbol
|
||||
import org.jetbrains.kotlin.fir.resolve.transformers.body.resolve.FirAbstractBodyResolveTransformer
|
||||
import org.jetbrains.kotlin.fir.resolve.transformers.body.resolve.resultType
|
||||
import org.jetbrains.kotlin.fir.symbols.AbstractFirBasedSymbol
|
||||
import org.jetbrains.kotlin.fir.symbols.impl.FirTypeParameterSymbol
|
||||
import org.jetbrains.kotlin.name.CallableId
|
||||
import org.jetbrains.kotlin.name.StandardClassIds
|
||||
import org.jetbrains.kotlin.fir.symbols.impl.FirVariableSymbol
|
||||
import org.jetbrains.kotlin.fir.types.*
|
||||
import org.jetbrains.kotlin.fir.visitors.transformSingle
|
||||
import org.jetbrains.kotlin.name.CallableId
|
||||
import org.jetbrains.kotlin.name.FqName
|
||||
import org.jetbrains.kotlin.name.Name
|
||||
import org.jetbrains.kotlin.name.StandardClassIds
|
||||
import org.jetbrains.kotlin.types.ConstantValueKind
|
||||
import org.jetbrains.kotlin.utils.addIfNotNull
|
||||
|
||||
@@ -159,7 +162,7 @@ abstract class FirDataFlowAnalyzer<FLOW : Flow>(
|
||||
|
||||
// ----------------------------------- Requests -----------------------------------
|
||||
|
||||
fun getTypeUsingSmartcastInfo(qualifiedAccessExpression: FirQualifiedAccessExpression): MutableList<ConeKotlinType>? {
|
||||
fun getTypeUsingSmartcastInfo(qualifiedAccessExpression: FirQualifiedAccessExpression): Pair<PropertyStability, MutableList<ConeKotlinType>>? {
|
||||
/*
|
||||
* DataFlowAnalyzer holds variables only for declarations that have some smartcast (or can have)
|
||||
* If there is no useful information there is no data flow variable also
|
||||
@@ -167,13 +170,14 @@ abstract class FirDataFlowAnalyzer<FLOW : Flow>(
|
||||
val symbol: AbstractFirBasedSymbol<*> = qualifiedAccessExpression.symbol ?: return null
|
||||
val flow = graphBuilder.lastNode.flow
|
||||
var variable = variableStorage.getRealVariableWithoutUnwrappingAlias(symbol, qualifiedAccessExpression, flow) ?: return null
|
||||
val stability = variable.stability
|
||||
val result = mutableListOf<ConeKotlinType>()
|
||||
flow.directAliasMap[variable]?.let {
|
||||
result.addIfNotNull(it.originalType)
|
||||
variable = it.variable
|
||||
}
|
||||
flow.getTypeStatement(variable)?.exactType?.let { result += it }
|
||||
return result.takeIf { it.isNotEmpty() }
|
||||
return result.takeIf { it.isNotEmpty() }?.let { stability to it }
|
||||
}
|
||||
|
||||
fun returnExpressionsOfAnonymousFunction(function: FirAnonymousFunction): Collection<FirStatement> {
|
||||
@@ -441,7 +445,7 @@ abstract class FirDataFlowAnalyzer<FLOW : Flow>(
|
||||
val operandVariable = variableStorage.getOrCreateVariable(node.previousFlow, operand)
|
||||
// expression == const -> expression != null
|
||||
flow.addImplication((expressionVariable eq isEq) implies (operandVariable notEq null))
|
||||
if (operandVariable is RealVariable) {
|
||||
if (operandVariable.isReal()) {
|
||||
flow.addImplication((expressionVariable eq isEq) implies (operandVariable typeEq any))
|
||||
}
|
||||
|
||||
@@ -820,7 +824,7 @@ abstract class FirDataFlowAnalyzer<FLOW : Flow>(
|
||||
?: return@let
|
||||
|
||||
val variable = variableStorage.getOrCreateVariable(flow, receiver)
|
||||
if (variable is RealVariable) {
|
||||
if (variable.isReal()) {
|
||||
if (shouldFork) {
|
||||
flow = logicSystem.forkFlow(flow)
|
||||
}
|
||||
@@ -1006,7 +1010,12 @@ abstract class FirDataFlowAnalyzer<FLOW : Flow>(
|
||||
assignment: FirVariableAssignment?
|
||||
) {
|
||||
val flow = node.flow
|
||||
val propertyVariable = variableStorage.getOrCreateRealVariableWithoutUnwrappingAlias(flow, property.symbol, assignment ?: property)
|
||||
val propertyVariable = variableStorage.getOrCreateRealVariableWithoutUnwrappingAlias(
|
||||
flow,
|
||||
property.symbol,
|
||||
assignment ?: property,
|
||||
if (property.isVal) PropertyStability.STABLE_VALUE else PropertyStability.LOCAL_VAR
|
||||
)
|
||||
val isAssignment = assignment != null
|
||||
if (isAssignment) {
|
||||
logicSystem.removeLocalVariableAlias(flow, propertyVariable)
|
||||
@@ -1014,13 +1023,21 @@ abstract class FirDataFlowAnalyzer<FLOW : Flow>(
|
||||
logicSystem.recordNewAssignment(flow, propertyVariable, context.newAssignmentIndex())
|
||||
}
|
||||
|
||||
variableStorage.getOrCreateRealVariable(flow, initializer.symbol, initializer)?.let { initializerVariable ->
|
||||
logicSystem.addLocalVariableAlias(
|
||||
flow, propertyVariable,
|
||||
RealVariableAndType(initializerVariable, initializer.coneType)
|
||||
)
|
||||
// node.flow.addImplication((propertyVariable notEq null) implies (initializerVariable notEq null))
|
||||
}
|
||||
variableStorage.getOrCreateRealVariable(flow, initializer.symbol, initializer)
|
||||
?.let { initializerVariable ->
|
||||
// TODO: handle capture variable
|
||||
if ((initializerVariable.stability == PropertyStability.STABLE_VALUE || initializerVariable.stability == PropertyStability.LOCAL_VAR) &&
|
||||
(propertyVariable.stability == PropertyStability.STABLE_VALUE || propertyVariable.stability == PropertyStability.LOCAL_VAR)
|
||||
) {
|
||||
logicSystem.addLocalVariableAlias(
|
||||
flow, propertyVariable,
|
||||
RealVariableAndType(initializerVariable, initializer.coneType)
|
||||
)
|
||||
// node.flow.addImplication((propertyVariable notEq null) implies (initializerVariable notEq null))
|
||||
} else {
|
||||
logicSystem.replaceVariableFromConditionInStatements(flow, initializerVariable, propertyVariable)
|
||||
}
|
||||
}
|
||||
|
||||
variableStorage.getSyntheticVariable(initializer)?.let { initializerVariable ->
|
||||
/*
|
||||
|
||||
@@ -8,7 +8,9 @@ package org.jetbrains.kotlin.fir.resolve.dfa
|
||||
import org.jetbrains.kotlin.descriptors.Modality
|
||||
import org.jetbrains.kotlin.fir.FirElement
|
||||
import org.jetbrains.kotlin.fir.FirSession
|
||||
import org.jetbrains.kotlin.fir.declarations.FirAnonymousObject
|
||||
import org.jetbrains.kotlin.fir.declarations.FirProperty
|
||||
import org.jetbrains.kotlin.fir.declarations.FirRegularClass
|
||||
import org.jetbrains.kotlin.fir.declarations.impl.FirDefaultPropertyAccessor
|
||||
import org.jetbrains.kotlin.fir.declarations.modality
|
||||
import org.jetbrains.kotlin.fir.expressions.*
|
||||
@@ -34,14 +36,24 @@ class VariableStorage(private val session: FirSession) {
|
||||
|
||||
fun clear(): VariableStorage = VariableStorage(session)
|
||||
|
||||
fun getOrCreateRealVariableWithoutUnwrappingAlias(flow: Flow, symbol: AbstractFirBasedSymbol<*>, fir: FirElement): RealVariable {
|
||||
fun getOrCreateRealVariableWithoutUnwrappingAlias(
|
||||
flow: Flow,
|
||||
symbol: AbstractFirBasedSymbol<*>,
|
||||
fir: FirElement,
|
||||
stability: PropertyStability
|
||||
): RealVariable {
|
||||
val realFir = fir.unwrapElement()
|
||||
val identifier = getIdentifierBySymbol(flow, symbol, realFir)
|
||||
return _realVariables.getOrPut(identifier) { createRealVariableInternal(flow, identifier, realFir) }
|
||||
return _realVariables.getOrPut(identifier) { createRealVariableInternal(flow, identifier, realFir, stability) }
|
||||
}
|
||||
|
||||
private fun getOrCreateRealVariable(flow: Flow, symbol: AbstractFirBasedSymbol<*>, fir: FirElement): RealVariable {
|
||||
val variable = getOrCreateRealVariableWithoutUnwrappingAlias(flow, symbol, fir)
|
||||
private fun getOrCreateRealVariable(
|
||||
flow: Flow,
|
||||
symbol: AbstractFirBasedSymbol<*>,
|
||||
fir: FirElement,
|
||||
stability: PropertyStability
|
||||
): RealVariable {
|
||||
val variable = getOrCreateRealVariableWithoutUnwrappingAlias(flow, symbol, fir, stability)
|
||||
return flow.directAliasMap[variable]?.variable ?: variable
|
||||
}
|
||||
|
||||
@@ -69,7 +81,12 @@ class VariableStorage(private val session: FirSession) {
|
||||
/**
|
||||
* [originalFir] used for extracting expression under <when_subject> and extracting receiver
|
||||
*/
|
||||
private fun createRealVariableInternal(flow: Flow, identifier: Identifier, originalFir: FirElement): RealVariable {
|
||||
private fun createRealVariableInternal(
|
||||
flow: Flow,
|
||||
identifier: Identifier,
|
||||
originalFir: FirElement,
|
||||
stability: PropertyStability
|
||||
): RealVariable {
|
||||
val receiver: FirExpression?
|
||||
val isThisReference: Boolean
|
||||
val expression: FirQualifiedAccess? = when (originalFir) {
|
||||
@@ -88,12 +105,12 @@ class VariableStorage(private val session: FirSession) {
|
||||
}
|
||||
|
||||
val receiverVariable = receiver?.let { getOrCreateVariable(flow, it) }
|
||||
return RealVariable(identifier, isThisReference, receiverVariable, counter++)
|
||||
return RealVariable(identifier, isThisReference, receiverVariable, counter++, stability)
|
||||
}
|
||||
|
||||
@JvmName("getOrCreateRealVariableOrNull")
|
||||
fun getOrCreateRealVariable(flow: Flow, symbol: AbstractFirBasedSymbol<*>?, fir: FirElement): RealVariable? =
|
||||
symbol.takeIf { it.isStable(fir) }?.let { getOrCreateRealVariable(flow, it, fir) }
|
||||
symbol.getStability(fir)?.let { getOrCreateRealVariable(flow, symbol!!, fir, it) }
|
||||
|
||||
fun createSyntheticVariable(fir: FirElement): SyntheticVariable =
|
||||
SyntheticVariable(fir, counter++).also { syntheticVariables[fir] = it }
|
||||
@@ -101,8 +118,9 @@ class VariableStorage(private val session: FirSession) {
|
||||
fun getOrCreateVariable(flow: Flow, fir: FirElement): DataFlowVariable {
|
||||
val realFir = fir.unwrapElement()
|
||||
val symbol = realFir.symbol
|
||||
return if (symbol.isStable(realFir)) {
|
||||
getOrCreateRealVariable(flow, symbol!!, realFir)
|
||||
val stability = symbol.getStability(realFir)
|
||||
return if (stability != null) {
|
||||
getOrCreateRealVariable(flow, symbol!!, realFir, stability)
|
||||
} else {
|
||||
syntheticVariables[realFir] ?: createSyntheticVariable(realFir)
|
||||
}
|
||||
@@ -110,7 +128,7 @@ class VariableStorage(private val session: FirSession) {
|
||||
|
||||
fun getRealVariableWithoutUnwrappingAlias(symbol: AbstractFirBasedSymbol<*>?, fir: FirElement, flow: Flow): RealVariable? {
|
||||
val realFir = fir.unwrapElement()
|
||||
return symbol.takeIf { it.isStable(realFir) }?.let {
|
||||
return symbol.takeIf { it.getStability(realFir) != null }?.let {
|
||||
_realVariables[getIdentifierBySymbol(flow, it, realFir.unwrapElement())]
|
||||
}
|
||||
}
|
||||
@@ -126,7 +144,8 @@ class VariableStorage(private val session: FirSession) {
|
||||
fun getVariable(fir: FirElement, flow: Flow): DataFlowVariable? {
|
||||
val realFir = fir.unwrapElement()
|
||||
val symbol = realFir.symbol
|
||||
return if (symbol.isStable(fir)) {
|
||||
val stability = symbol.getStability(fir)
|
||||
return if (stability != null) {
|
||||
getRealVariable(symbol, realFir, flow)
|
||||
} else {
|
||||
getSyntheticVariable(fir)
|
||||
@@ -138,44 +157,45 @@ class VariableStorage(private val session: FirSession) {
|
||||
}
|
||||
|
||||
fun removeSyntheticVariable(variable: DataFlowVariable) {
|
||||
if (variable !is SyntheticVariable) return
|
||||
if (!variable.isSynthetic()) return
|
||||
syntheticVariables.remove(variable.fir)
|
||||
}
|
||||
|
||||
@OptIn(ExperimentalContracts::class)
|
||||
fun AbstractFirBasedSymbol<*>?.isStable(originalFir: FirElement): Boolean {
|
||||
fun AbstractFirBasedSymbol<*>?.getStability(originalFir: FirElement): PropertyStability? {
|
||||
contract {
|
||||
returns(true) implies(this@isStable != null)
|
||||
returnsNotNull() implies (this@getStability != null)
|
||||
}
|
||||
when (this) {
|
||||
is FirAnonymousObjectSymbol -> return false
|
||||
is FirAnonymousObjectSymbol -> return null
|
||||
is FirFunctionSymbol<*>,
|
||||
is FirClassSymbol<*>,
|
||||
is FirBackingFieldSymbol -> return true
|
||||
null -> return false
|
||||
is FirBackingFieldSymbol -> return PropertyStability.STABLE_VALUE
|
||||
null -> return null
|
||||
}
|
||||
if (originalFir is FirThisReceiverExpression) return true
|
||||
if (this !is FirVariableSymbol<*>) return false
|
||||
if (originalFir is FirThisReceiverExpression) return PropertyStability.STABLE_VALUE
|
||||
if (this !is FirVariableSymbol<*>) return null
|
||||
|
||||
val property = this.fir as? FirProperty ?: return true
|
||||
val property = this.fir as? FirProperty ?: return PropertyStability.STABLE_VALUE
|
||||
|
||||
return when {
|
||||
property.isLocal -> true
|
||||
property.isVar -> false
|
||||
property.receiverTypeRef != null -> false
|
||||
property.getter.let { it != null && it !is FirDefaultPropertyAccessor } -> false
|
||||
property.delegate != null -> PropertyStability.DELEGATED_PROPERTY
|
||||
property.isLocal -> if (property.isVal) PropertyStability.STABLE_VALUE else PropertyStability.LOCAL_VAR
|
||||
property.isVar -> PropertyStability.MUTABLE_PROPERTY
|
||||
property.receiverTypeRef != null -> PropertyStability.PROPERTY_WITH_GETTER
|
||||
property.getter.let { it != null && it !is FirDefaultPropertyAccessor } -> PropertyStability.PROPERTY_WITH_GETTER
|
||||
property.moduleData.session != session -> PropertyStability.ALIEN_PUBLIC_PROPERTY
|
||||
property.modality != Modality.FINAL -> {
|
||||
val dispatchReceiver = (originalFir.unwrapElement() as? FirQualifiedAccess)?.dispatchReceiver ?: return false
|
||||
val receiverType = dispatchReceiver.typeRef.coneTypeSafe<ConeClassLikeType>()?.fullyExpandedType(session) ?: return false
|
||||
val receiverSymbol = receiverType.lookupTag.toSymbol(session) ?: return false
|
||||
val dispatchReceiver = (originalFir.unwrapElement() as? FirQualifiedAccess)?.dispatchReceiver ?: return null
|
||||
val receiverType = dispatchReceiver.typeRef.coneTypeSafe<ConeClassLikeType>()?.fullyExpandedType(session) ?: return null
|
||||
val receiverSymbol = receiverType.lookupTag.toSymbol(session) ?: return null
|
||||
when (val receiverFir = receiverSymbol.fir) {
|
||||
is org.jetbrains.kotlin.fir.declarations.FirAnonymousObject -> true
|
||||
is org.jetbrains.kotlin.fir.declarations.FirRegularClass -> receiverFir.modality == Modality.FINAL
|
||||
is FirAnonymousObject -> PropertyStability.STABLE_VALUE
|
||||
is FirRegularClass -> if (receiverFir.modality == Modality.FINAL) PropertyStability.STABLE_VALUE else PropertyStability.PROPERTY_WITH_GETTER
|
||||
else -> throw IllegalStateException("Should not be here: $receiverFir")
|
||||
}
|
||||
|
||||
}
|
||||
else -> true
|
||||
else -> PropertyStability.STABLE_VALUE
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -11,6 +11,7 @@ import org.jetbrains.kotlin.fir.symbols.AbstractFirBasedSymbol
|
||||
import org.jetbrains.kotlin.fir.symbols.impl.FirCallableSymbol
|
||||
import org.jetbrains.kotlin.fir.types.ConeClassErrorType
|
||||
import org.jetbrains.kotlin.fir.types.ConeKotlinType
|
||||
import org.jetbrains.kotlin.types.SmartcastStability
|
||||
import kotlin.contracts.ExperimentalContracts
|
||||
import kotlin.contracts.contract
|
||||
|
||||
@@ -33,11 +34,37 @@ sealed class DataFlowVariable(private val variableIndexForDebug: Int) {
|
||||
}
|
||||
}
|
||||
|
||||
enum class PropertyStability(val impliedSmartcastStability: SmartcastStability?) {
|
||||
// Immutable and no custom getter or local.
|
||||
// Smartcast is definitely safe regardless of usage.
|
||||
STABLE_VALUE(SmartcastStability.STABLE_VALUE),
|
||||
|
||||
// Open or custom getter.
|
||||
// Smartcast is always unsafe regardless of usage.
|
||||
PROPERTY_WITH_GETTER(SmartcastStability.PROPERTY_WITH_GETTER),
|
||||
|
||||
// Protected / public member value from another module.
|
||||
// Smartcast is always unsafe regardless of usage.
|
||||
ALIEN_PUBLIC_PROPERTY(SmartcastStability.ALIEN_PUBLIC_PROPERTY),
|
||||
|
||||
// Smartcast may or may not be safe, depending on whether there are concurrent writes to this local variable.
|
||||
LOCAL_VAR(null),
|
||||
|
||||
// Mutable member property of a class or object.
|
||||
// Smartcast is always unsafe regardless of usage.
|
||||
MUTABLE_PROPERTY(SmartcastStability.MUTABLE_PROPERTY),
|
||||
|
||||
// Delegated property of a class or object.
|
||||
// Smartcast is always unsafe regardless of usage.
|
||||
DELEGATED_PROPERTY(SmartcastStability.DELEGATED_PROPERTY),
|
||||
}
|
||||
|
||||
class RealVariable(
|
||||
val identifier: Identifier,
|
||||
val isThisReference: Boolean,
|
||||
val explicitReceiverVariable: DataFlowVariable?,
|
||||
variableIndexForDebug: Int
|
||||
variableIndexForDebug: Int,
|
||||
val stability: PropertyStability,
|
||||
) : DataFlowVariable(variableIndexForDebug) {
|
||||
override fun equals(other: Any?): Boolean {
|
||||
return this === other
|
||||
|
||||
@@ -63,7 +63,7 @@ class FirWhenExhaustivenessTransformer(private val bodyResolveComponents: BodyRe
|
||||
|
||||
val checkers = buildList {
|
||||
exhaustivenessCheckers.filterTo(this) { it.isApplicable(cleanSubjectType, session) }
|
||||
if (isNotEmpty() && cleanSubjectType.isMarkedNullable) {
|
||||
if (isNotEmpty<WhenExhaustivenessChecker>() && cleanSubjectType.isMarkedNullable) {
|
||||
add(WhenOnNullableExhaustivenessChecker)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -251,11 +251,15 @@ interface ConeInferenceContext : TypeSystemInferenceExtensionContext, ConeTypeCo
|
||||
)
|
||||
}
|
||||
|
||||
override fun createStubType(typeVariable: TypeVariableMarker): StubTypeMarker {
|
||||
override fun createStubTypeForBuilderInference(typeVariable: TypeVariableMarker): StubTypeMarker {
|
||||
require(typeVariable is ConeTypeVariable) { "$typeVariable should subtype of ${ConeTypeVariable::class.qualifiedName}" }
|
||||
return ConeStubType(typeVariable, ConeNullability.create(typeVariable.defaultType().isMarkedNullable()))
|
||||
}
|
||||
|
||||
// TODO
|
||||
override fun createStubTypeForTypeVariablesInSubtyping(typeVariable: TypeVariableMarker) =
|
||||
createStubTypeForBuilderInference(typeVariable)
|
||||
|
||||
override fun KotlinTypeMarker.removeAnnotations(): KotlinTypeMarker {
|
||||
require(this is ConeKotlinType)
|
||||
return withAttributes(ConeAttributes.Empty, this@ConeInferenceContext)
|
||||
|
||||
@@ -380,7 +380,15 @@ interface ConeTypeContext : TypeSystemContext, TypeSystemOptimizationContext, Ty
|
||||
}
|
||||
|
||||
override fun SimpleTypeMarker.isStubType(): Boolean {
|
||||
return this is StubTypeMarker
|
||||
return this is ConeStubType // TODO: distinguish stub types for builder inference and for subtyping
|
||||
}
|
||||
|
||||
override fun SimpleTypeMarker.isStubTypeForVariableInSubtyping(): Boolean {
|
||||
return this is ConeStubType // TODO: distinguish stub types for builder inference and for subtyping
|
||||
}
|
||||
|
||||
override fun SimpleTypeMarker.isStubTypeForBuilderInference(): Boolean {
|
||||
return this is ConeStubType // TODO: distinguish stub types for builder inference and for subtyping
|
||||
}
|
||||
|
||||
override fun intersectTypes(types: List<SimpleTypeMarker>): SimpleTypeMarker {
|
||||
|
||||
@@ -11,6 +11,7 @@ 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.types.SmartcastStability
|
||||
import org.jetbrains.kotlin.fir.visitors.*
|
||||
import org.jetbrains.kotlin.fir.FirImplementationDetail
|
||||
|
||||
@@ -31,6 +32,8 @@ abstract class FirExpressionWithSmartcast : FirQualifiedAccessExpression() {
|
||||
abstract val originalExpression: FirQualifiedAccessExpression
|
||||
abstract val typesFromSmartCast: Collection<ConeKotlinType>
|
||||
abstract val originalType: FirTypeRef
|
||||
abstract val smartcastType: FirTypeRef
|
||||
abstract val smartcastStability: SmartcastStability
|
||||
|
||||
override fun <R, D> accept(visitor: FirVisitor<R, D>, data: D): R = visitor.visitExpressionWithSmartcast(this, data)
|
||||
|
||||
|
||||
@@ -11,6 +11,7 @@ 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.types.SmartcastStability
|
||||
import org.jetbrains.kotlin.fir.visitors.*
|
||||
import org.jetbrains.kotlin.fir.FirImplementationDetail
|
||||
|
||||
@@ -31,6 +32,8 @@ abstract class FirExpressionWithSmartcastToNull : FirExpressionWithSmartcast() {
|
||||
abstract override val originalExpression: FirQualifiedAccessExpression
|
||||
abstract override val typesFromSmartCast: Collection<ConeKotlinType>
|
||||
abstract override val originalType: FirTypeRef
|
||||
abstract override val smartcastType: FirTypeRef
|
||||
abstract override val smartcastStability: SmartcastStability
|
||||
|
||||
override fun <R, D> accept(visitor: FirVisitor<R, D>, data: D): R = visitor.visitExpressionWithSmartcastToNull(this, data)
|
||||
|
||||
|
||||
@@ -10,14 +10,16 @@ import org.jetbrains.kotlin.fir.expressions.FirQualifiedAccessExpression
|
||||
import org.jetbrains.kotlin.fir.expressions.impl.FirExpressionWithSmartcastImpl
|
||||
import org.jetbrains.kotlin.fir.types.ConeKotlinType
|
||||
import org.jetbrains.kotlin.fir.types.FirTypeRef
|
||||
import org.jetbrains.kotlin.types.SmartcastStability
|
||||
|
||||
class FirExpressionWithSmartcastBuilder {
|
||||
lateinit var originalExpression: FirQualifiedAccessExpression
|
||||
lateinit var typeRef: FirTypeRef
|
||||
lateinit var smartcastType: FirTypeRef
|
||||
lateinit var typesFromSmartCast: Collection<ConeKotlinType>
|
||||
lateinit var smartcastStability: SmartcastStability
|
||||
|
||||
fun build(): FirExpressionWithSmartcast {
|
||||
return FirExpressionWithSmartcastImpl(originalExpression, typeRef, typesFromSmartCast)
|
||||
return FirExpressionWithSmartcastImpl(originalExpression, smartcastType, typesFromSmartCast, smartcastStability)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -10,14 +10,16 @@ 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
|
||||
import org.jetbrains.kotlin.types.SmartcastStability
|
||||
|
||||
class FirExpressionWithSmartcastToNullBuilder {
|
||||
lateinit var originalExpression: FirQualifiedAccessExpression
|
||||
lateinit var typeRef: FirTypeRef
|
||||
lateinit var smartcastType: FirTypeRef
|
||||
lateinit var typesFromSmartCast: Collection<ConeKotlinType>
|
||||
lateinit var smartcastStability: SmartcastStability
|
||||
|
||||
fun build(): FirExpressionWithSmartcastToNull {
|
||||
return FirExpressionWithSmartcastToNullImpl(originalExpression, typeRef, typesFromSmartCast)
|
||||
return FirExpressionWithSmartcastToNullImpl(originalExpression, smartcastType, typesFromSmartCast, smartcastStability)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -19,11 +19,13 @@ 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
|
||||
import org.jetbrains.kotlin.types.SmartcastStability
|
||||
|
||||
internal class FirExpressionWithSmartcastImpl(
|
||||
override var originalExpression: FirQualifiedAccessExpression,
|
||||
override val typeRef: FirTypeRef,
|
||||
override val typesFromSmartCast: Collection<ConeKotlinType>
|
||||
override val smartcastType: FirTypeRef,
|
||||
override val typesFromSmartCast: Collection<ConeKotlinType>,
|
||||
override val smartcastStability: SmartcastStability
|
||||
) : FirExpressionWithSmartcast() {
|
||||
init {
|
||||
assert(originalExpression.typeRef is FirResolvedTypeRef)
|
||||
@@ -37,6 +39,10 @@ internal class FirExpressionWithSmartcastImpl(
|
||||
override val extensionReceiver: FirExpression get() = originalExpression.extensionReceiver
|
||||
override val calleeReference: FirReference get() = originalExpression.calleeReference
|
||||
override val originalType: FirTypeRef get() = originalExpression.typeRef
|
||||
// A FirExpressionWithSmartcast is only an effective smartcast if `smartcastStability == SmartcastStability.STABLE_VALUE`. Otherwise,
|
||||
// it's the same as the `originalExpression` under the hood. The reason we still create such a smartcast expression is for diagnostics
|
||||
// purpose only.
|
||||
override val typeRef: FirTypeRef get() = if (smartcastStability == SmartcastStability.STABLE_VALUE) smartcastType else originalType
|
||||
|
||||
override fun <D> transformChildren(transformer: FirTransformer<D>, data: D): FirExpressionWithSmartcast {
|
||||
originalExpression = originalExpression.transformSingle(transformer, data)
|
||||
|
||||
@@ -16,11 +16,13 @@ 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
|
||||
import org.jetbrains.kotlin.types.SmartcastStability
|
||||
|
||||
class FirExpressionWithSmartcastToNullImpl(
|
||||
override var originalExpression: FirQualifiedAccessExpression,
|
||||
override val typeRef: FirTypeRef,
|
||||
override val typesFromSmartCast: Collection<ConeKotlinType>
|
||||
override val smartcastType: FirTypeRef,
|
||||
override val typesFromSmartCast: Collection<ConeKotlinType>,
|
||||
override val smartcastStability: SmartcastStability
|
||||
) : FirExpressionWithSmartcastToNull() {
|
||||
init {
|
||||
assert(originalExpression.typeRef is FirResolvedTypeRef)
|
||||
@@ -34,6 +36,10 @@ class FirExpressionWithSmartcastToNullImpl(
|
||||
override val extensionReceiver: FirExpression get() = originalExpression.extensionReceiver
|
||||
override val calleeReference: FirReference get() = originalExpression.calleeReference
|
||||
override val originalType: FirTypeRef get() = originalExpression.typeRef
|
||||
// A FirExpressionWithSmartcast is only an effective smartcast if `smartcastStability == SmartcastStability.STABLE_VALUE`. Otherwise,
|
||||
// it's the same as the `originalExpression` under the hood. The reason we still create such a smartcast expression is for diagnostics
|
||||
// purpose only.
|
||||
override val typeRef: FirTypeRef get() = if (smartcastStability == SmartcastStability.STABLE_VALUE) smartcastType else originalType
|
||||
|
||||
override fun <D> transformChildren(transformer: FirTransformer<D>, data: D): FirExpressionWithSmartcastToNull {
|
||||
originalExpression = originalExpression.transformSingle(transformer, data)
|
||||
|
||||
@@ -0,0 +1,106 @@
|
||||
/*
|
||||
* 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.scopes
|
||||
|
||||
import org.jetbrains.kotlin.fir.declarations.FirCallableMemberDeclaration
|
||||
import org.jetbrains.kotlin.fir.resolve.substitution.ConeSubstitutor
|
||||
import org.jetbrains.kotlin.fir.symbols.impl.*
|
||||
import org.jetbrains.kotlin.fir.types.ConeKotlinType
|
||||
import org.jetbrains.kotlin.name.Name
|
||||
|
||||
/**
|
||||
* Special type scope for unstable smartcast. The purpose of this scope is only to report "SMARTCAST_IMPOSSIBLE" diagnostics.
|
||||
*
|
||||
* This scope will serve all candidates available in the original scope. In addition, it also serve all additional members that are
|
||||
* available from the smartcast type. This way, these additional members can be resolved. Later in
|
||||
* [org.jetbrains.kotlin.fir.resolve.calls.CheckDispatchReceiver], these additional members are rejected with "UnstableSmartcast"
|
||||
* diagnostic, which surfaces as "SMARTCAST_IMPOSSIBLE" diagnostic.
|
||||
*/
|
||||
class FirUnstableSmartcastTypeScope(
|
||||
private val smartcastType: ConeKotlinType,
|
||||
private val smartcastScope: FirTypeScope,
|
||||
private val originalScope: FirTypeScope
|
||||
) : FirTypeScope(), FirContainingNamesAwareScope {
|
||||
private val scopes = listOf(smartcastScope, originalScope)
|
||||
override fun processClassifiersByNameWithSubstitution(
|
||||
name: Name,
|
||||
processor: (FirClassifierSymbol<*>, ConeSubstitutor) -> Unit
|
||||
) {
|
||||
for (scope in scopes) {
|
||||
scope.processClassifiersByNameWithSubstitution(name, processor)
|
||||
}
|
||||
}
|
||||
|
||||
private inline fun <T> processComposite(
|
||||
process: FirTypeScope.(Name, (T) -> Unit) -> Unit,
|
||||
name: Name,
|
||||
noinline processor: (T) -> Unit
|
||||
) {
|
||||
val unique = mutableSetOf<T>()
|
||||
for (scope in scopes) {
|
||||
scope.process(name) {
|
||||
if (unique.add(it)) {
|
||||
processor(it)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
override fun processFunctionsByName(name: Name, processor: (FirNamedFunctionSymbol) -> Unit) {
|
||||
return processComposite(FirScope::processFunctionsByName, name, processor)
|
||||
}
|
||||
|
||||
override fun processPropertiesByName(name: Name, processor: (FirVariableSymbol<*>) -> Unit) {
|
||||
return processComposite(FirScope::processPropertiesByName, name, processor)
|
||||
}
|
||||
|
||||
private inline fun <N, T : FirCallableSymbol<*>> processTypedComposite(
|
||||
process: FirTypeScope.(N, (T, FirTypeScope) -> ProcessorAction) -> ProcessorAction,
|
||||
name: N,
|
||||
noinline processor: (T, FirTypeScope) -> ProcessorAction
|
||||
): ProcessorAction {
|
||||
originalScope.process(name) { symbol, firTypeScope ->
|
||||
processor(symbol, firTypeScope)
|
||||
}.let { if (it == ProcessorAction.STOP) return ProcessorAction.STOP }
|
||||
|
||||
smartcastScope.process(name) { symbol, firTypeScope ->
|
||||
// Only process the symbol if the dispatcher type is exactly the smartcast type. This way, we don't add any additional
|
||||
// symbols that already exists in the original scope.
|
||||
if ((symbol.fir as? FirCallableMemberDeclaration)?.dispatchReceiverType == smartcastType) {
|
||||
processor(symbol, firTypeScope)
|
||||
} else {
|
||||
ProcessorAction.NEXT
|
||||
}
|
||||
}.let { if (it == ProcessorAction.STOP) return ProcessorAction.STOP }
|
||||
return ProcessorAction.NEXT
|
||||
}
|
||||
|
||||
override fun processDirectOverriddenFunctionsWithBaseScope(
|
||||
functionSymbol: FirNamedFunctionSymbol,
|
||||
processor: (FirNamedFunctionSymbol, FirTypeScope) -> ProcessorAction
|
||||
): ProcessorAction {
|
||||
return processTypedComposite(FirTypeScope::processDirectOverriddenFunctionsWithBaseScope, functionSymbol, processor)
|
||||
}
|
||||
|
||||
override fun processDirectOverriddenPropertiesWithBaseScope(
|
||||
propertySymbol: FirPropertySymbol,
|
||||
processor: (FirPropertySymbol, FirTypeScope) -> ProcessorAction
|
||||
): ProcessorAction {
|
||||
return processTypedComposite(FirTypeScope::processDirectOverriddenPropertiesWithBaseScope, propertySymbol, processor)
|
||||
}
|
||||
|
||||
override fun getCallableNames(): Set<Name> {
|
||||
return scopes.flatMapTo(hashSetOf()) { it.getContainingCallableNamesIfPresent() }
|
||||
}
|
||||
|
||||
override fun getClassifierNames(): Set<Name> {
|
||||
return scopes.flatMapTo(hashSetOf()) { it.getContainingClassifierNamesIfPresent() }
|
||||
}
|
||||
|
||||
override val scopeOwnerLookupNames: List<String> by lazy(LazyThreadSafetyMode.PUBLICATION) {
|
||||
scopes.flatMap { it.scopeOwnerLookupNames }
|
||||
}
|
||||
}
|
||||
@@ -83,4 +83,6 @@ object FieldSets {
|
||||
val modality = field(modalityType, nullable = true)
|
||||
|
||||
val scopeProvider = field("scopeProvider", firScopeProviderType)
|
||||
|
||||
val smartcastStability = field(smartcastStabilityType)
|
||||
}
|
||||
|
||||
@@ -19,6 +19,7 @@ import org.jetbrains.kotlin.fir.tree.generator.FieldSets.name
|
||||
import org.jetbrains.kotlin.fir.tree.generator.FieldSets.receivers
|
||||
import org.jetbrains.kotlin.fir.tree.generator.FieldSets.returnTypeRef
|
||||
import org.jetbrains.kotlin.fir.tree.generator.FieldSets.scopeProvider
|
||||
import org.jetbrains.kotlin.fir.tree.generator.FieldSets.smartcastStability
|
||||
import org.jetbrains.kotlin.fir.tree.generator.FieldSets.status
|
||||
import org.jetbrains.kotlin.fir.tree.generator.FieldSets.superTypeRefs
|
||||
import org.jetbrains.kotlin.fir.tree.generator.FieldSets.symbol
|
||||
@@ -458,12 +459,16 @@ object NodeConfigurator : AbstractFieldConfigurator<FirTreeBuilder>(FirTreeBuild
|
||||
+field("originalExpression", qualifiedAccessExpression)
|
||||
+field("typesFromSmartCast", "Collection<ConeKotlinType>", null, customType = coneKotlinTypeType)
|
||||
+field("originalType", typeRef)
|
||||
+field("smartcastType", typeRef)
|
||||
+smartcastStability
|
||||
}
|
||||
|
||||
expressionWithSmartcastToNull.configure {
|
||||
+field("originalExpression", qualifiedAccessExpression)
|
||||
+field("typesFromSmartCast", "Collection<ConeKotlinType>", null, customType = coneKotlinTypeType)
|
||||
+field("originalType", typeRef)
|
||||
+field("smartcastType", typeRef)
|
||||
+smartcastStability
|
||||
}
|
||||
|
||||
safeCallExpression.configure {
|
||||
|
||||
@@ -17,6 +17,7 @@ import org.jetbrains.kotlin.fir.types.ConeKotlinType
|
||||
import org.jetbrains.kotlin.name.ClassId
|
||||
import org.jetbrains.kotlin.name.FqName
|
||||
import org.jetbrains.kotlin.name.Name
|
||||
import org.jetbrains.kotlin.types.SmartcastStability
|
||||
import org.jetbrains.kotlin.types.Variance
|
||||
|
||||
val sourceElementType = type("fir", "FirSourceElement")
|
||||
@@ -31,6 +32,7 @@ val nameType = type(Name::class)
|
||||
val visibilityType = type(Visibility::class)
|
||||
val effectiveVisibilityType = type("descriptors", "EffectiveVisibility")
|
||||
val modalityType = type(Modality::class)
|
||||
val smartcastStabilityType = type(SmartcastStability::class)
|
||||
val fqNameType = type(FqName::class)
|
||||
val classIdType = type(ClassId::class)
|
||||
val annotationUseSiteTargetType = type(AnnotationUseSiteTarget::class)
|
||||
|
||||
@@ -103,7 +103,7 @@ object RuntimeAssertionsTypeChecker : AdditionalTypeChecker {
|
||||
expressionTypeWithSmartCast: KotlinType,
|
||||
c: ResolutionContext<*>
|
||||
) {
|
||||
if (TypeUtils.noExpectedType(c.expectedType) || c.expectedType is StubType) return
|
||||
if (TypeUtils.noExpectedType(c.expectedType) || c.expectedType is StubTypeForBuilderInference) return
|
||||
|
||||
val assertionInfo = RuntimeAssertionInfo.create(
|
||||
c.expectedType,
|
||||
|
||||
@@ -15,7 +15,6 @@ dependencies {
|
||||
compile(project(":compiler:frontend.common"))
|
||||
compile(project(":kotlin-script-runtime"))
|
||||
compile(commonDep("io.javaslang","javaslang"))
|
||||
api(project(":core:compiler.common.jvm"))
|
||||
compileOnly(intellijCoreDep()) { includeJars("intellij-core") }
|
||||
compileOnly(intellijDep()) { includeJars("trove4j", "guava", rootProject = rootProject) }
|
||||
}
|
||||
|
||||
@@ -110,7 +110,7 @@ fun ResolutionContext<*>.reportTypeMismatchDueToTypeProjection(
|
||||
}
|
||||
|
||||
fun BindingTrace.reportDiagnosticOnce(diagnostic: Diagnostic) {
|
||||
if (bindingContext.diagnostics.forElement(diagnostic.psiElement).any { it.factory == diagnostic.factory }) return
|
||||
if (bindingContext.diagnostics.noSuppression().forElement(diagnostic.psiElement).any { it.factory == diagnostic.factory }) return
|
||||
|
||||
report(diagnostic)
|
||||
}
|
||||
@@ -119,8 +119,10 @@ fun BindingTrace.reportDiagnosticOnceWrtDiagnosticFactoryList(
|
||||
diagnosticToReport: Diagnostic,
|
||||
vararg diagnosticFactories: DiagnosticFactory<*>,
|
||||
) {
|
||||
val hasAlreadyReportedDiagnosticFromListOrSameType = bindingContext.diagnostics.forElement(diagnosticToReport.psiElement)
|
||||
.any { diagnostic -> diagnostic.factory == diagnosticToReport.factory || diagnosticFactories.any { it == diagnostic.factory } }
|
||||
val hasAlreadyReportedDiagnosticFromListOrSameType =
|
||||
bindingContext.diagnostics.noSuppression()
|
||||
.forElement(diagnosticToReport.psiElement)
|
||||
.any { diagnostic -> diagnostic.factory == diagnosticToReport.factory || diagnosticFactories.any { it == diagnostic.factory } }
|
||||
|
||||
if (hasAlreadyReportedDiagnosticFromListOrSameType) return
|
||||
|
||||
|
||||
@@ -26,6 +26,7 @@ import org.jetbrains.kotlin.resolve.descriptorUtil.annotationClass
|
||||
import org.jetbrains.kotlin.resolve.descriptorUtil.getAnnotationRetention
|
||||
import org.jetbrains.kotlin.resolve.descriptorUtil.isRepeatableAnnotation
|
||||
import org.jetbrains.kotlin.resolve.inline.InlineUtil
|
||||
import org.jetbrains.kotlin.resolve.lazy.ForceResolveUtil
|
||||
import org.jetbrains.kotlin.resolve.lazy.descriptors.LazyAnnotationDescriptor
|
||||
import org.jetbrains.kotlin.types.KotlinType
|
||||
import org.jetbrains.kotlin.types.expressions.ExpressionTypingUtils
|
||||
@@ -53,8 +54,16 @@ class AnnotationChecker(
|
||||
}
|
||||
if (
|
||||
annotated is KtTypeParameterListOwner &&
|
||||
(annotated is KtCallableDeclaration || languageVersionSettings.supportsFeature(ProperCheckAnnotationsTargetInTypeUsePositions))
|
||||
(annotated is KtCallableDeclaration || languageVersionSettings.supportsFeature(ProperCheckAnnotationsTargetInTypeUsePositions) ||
|
||||
(annotated is KtClass && languageVersionSettings.supportsFeature(ClassTypeParameterAnnotations)))
|
||||
) {
|
||||
if (annotated is KtClass && languageVersionSettings.supportsFeature(ClassTypeParameterAnnotations)) {
|
||||
(descriptor as? ClassDescriptor)?.declaredTypeParameters?.forEach {
|
||||
//force annotation resolve to obtain targets
|
||||
ForceResolveUtil.forceResolveAllContents(it.annotations)
|
||||
}
|
||||
}
|
||||
|
||||
annotated.typeParameters.forEach { check(it, trace) }
|
||||
for (typeParameter in annotated.typeParameters) {
|
||||
typeParameter.extendsBound?.let {
|
||||
|
||||
@@ -518,9 +518,10 @@ class DeclarationsChecker(
|
||||
}
|
||||
|
||||
private fun checkTypeParameters(typeParameterListOwner: KtTypeParameterListOwner) {
|
||||
// TODO: Support annotation for type parameters
|
||||
for (jetTypeParameter in typeParameterListOwner.typeParameters) {
|
||||
AnnotationResolverImpl.reportUnsupportedAnnotationForTypeParameter(jetTypeParameter, trace)
|
||||
if (!languageVersionSettings.supportsFeature(LanguageFeature.ClassTypeParameterAnnotations)) {
|
||||
AnnotationResolverImpl.reportUnsupportedAnnotationForTypeParameter(jetTypeParameter, trace)
|
||||
}
|
||||
|
||||
trace.get(TYPE_PARAMETER, jetTypeParameter)?.let { DescriptorResolver.checkConflictingUpperBounds(trace, it, jetTypeParameter) }
|
||||
}
|
||||
|
||||
@@ -32,6 +32,7 @@ import org.jetbrains.kotlin.psi.KtPsiUtil
|
||||
import org.jetbrains.kotlin.psi.KtVariableDeclaration
|
||||
import org.jetbrains.kotlin.resolve.calls.components.InferenceSession
|
||||
import org.jetbrains.kotlin.resolve.calls.context.ContextDependency
|
||||
import org.jetbrains.kotlin.resolve.calls.inference.BuilderInferenceSession
|
||||
import org.jetbrains.kotlin.resolve.calls.smartcasts.DataFlowInfo
|
||||
import org.jetbrains.kotlin.resolve.calls.smartcasts.DataFlowValueFactory
|
||||
import org.jetbrains.kotlin.resolve.calls.util.isSingleUnderscore
|
||||
@@ -189,6 +190,9 @@ class LocalVariableResolver(
|
||||
initializeWithDefaultGetterSetter(propertyDescriptor)
|
||||
trace.record(BindingContext.VARIABLE, variable, propertyDescriptor)
|
||||
result = propertyDescriptor
|
||||
if (inferenceSession is BuilderInferenceSession) {
|
||||
inferenceSession.addLocalVariable(variable)
|
||||
}
|
||||
} else {
|
||||
val variableDescriptor = resolveLocalVariableDescriptorWithType(scope, variable, null, trace)
|
||||
// For a local variable the type must not be deferred
|
||||
@@ -196,6 +200,9 @@ class LocalVariableResolver(
|
||||
variableDescriptor, scope, variable, dataFlowInfo, inferenceSession, trace, local = true
|
||||
)
|
||||
variableDescriptor.setOutType(type)
|
||||
if (inferenceSession is BuilderInferenceSession) {
|
||||
inferenceSession.addLocalVariable(variable)
|
||||
}
|
||||
result = variableDescriptor
|
||||
}
|
||||
variableTypeAndInitializerResolver
|
||||
|
||||
@@ -254,7 +254,7 @@ class CallCompleter(
|
||||
system.resultingSubstitutor.replaceWithContravariantApproximatingSubstitution()
|
||||
} else system.resultingSubstitutor
|
||||
|
||||
setResultingSubstitutor(resultingSubstitutor)
|
||||
setSubstitutor(resultingSubstitutor)
|
||||
}
|
||||
|
||||
private fun <D : CallableDescriptor> MutableResolvedCall<D>.updateResolutionStatusFromConstraintSystem(
|
||||
|
||||
@@ -108,7 +108,7 @@ class CandidateResolver(
|
||||
private fun CallCandidateResolutionContext<*>.processTypeArguments() = check {
|
||||
val ktTypeArguments = call.typeArguments
|
||||
if (candidateCall.knownTypeParametersSubstitutor != null) {
|
||||
candidateCall.setResultingSubstitutor(candidateCall.knownTypeParametersSubstitutor!!)
|
||||
candidateCall.setSubstitutor(candidateCall.knownTypeParametersSubstitutor!!)
|
||||
} else if (ktTypeArguments.isNotEmpty()) {
|
||||
// Explicit type arguments passed
|
||||
|
||||
@@ -137,7 +137,7 @@ class CandidateResolver(
|
||||
checkGenericBoundsInAFunctionCall(ktTypeArguments, typeArguments, candidateDescriptor, substitutor, trace)
|
||||
}
|
||||
|
||||
candidateCall.setResultingSubstitutor(substitutor)
|
||||
candidateCall.setSubstitutor(substitutor)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -19,6 +19,7 @@ import org.jetbrains.kotlin.resolve.calls.callUtil.getCalleeExpressionIfAny
|
||||
import org.jetbrains.kotlin.resolve.calls.callUtil.getResolvedCall
|
||||
import org.jetbrains.kotlin.resolve.calls.callUtil.reportTrailingLambdaErrorOr
|
||||
import org.jetbrains.kotlin.resolve.calls.context.BasicCallResolutionContext
|
||||
import org.jetbrains.kotlin.resolve.calls.inference.BuilderInferenceExpectedTypeConstraintPosition
|
||||
import org.jetbrains.kotlin.resolve.calls.inference.model.*
|
||||
import org.jetbrains.kotlin.resolve.calls.model.*
|
||||
import org.jetbrains.kotlin.resolve.calls.smartcasts.DataFlowValueFactory
|
||||
@@ -396,6 +397,13 @@ class DiagnosticReporterByTrackingStrategy(
|
||||
}
|
||||
}
|
||||
|
||||
(position as? BuilderInferenceExpectedTypeConstraintPosition)?.let {
|
||||
val inferredType =
|
||||
if (!error.lowerKotlinType.isNullableNothing()) error.lowerKotlinType
|
||||
else error.upperKotlinType.makeNullable()
|
||||
trace.report(TYPE_MISMATCH.on(it.topLevelCall, error.upperKotlinType, inferredType))
|
||||
}
|
||||
|
||||
(position as? ExplicitTypeParameterConstraintPositionImpl)?.let {
|
||||
val typeArgumentReference = (it.typeArgument as SimpleTypeArgumentImpl).typeReference
|
||||
val diagnosticFactory = if (error.isWarning) UPPER_BOUND_VIOLATED_WARNING else UPPER_BOUND_VIOLATED
|
||||
|
||||
@@ -353,7 +353,7 @@ class GenericCandidateResolver(
|
||||
resultingSystem.resultingSubstitutor.replaceWithContravariantApproximatingSubstitution()
|
||||
} else resultingSystem.resultingSubstitutor
|
||||
|
||||
resolvedCall.setResultingSubstitutor(resultingSubstitutor)
|
||||
resolvedCall.setSubstitutor(resultingSubstitutor)
|
||||
}
|
||||
|
||||
// See KT-5385
|
||||
|
||||
@@ -15,23 +15,27 @@ import org.jetbrains.kotlin.psi.psiUtil.getParentOfType
|
||||
import org.jetbrains.kotlin.psi.psiUtil.isAncestor
|
||||
import org.jetbrains.kotlin.resolve.*
|
||||
import org.jetbrains.kotlin.resolve.calls.ArgumentTypeResolver
|
||||
import org.jetbrains.kotlin.resolve.calls.callUtil.shouldBeSubstituteWithStubTypes
|
||||
import org.jetbrains.kotlin.resolve.calls.callUtil.toOldSubstitution
|
||||
import org.jetbrains.kotlin.resolve.calls.components.*
|
||||
import org.jetbrains.kotlin.resolve.calls.context.BasicCallResolutionContext
|
||||
import org.jetbrains.kotlin.resolve.calls.inference.components.ConstraintSystemCompletionMode
|
||||
import org.jetbrains.kotlin.resolve.calls.inference.components.KotlinConstraintSystemCompleter
|
||||
import org.jetbrains.kotlin.resolve.calls.inference.components.NewTypeSubstitutor
|
||||
import org.jetbrains.kotlin.resolve.calls.inference.components.NewTypeSubstitutorByConstructorMap
|
||||
import org.jetbrains.kotlin.resolve.calls.inference.components.*
|
||||
import org.jetbrains.kotlin.resolve.calls.inference.model.*
|
||||
import org.jetbrains.kotlin.resolve.calls.model.*
|
||||
import org.jetbrains.kotlin.resolve.calls.tower.*
|
||||
import org.jetbrains.kotlin.resolve.calls.util.FakeCallableDescriptorForObject
|
||||
import org.jetbrains.kotlin.resolve.deprecation.DeprecationResolver
|
||||
import org.jetbrains.kotlin.resolve.descriptorUtil.hasBuilderInferenceAnnotation
|
||||
import org.jetbrains.kotlin.resolve.descriptorUtil.shouldBeSubstituteWithStubTypes
|
||||
import org.jetbrains.kotlin.types.*
|
||||
import org.jetbrains.kotlin.types.checker.NewCapturedType
|
||||
import org.jetbrains.kotlin.types.expressions.DoubleColonExpressionResolver
|
||||
import org.jetbrains.kotlin.types.expressions.ExpressionTypingServices
|
||||
import org.jetbrains.kotlin.types.model.freshTypeConstructor
|
||||
import org.jetbrains.kotlin.types.model.safeSubstitute
|
||||
import org.jetbrains.kotlin.types.typeUtil.asTypeProjection
|
||||
import org.jetbrains.kotlin.types.typeUtil.contains
|
||||
import org.jetbrains.kotlin.types.typeUtil.shouldBeUpdated
|
||||
import org.jetbrains.kotlin.utils.addToStdlib.cast
|
||||
|
||||
class BuilderInferenceSession(
|
||||
@@ -41,7 +45,7 @@ class BuilderInferenceSession(
|
||||
callComponents: KotlinCallComponents,
|
||||
builtIns: KotlinBuiltIns,
|
||||
private val topLevelCallContext: BasicCallResolutionContext,
|
||||
private val stubsForPostponedVariables: Map<NewTypeVariable, StubType>,
|
||||
private val stubsForPostponedVariables: Map<NewTypeVariable, StubTypeForBuilderInference>,
|
||||
private val trace: BindingTrace,
|
||||
private val kotlinToResolvedCallTransformer: KotlinToResolvedCallTransformer,
|
||||
private val expressionTypingServices: ExpressionTypingServices,
|
||||
@@ -50,23 +54,27 @@ class BuilderInferenceSession(
|
||||
private val deprecationResolver: DeprecationResolver,
|
||||
private val moduleDescriptor: ModuleDescriptor,
|
||||
private val typeApproximator: TypeApproximator,
|
||||
private val missingSupertypesResolver: MissingSupertypesResolver
|
||||
private val missingSupertypesResolver: MissingSupertypesResolver,
|
||||
private val lambdaArgument: LambdaKotlinCallArgument
|
||||
) : ManyCandidatesResolver<CallableDescriptor>(
|
||||
psiCallResolver, postponedArgumentsAnalyzer, kotlinConstraintSystemCompleter, callComponents, builtIns
|
||||
) {
|
||||
private var nestedBuilderInferenceSessions: MutableSet<BuilderInferenceSession> = mutableSetOf()
|
||||
|
||||
private lateinit var lambda: ResolvedLambdaAtom
|
||||
private lateinit var commonSystem: NewConstraintSystemImpl
|
||||
private val commonSystem = NewConstraintSystemImpl(callComponents.constraintInjector, builtIns)
|
||||
|
||||
init {
|
||||
if (topLevelCallContext.inferenceSession is BuilderInferenceSession) {
|
||||
topLevelCallContext.inferenceSession.nestedBuilderInferenceSessions.add(this)
|
||||
}
|
||||
stubsForPostponedVariables.keys.forEach(commonSystem::registerVariable)
|
||||
}
|
||||
|
||||
private val commonCalls = arrayListOf<PSICompletedCallInfo>()
|
||||
|
||||
private val localVariables = arrayListOf<KtVariableDeclaration>()
|
||||
|
||||
// These calls come from the old type inference
|
||||
private val oldDoubleColonExpressionCalls = arrayListOf<KtExpression>()
|
||||
|
||||
@@ -112,7 +120,7 @@ class BuilderInferenceSession(
|
||||
|
||||
private fun KotlinType.containsStubType(): Boolean {
|
||||
return this.contains {
|
||||
it is StubType
|
||||
it is StubTypeForBuilderInference
|
||||
}
|
||||
}
|
||||
|
||||
@@ -134,20 +142,23 @@ class BuilderInferenceSession(
|
||||
|
||||
if (!checkCall) return
|
||||
|
||||
val isApplicableCall =
|
||||
callComponents.statelessCallbacks.isApplicableCallForBuilderInference(
|
||||
resultingDescriptor,
|
||||
callComponents.languageVersionSettings
|
||||
)
|
||||
val isApplicableCall = callComponents.statelessCallbacks.isApplicableCallForBuilderInference(
|
||||
resultingDescriptor,
|
||||
callComponents.languageVersionSettings
|
||||
)
|
||||
|
||||
if (!isApplicableCall) {
|
||||
hasInapplicableCall = true
|
||||
}
|
||||
}
|
||||
|
||||
fun addLocalVariable(variable: KtVariableDeclaration) {
|
||||
localVariables.add(variable)
|
||||
}
|
||||
|
||||
private fun anyReceiverContainStubType(descriptor: CallableDescriptor): Boolean {
|
||||
return descriptor.dispatchReceiverParameter?.type?.contains { it is StubType } == true ||
|
||||
descriptor.extensionReceiverParameter?.type?.contains { it is StubType } == true
|
||||
return descriptor.dispatchReceiverParameter?.type?.contains { it is StubTypeForBuilderInference } == true ||
|
||||
descriptor.extensionReceiverParameter?.type?.contains { it is StubTypeForBuilderInference } == true
|
||||
}
|
||||
|
||||
private fun isTopLevelBuilderInferenceCall() = findParentBuildInferenceSession() == null
|
||||
@@ -163,6 +174,16 @@ class BuilderInferenceSession(
|
||||
return null
|
||||
}
|
||||
|
||||
@OptIn(ExperimentalStdlibApi::class)
|
||||
private fun findAllParentBuildInferenceSessions() = buildList {
|
||||
var currentSession: BuilderInferenceSession? = findParentBuildInferenceSession()
|
||||
|
||||
while (currentSession != null) {
|
||||
add(currentSession)
|
||||
currentSession = currentSession.findParentBuildInferenceSession()
|
||||
}
|
||||
}
|
||||
|
||||
fun hasInapplicableCall(): Boolean = hasInapplicableCall
|
||||
|
||||
override fun writeOnlyStubs(callInfo: SingleCallResolutionResult): Boolean {
|
||||
@@ -190,8 +211,12 @@ class BuilderInferenceSession(
|
||||
return lhs.isAncestor(callElement)
|
||||
}
|
||||
|
||||
override fun currentConstraintSystem(): ConstraintStorage {
|
||||
return ConstraintStorage.Empty
|
||||
override fun currentConstraintSystem() = ConstraintStorage.Empty
|
||||
|
||||
fun getNotFixedToInferredTypesSubstitutor(): NewTypeSubstitutor {
|
||||
val currentSubstitutor =
|
||||
commonSystem.buildCurrentSubstitutor().cast<NewTypeSubstitutor>().takeIf { !it.isEmpty } ?: return EmptySubstitutor
|
||||
return ComposedSubstitutor(currentSubstitutor, createNonFixedTypeToVariableSubstitutor())
|
||||
}
|
||||
|
||||
override fun inferPostponedVariables(
|
||||
@@ -200,15 +225,18 @@ class BuilderInferenceSession(
|
||||
completionMode: ConstraintSystemCompletionMode,
|
||||
diagnosticsHolder: KotlinDiagnosticsHolder,
|
||||
): Map<TypeConstructor, UnwrappedType>? {
|
||||
val (commonSystem, effectivelyEmptyConstraintSystem) = buildCommonSystem(initialStorage)
|
||||
val initialStorageSubstitutor = initialStorage.buildResultingSubstitutor(commonSystem, transformTypeVariablesToErrorTypes = false)
|
||||
|
||||
this.lambda = lambda
|
||||
this.commonSystem = commonSystem
|
||||
|
||||
fun getResultingSubstitutor(): NewTypeSubstitutor {
|
||||
val storageSubstitutor = initialStorage.buildResultingSubstitutor(commonSystem, transformTypeVariablesToErrorTypes = false)
|
||||
return ComposedSubstitutor(storageSubstitutor, commonSystem.buildCurrentSubstitutor() as NewTypeSubstitutor)
|
||||
}
|
||||
|
||||
val effectivelyEmptyConstraintSystem = initializeCommonSystem(initialStorage)
|
||||
|
||||
if (effectivelyEmptyConstraintSystem) {
|
||||
if (isTopLevelBuilderInferenceCall()) {
|
||||
updateAllCalls(initialStorageSubstitutor)
|
||||
updateAllCalls(getResultingSubstitutor())
|
||||
}
|
||||
return null
|
||||
}
|
||||
@@ -222,7 +250,7 @@ class BuilderInferenceSession(
|
||||
)
|
||||
|
||||
if (isTopLevelBuilderInferenceCall()) {
|
||||
updateAllCalls(initialStorageSubstitutor)
|
||||
updateAllCalls(getResultingSubstitutor())
|
||||
}
|
||||
|
||||
return commonSystem.fixedTypeVariables.cast() // TODO: SUB
|
||||
@@ -237,12 +265,15 @@ class BuilderInferenceSession(
|
||||
private fun updateAllCalls(substitutor: NewTypeSubstitutor) {
|
||||
updateCalls(
|
||||
lambda,
|
||||
substitutor = ComposedSubstitutor(substitutor, commonSystem.buildCurrentSubstitutor() as NewTypeSubstitutor),
|
||||
substitutor = substitutor,
|
||||
commonSystem.errors
|
||||
)
|
||||
|
||||
for (nestedSession in nestedBuilderInferenceSessions) {
|
||||
nestedSession.updateAllCalls(substitutor)
|
||||
// TODO: exclude injected variables
|
||||
nestedSession.updateAllCalls(
|
||||
ComposedSubstitutor(nestedSession.commonSystem.buildCurrentSubstitutor() as NewTypeSubstitutor, substitutor)
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -267,12 +298,26 @@ class BuilderInferenceSession(
|
||||
private fun createNonFixedTypeToVariableSubstitutor() = NewTypeSubstitutorByConstructorMap(createNonFixedTypeToVariableMap())
|
||||
|
||||
private fun integrateConstraints(
|
||||
commonSystem: NewConstraintSystemImpl,
|
||||
storage: ConstraintStorage,
|
||||
nonFixedToVariablesSubstitutor: NewTypeSubstitutor,
|
||||
shouldIntegrateAllConstraints: Boolean
|
||||
): Boolean {
|
||||
storage.notFixedTypeVariables.values.forEach { commonSystem.registerVariable(it.typeVariable) }
|
||||
) {
|
||||
storage.notFixedTypeVariables.values.forEach {
|
||||
if (it.typeVariable.freshTypeConstructor(commonSystem.typeSystemContext) !in commonSystem.allTypeVariables) {
|
||||
commonSystem.registerVariable(it.typeVariable)
|
||||
}
|
||||
}
|
||||
|
||||
for (parentSession in findAllParentBuildInferenceSessions()) {
|
||||
for ((variable, stubType) in parentSession.stubsForPostponedVariables) {
|
||||
commonSystem.registerVariable(variable)
|
||||
commonSystem.addSubtypeConstraint(
|
||||
variable.defaultType,
|
||||
stubType,
|
||||
InjectedAnotherStubTypeConstraintPositionImpl(lambdaArgument)
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* storage can contain the following substitutions:
|
||||
@@ -283,16 +328,14 @@ class BuilderInferenceSession(
|
||||
* */
|
||||
val callSubstitutor = storage.buildResultingSubstitutor(commonSystem, transformTypeVariablesToErrorTypes = false)
|
||||
|
||||
var introducedConstraint = false
|
||||
|
||||
for (initialConstraint in storage.initialConstraints) {
|
||||
val lower = nonFixedToVariablesSubstitutor.safeSubstitute(callSubstitutor.safeSubstitute(initialConstraint.a as UnwrappedType)) // TODO: SUB
|
||||
val upper = nonFixedToVariablesSubstitutor.safeSubstitute(callSubstitutor.safeSubstitute(initialConstraint.b as UnwrappedType)) // TODO: SUB
|
||||
val lowerCallSubstituted = callSubstitutor.safeSubstitute(initialConstraint.a as UnwrappedType)
|
||||
val upperCallSubstituted = callSubstitutor.safeSubstitute(initialConstraint.b as UnwrappedType)
|
||||
|
||||
val (lower, upper) = substituteNotFixedVariables(lowerCallSubstituted, upperCallSubstituted, nonFixedToVariablesSubstitutor)
|
||||
|
||||
if (commonSystem.isProperType(lower) && commonSystem.isProperType(upper)) continue
|
||||
|
||||
introducedConstraint = true
|
||||
|
||||
when (initialConstraint.constraintKind) {
|
||||
ConstraintKind.LOWER -> error("LOWER constraint shouldn't be used, please use UPPER")
|
||||
|
||||
@@ -311,34 +354,73 @@ class BuilderInferenceSession(
|
||||
val typeVariable = storage.allTypeVariables.getValue(variableConstructor)
|
||||
commonSystem.registerVariable(typeVariable)
|
||||
commonSystem.addEqualityConstraint((typeVariable as NewTypeVariable).defaultType, type, CoroutinePosition)
|
||||
introducedConstraint = true
|
||||
}
|
||||
}
|
||||
|
||||
return introducedConstraint
|
||||
}
|
||||
|
||||
private fun buildCommonSystem(initialStorage: ConstraintStorage): Pair<NewConstraintSystemImpl, Boolean> {
|
||||
val commonSystem = NewConstraintSystemImpl(callComponents.constraintInjector, builtIns)
|
||||
fun addExpectedTypeConstraint(
|
||||
callExpression: KtExpression,
|
||||
a: KotlinType,
|
||||
b: KotlinType
|
||||
) {
|
||||
val nonFixedToVariablesSubstitutor: NewTypeSubstitutor = createNonFixedTypeToVariableSubstitutor()
|
||||
val (lower, upper) = substituteNotFixedVariables(a, b, nonFixedToVariablesSubstitutor)
|
||||
val position = BuilderInferenceExpectedTypeConstraintPosition(callExpression)
|
||||
val currentSubstitutor = commonSystem.buildCurrentSubstitutor()
|
||||
|
||||
commonSystem.addSubtypeConstraint(
|
||||
currentSubstitutor.safeSubstitute(commonSystem.typeSystemContext, lower),
|
||||
currentSubstitutor.safeSubstitute(commonSystem.typeSystemContext, upper),
|
||||
position
|
||||
)
|
||||
}
|
||||
|
||||
private fun substituteNotFixedVariables(
|
||||
lowerType: KotlinType,
|
||||
upperType: KotlinType,
|
||||
nonFixedToVariablesSubstitutor: NewTypeSubstitutor
|
||||
): Pair<KotlinType, KotlinType> {
|
||||
val commonCapTypes = extractCommonCapturedTypes(lowerType, upperType)
|
||||
val substitutedCommonCapType = commonCapTypes.associate {
|
||||
it.constructor as TypeConstructor to nonFixedToVariablesSubstitutor.safeSubstitute(it).asTypeProjection()
|
||||
}
|
||||
|
||||
val capTypesSubstitutor = TypeConstructorSubstitution.createByConstructorsMap(substitutedCommonCapType).buildSubstitutor()
|
||||
|
||||
val substitutedLowerType = nonFixedToVariablesSubstitutor.safeSubstitute(capTypesSubstitutor.substitute(lowerType.unwrap()))
|
||||
val substitutedUpperType = nonFixedToVariablesSubstitutor.safeSubstitute(capTypesSubstitutor.substitute(upperType.unwrap()))
|
||||
|
||||
return substitutedLowerType to substitutedUpperType
|
||||
}
|
||||
|
||||
private fun extractCommonCapturedTypes(a: KotlinType, b: KotlinType): List<NewCapturedType> {
|
||||
val extractedCapturedTypes = mutableSetOf<NewCapturedType>().also { extractCapturedTypesTo(a, it) }
|
||||
return extractedCapturedTypes.filter { capturedType -> b.contains { it.constructor === capturedType.constructor } }
|
||||
}
|
||||
|
||||
private fun extractCapturedTypesTo(type: KotlinType, to: MutableSet<NewCapturedType>) {
|
||||
if (type is NewCapturedType) {
|
||||
to.add(type)
|
||||
}
|
||||
for (typeArgument in type.arguments) {
|
||||
if (typeArgument.isStarProjection) continue
|
||||
extractCapturedTypesTo(typeArgument.type, to)
|
||||
}
|
||||
}
|
||||
|
||||
private fun initializeCommonSystem(initialStorage: ConstraintStorage): Boolean {
|
||||
val nonFixedToVariablesSubstitutor = createNonFixedTypeToVariableSubstitutor()
|
||||
|
||||
integrateConstraints(commonSystem, initialStorage, nonFixedToVariablesSubstitutor, false)
|
||||
|
||||
var effectivelyEmptyCommonSystem = true
|
||||
integrateConstraints(initialStorage, nonFixedToVariablesSubstitutor, false)
|
||||
|
||||
for (call in commonCalls) {
|
||||
val hasConstraints =
|
||||
integrateConstraints(commonSystem, call.callResolutionResult.constraintSystem, nonFixedToVariablesSubstitutor, false)
|
||||
if (hasConstraints) effectivelyEmptyCommonSystem = false
|
||||
integrateConstraints(call.callResolutionResult.constraintSystem, nonFixedToVariablesSubstitutor, false)
|
||||
}
|
||||
for (call in partiallyResolvedCallsInfo) {
|
||||
val hasConstraints =
|
||||
integrateConstraints(commonSystem, call.callResolutionResult.constraintSystem, nonFixedToVariablesSubstitutor, true)
|
||||
if (hasConstraints) effectivelyEmptyCommonSystem = false
|
||||
integrateConstraints(call.callResolutionResult.constraintSystem, nonFixedToVariablesSubstitutor, true)
|
||||
}
|
||||
|
||||
return commonSystem to effectivelyEmptyCommonSystem
|
||||
return commonSystem.notFixedTypeVariables.all { it.value.constraints.isEmpty() }
|
||||
}
|
||||
|
||||
private fun reportErrors(completedCall: CallInfo, resolvedCall: ResolvedCall<*>, errors: List<ConstraintSystemError>) {
|
||||
@@ -351,6 +433,13 @@ class BuilderInferenceSession(
|
||||
)
|
||||
}
|
||||
|
||||
private fun updateLocalVariable(localVariable: KtVariableDeclaration, substitutor: NewTypeSubstitutor) {
|
||||
val descriptor = trace[BindingContext.VARIABLE, localVariable] as? LocalVariableDescriptor
|
||||
if (descriptor != null && descriptor.type.shouldBeUpdated()) {
|
||||
descriptor.setOutType(substitutor.safeSubstitute(descriptor.type.unwrap()))
|
||||
}
|
||||
}
|
||||
|
||||
private fun updateCall(
|
||||
completedCall: PSICompletedCallInfo,
|
||||
nonFixedTypesToResultSubstitutor: NewTypeSubstitutor,
|
||||
@@ -378,7 +467,7 @@ class BuilderInferenceSession(
|
||||
return currentSession.topLevelCallContext.trace
|
||||
}
|
||||
|
||||
private fun completeDoubleColonExpression(expression: KtDoubleColonExpression, substitutor: NewTypeSubstitutor) {
|
||||
fun completeDoubleColonExpression(expression: KtDoubleColonExpression, substitutor: NewTypeSubstitutor) {
|
||||
val atomCompleter = createResolvedAtomCompleter(substitutor, topLevelCallContext)
|
||||
val declarationDescriptor = trace.get(BindingContext.DECLARATION_TO_DESCRIPTOR, expression)
|
||||
|
||||
@@ -402,7 +491,13 @@ class BuilderInferenceSession(
|
||||
val resolvedCall = trace.get(BindingContext.RESOLVED_CALL, call)
|
||||
|
||||
if (resolvedCall is ResolvedCallImpl<*>) {
|
||||
resolvedCall.setResultingSubstitutor(substitutor.toOldSubstitution().buildSubstitutor())
|
||||
val oldSubstitutor = substitutor.toOldSubstitution().buildSubstitutor()
|
||||
if (resolvedCall.resultingDescriptor.shouldBeSubstituteWithStubTypes()) {
|
||||
resolvedCall.setResultingSubstitutor(oldSubstitutor)
|
||||
}
|
||||
if (resolvedCall.shouldBeSubstituteWithStubTypes()) {
|
||||
resolvedCall.setResolvedCallSubstitutor(oldSubstitutor)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -463,6 +558,10 @@ class BuilderInferenceSession(
|
||||
topLevelCallContext.replaceBindingTrace(findTopLevelTrace()).replaceInferenceSession(this)
|
||||
)
|
||||
|
||||
for (localVariable in localVariables) {
|
||||
updateLocalVariable(localVariable, nonFixedTypesToResultSubstitutor)
|
||||
}
|
||||
|
||||
for (completedCall in commonCalls) {
|
||||
updateCall(completedCall, nonFixedTypesToResultSubstitutor, nonFixedTypesToResult)
|
||||
reportErrors(completedCall, completedCall.resolvedCall, errors)
|
||||
@@ -493,3 +592,5 @@ class ComposedSubstitutor(val left: NewTypeSubstitutor, val right: NewTypeSubsti
|
||||
|
||||
override val isEmpty: Boolean get() = left.isEmpty && right.isEmpty
|
||||
}
|
||||
|
||||
class BuilderInferenceExpectedTypeConstraintPosition(callElement: KtExpression) : ExpectedTypeConstraintPosition<KtExpression>(callElement)
|
||||
|
||||
@@ -14,10 +14,7 @@ import org.jetbrains.kotlin.descriptors.CallableDescriptor
|
||||
import org.jetbrains.kotlin.descriptors.FunctionDescriptor
|
||||
import org.jetbrains.kotlin.descriptors.ValueParameterDescriptor
|
||||
import org.jetbrains.kotlin.descriptors.annotations.Annotations
|
||||
import org.jetbrains.kotlin.psi.KtExpression
|
||||
import org.jetbrains.kotlin.psi.KtFunction
|
||||
import org.jetbrains.kotlin.psi.KtLambdaExpression
|
||||
import org.jetbrains.kotlin.psi.ValueArgument
|
||||
import org.jetbrains.kotlin.psi.*
|
||||
import org.jetbrains.kotlin.renderer.DescriptorRenderer
|
||||
import org.jetbrains.kotlin.renderer.DescriptorRendererOptions
|
||||
import org.jetbrains.kotlin.resolve.calls.ArgumentTypeResolver
|
||||
@@ -299,9 +296,11 @@ class CoroutineInferenceSupport(
|
||||
}
|
||||
}
|
||||
|
||||
private fun KotlinType.containsTypeTemplate() = contains { it is TypeTemplate || it is StubType }
|
||||
private fun KotlinType.containsTypeTemplate() = contains { it is TypeTemplate || it is StubTypeForBuilderInference }
|
||||
|
||||
fun isApplicableCallForBuilderInference(descriptor: CallableDescriptor, languageVersionSettings: LanguageVersionSettings): Boolean {
|
||||
if (languageVersionSettings.supportsFeature(LanguageFeature.UnrestrictedBuilderInference)) return true
|
||||
|
||||
if (!languageVersionSettings.supportsFeature(LanguageFeature.ExperimentalBuilderInference)) {
|
||||
return isGoodCallForOldCoroutines(descriptor)
|
||||
}
|
||||
@@ -335,8 +334,11 @@ fun isCoroutineCallWithAdditionalInference(
|
||||
else
|
||||
parameterDescriptor.hasSuspendFunctionType
|
||||
|
||||
val pureExpression = argument.getArgumentExpression()
|
||||
val baseExpression = if (pureExpression is KtLabeledExpression) pureExpression.baseExpression else pureExpression
|
||||
|
||||
return parameterHasOptIn &&
|
||||
argument.getArgumentExpression() is KtLambdaExpression &&
|
||||
baseExpression is KtLambdaExpression &&
|
||||
parameterDescriptor.type.let { it.isBuiltinFunctionalType && it.getReceiverTypeFromFunctionType() != null }
|
||||
}
|
||||
|
||||
|
||||
@@ -64,7 +64,7 @@ public interface MutableResolvedCall<D extends CallableDescriptor> extends Resol
|
||||
|
||||
void setConstraintSystem(@NotNull ConstraintSystem constraintSystem);
|
||||
|
||||
void setResultingSubstitutor(@NotNull TypeSubstitutor substitutor);
|
||||
void setSubstitutor(@NotNull TypeSubstitutor substitutor);
|
||||
|
||||
@Nullable
|
||||
TypeSubstitutor getKnownTypeParametersSubstitutor();
|
||||
|
||||
@@ -35,6 +35,7 @@ import org.jetbrains.kotlin.resolve.calls.results.ResolutionStatus;
|
||||
import org.jetbrains.kotlin.resolve.calls.tasks.ExplicitReceiverKind;
|
||||
import org.jetbrains.kotlin.resolve.calls.tasks.ResolutionCandidate;
|
||||
import org.jetbrains.kotlin.resolve.calls.tasks.TracingStrategy;
|
||||
import org.jetbrains.kotlin.resolve.descriptorUtil.DescriptorUtilsKt;
|
||||
import org.jetbrains.kotlin.resolve.scopes.receivers.*;
|
||||
import org.jetbrains.kotlin.types.KotlinType;
|
||||
import org.jetbrains.kotlin.types.TypeProjection;
|
||||
@@ -42,6 +43,7 @@ import org.jetbrains.kotlin.types.TypeSubstitutor;
|
||||
import org.jetbrains.kotlin.types.Variance;
|
||||
|
||||
import java.util.*;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
import static org.jetbrains.kotlin.resolve.calls.results.ResolutionStatus.INCOMPLETE_TYPE_INFERENCE;
|
||||
import static org.jetbrains.kotlin.resolve.calls.results.ResolutionStatus.UNKNOWN_STATUS;
|
||||
@@ -68,7 +70,7 @@ public class ResolvedCallImpl<D extends CallableDescriptor> implements MutableRe
|
||||
private final TypeSubstitutor knownTypeParametersSubstitutor;
|
||||
|
||||
@NotNull
|
||||
private final Map<TypeParameterDescriptor, KotlinType> typeArguments;
|
||||
private Map<TypeParameterDescriptor, KotlinType> typeArguments;
|
||||
@NotNull
|
||||
private final Map<ValueParameterDescriptor, ResolvedValueArgument> valueArguments;
|
||||
private final MutableDataFlowInfoForArguments dataFlowInfoForArguments;
|
||||
@@ -193,19 +195,15 @@ public class ResolvedCallImpl<D extends CallableDescriptor> implements MutableRe
|
||||
return resultingDescriptor == null ? candidateDescriptor : resultingDescriptor;
|
||||
}
|
||||
|
||||
@Override
|
||||
@SuppressWarnings("unchecked")
|
||||
public void setResultingSubstitutor(@NotNull TypeSubstitutor substitutor) {
|
||||
resultingDescriptor = (D) candidateDescriptor.substitute(substitutor);
|
||||
//noinspection ConstantConditions
|
||||
if (resultingDescriptor == null) {
|
||||
throw new AssertionError(
|
||||
"resultingDescriptor shouldn't be null:\n" +
|
||||
"candidateDescriptor: " + DescriptorRenderer.COMPACT_WITH_SHORT_TYPES.render(candidateDescriptor) + "\n" +
|
||||
"substitution: " + substitutor.getSubstitution()
|
||||
);
|
||||
}
|
||||
D descriptorToSubstitute = resultingDescriptor != null && DescriptorUtilsKt.shouldBeSubstituteWithStubTypes(resultingDescriptor)
|
||||
? resultingDescriptor
|
||||
: candidateDescriptor;
|
||||
resultingDescriptor = (D) descriptorToSubstitute.substitute(substitutor);
|
||||
}
|
||||
|
||||
public void setResolvedCallSubstitutor(@NotNull TypeSubstitutor substitutor) {
|
||||
for (TypeParameterDescriptor typeParameter : candidateDescriptor.getTypeParameters()) {
|
||||
TypeProjection typeArgumentProjection = substitutor.getSubstitution().get(typeParameter.getDefaultType());
|
||||
if (typeArgumentProjection != null) {
|
||||
@@ -213,6 +211,17 @@ public class ResolvedCallImpl<D extends CallableDescriptor> implements MutableRe
|
||||
}
|
||||
}
|
||||
|
||||
typeArguments = typeArguments.entrySet().stream()
|
||||
.collect(Collectors.toMap(Map.Entry::getKey, e -> substitutor.safeSubstitute(e.getValue(), e.getKey().getVariance())));
|
||||
|
||||
if (dispatchReceiver instanceof ExpressionReceiver) {
|
||||
dispatchReceiver = dispatchReceiver.replaceType(substitutor.safeSubstitute(dispatchReceiver.getType(), Variance.IN_VARIANCE));
|
||||
}
|
||||
if (extensionReceiver instanceof ExtensionReceiver) {
|
||||
extensionReceiver =
|
||||
extensionReceiver.replaceType(substitutor.safeSubstitute(extensionReceiver.getType(), Variance.IN_VARIANCE));
|
||||
}
|
||||
|
||||
if (candidateDescriptor.getValueParameters().isEmpty()) return;
|
||||
|
||||
List<ValueParameterDescriptor> substitutedParameters = resultingDescriptor.getValueParameters();
|
||||
@@ -239,14 +248,12 @@ public class ResolvedCallImpl<D extends CallableDescriptor> implements MutableRe
|
||||
assert substitutedVersion != null : valueParameterDescriptor;
|
||||
argumentToParameterMap.put(entry.getKey(), argumentMatch.replaceValueParameter(substitutedVersion));
|
||||
}
|
||||
}
|
||||
|
||||
if (dispatchReceiver instanceof ExpressionReceiver) {
|
||||
dispatchReceiver = dispatchReceiver.replaceType(substitutor.safeSubstitute(dispatchReceiver.getType(), Variance.IN_VARIANCE));
|
||||
}
|
||||
if (extensionReceiver instanceof ExtensionReceiver) {
|
||||
extensionReceiver =
|
||||
extensionReceiver.replaceType(substitutor.safeSubstitute(extensionReceiver.getType(), Variance.IN_VARIANCE));
|
||||
}
|
||||
@Override
|
||||
public void setSubstitutor(@NotNull TypeSubstitutor substitutor) {
|
||||
setResultingSubstitutor(substitutor);
|
||||
setResolvedCallSubstitutor(substitutor);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -30,6 +30,7 @@ import org.jetbrains.kotlin.resolve.BindingContext.SMARTCAST
|
||||
import org.jetbrains.kotlin.resolve.BindingTrace
|
||||
import org.jetbrains.kotlin.resolve.calls.ArgumentTypeResolver
|
||||
import org.jetbrains.kotlin.resolve.calls.context.ResolutionContext
|
||||
import org.jetbrains.kotlin.resolve.calls.inference.BuilderInferenceSession
|
||||
import org.jetbrains.kotlin.resolve.scopes.receivers.ImplicitReceiver
|
||||
import org.jetbrains.kotlin.resolve.scopes.receivers.ReceiverValue
|
||||
import org.jetbrains.kotlin.types.KotlinType
|
||||
@@ -136,7 +137,10 @@ class SmartCastManager(private val argumentTypeResolver: ArgumentTypeResolver) {
|
||||
else
|
||||
listOf(expectedType)
|
||||
|
||||
val collectedTypes = c.dataFlowInfo.getCollectedTypes(dataFlowValue, c.languageVersionSettings).toMutableList()
|
||||
val builderInferenceSubstitutor = (c.inferenceSession as? BuilderInferenceSession)?.getNotFixedToInferredTypesSubstitutor()
|
||||
val collectedTypes = c.dataFlowInfo.getCollectedTypes(dataFlowValue, c.languageVersionSettings).let { types ->
|
||||
if (builderInferenceSubstitutor != null) types.map { builderInferenceSubstitutor.safeSubstitute(it.unwrap()) } else types
|
||||
}.toMutableList()
|
||||
|
||||
if (collectedTypes.isNotEmpty() && c.languageVersionSettings.supportsFeature(LanguageFeature.NewInference)) {
|
||||
// Sometime expected type may be inferred to be an intersection of all of the smart-cast types
|
||||
|
||||
@@ -90,7 +90,7 @@ class KotlinResolutionCallbacksImpl(
|
||||
parameters: List<UnwrappedType>,
|
||||
expectedReturnType: UnwrappedType?,
|
||||
annotations: Annotations,
|
||||
stubsForPostponedVariables: Map<NewTypeVariable, StubType>,
|
||||
stubsForPostponedVariables: Map<NewTypeVariable, StubTypeForBuilderInference>,
|
||||
): ReturnArgumentsAnalysisResult {
|
||||
val psiCallArgument = lambdaArgument.psiCallArgument as PSIFunctionKotlinCallArgument
|
||||
val outerCallContext = psiCallArgument.outerCallContext
|
||||
@@ -167,7 +167,7 @@ class KotlinResolutionCallbacksImpl(
|
||||
callComponents, builtIns, topLevelCallContext, stubsForPostponedVariables, trace,
|
||||
kotlinToResolvedCallTransformer, expressionTypingServices, argumentTypeResolver,
|
||||
doubleColonExpressionResolver, deprecationResolver, moduleDescriptor, typeApproximator,
|
||||
missingSupertypesResolver
|
||||
missingSupertypesResolver, lambdaArgument
|
||||
)
|
||||
} else {
|
||||
null
|
||||
|
||||
@@ -48,6 +48,7 @@ import org.jetbrains.kotlin.resolve.constants.IntegerLiteralTypeConstructor
|
||||
import org.jetbrains.kotlin.resolve.constants.IntegerValueTypeConstant
|
||||
import org.jetbrains.kotlin.resolve.constants.evaluate.ConstantExpressionEvaluator
|
||||
import org.jetbrains.kotlin.resolve.deprecation.DeprecationResolver
|
||||
import org.jetbrains.kotlin.resolve.diagnostics.MutableDiagnosticsWithSuppression
|
||||
import org.jetbrains.kotlin.resolve.scopes.receivers.CastImplicitClassReceiver
|
||||
import org.jetbrains.kotlin.resolve.scopes.receivers.ImplicitClassReceiver
|
||||
import org.jetbrains.kotlin.resolve.scopes.receivers.ReceiverValue
|
||||
@@ -355,6 +356,7 @@ class KotlinToResolvedCallTransformer(
|
||||
} ?: return null
|
||||
|
||||
val recordedType = context.trace.getType(deparenthesized)
|
||||
val recordedTypeForParenthesized = context.trace.getType(expression)
|
||||
|
||||
var updatedType = convertedArgumentType ?: getResolvedCallForArgumentExpression(deparenthesized, context)?.run {
|
||||
makeNullableTypeIfSafeReceiver(resultingDescriptor.returnType, context)
|
||||
@@ -384,7 +386,7 @@ class KotlinToResolvedCallTransformer(
|
||||
context.trace.report(Errors.SIGNED_CONSTANT_CONVERTED_TO_UNSIGNED.on(deparenthesized))
|
||||
}
|
||||
|
||||
updatedType = updateRecordedTypeForArgument(updatedType, recordedType, expression, context)
|
||||
updatedType = updateRecordedTypeForArgument(updatedType, recordedType, recordedTypeForParenthesized, expression, context)
|
||||
|
||||
dataFlowAnalyzer.checkType(updatedType, deparenthesized, context, reportErrorDuringTypeCheck)
|
||||
|
||||
@@ -410,10 +412,12 @@ class KotlinToResolvedCallTransformer(
|
||||
private fun updateRecordedTypeForArgument(
|
||||
updatedType: KotlinType?,
|
||||
recordedType: KotlinType?,
|
||||
recordedTypeForParenthesized: KotlinType?,
|
||||
argumentExpression: KtExpression,
|
||||
context: BasicCallResolutionContext,
|
||||
): KotlinType? {
|
||||
if ((!ErrorUtils.containsErrorType(recordedType) && recordedType == updatedType) || updatedType == null) return updatedType
|
||||
if ((!ErrorUtils.containsErrorType(recordedType) && recordedType == updatedType && recordedType == recordedTypeForParenthesized) || updatedType == null)
|
||||
return updatedType
|
||||
|
||||
val expressions = ArrayList<KtExpression>().also { expressions ->
|
||||
var expression: KtExpression? = argumentExpression
|
||||
@@ -551,6 +555,8 @@ class TrackingBindingTrace(val trace: BindingTrace) : BindingTrace by trace {
|
||||
var reported: Boolean = false
|
||||
|
||||
override fun report(diagnostic: Diagnostic) {
|
||||
if (bindingContext.diagnostics.noSuppression().forElement(diagnostic.psiElement).any { it == diagnostic }) return
|
||||
|
||||
trace.report(diagnostic)
|
||||
reported = true
|
||||
}
|
||||
@@ -989,7 +995,7 @@ private fun CallableMemberDescriptor.isNotSimpleCall(): Boolean =
|
||||
it is NewCapturedType ||
|
||||
it.constructor is IntegerLiteralTypeConstructor ||
|
||||
it is DefinitelyNotNullType ||
|
||||
it is StubType
|
||||
it is StubTypeForBuilderInference
|
||||
}
|
||||
} ?: false)
|
||||
|
||||
|
||||
@@ -7,6 +7,7 @@ package org.jetbrains.kotlin.resolve.calls.tower
|
||||
|
||||
import org.jetbrains.kotlin.builtins.KotlinBuiltIns
|
||||
import org.jetbrains.kotlin.builtins.createFunctionType
|
||||
import org.jetbrains.kotlin.config.LanguageFeature
|
||||
import org.jetbrains.kotlin.descriptors.*
|
||||
import org.jetbrains.kotlin.descriptors.impl.ReceiverParameterDescriptorImpl
|
||||
import org.jetbrains.kotlin.descriptors.impl.SimpleFunctionDescriptorImpl
|
||||
@@ -14,10 +15,7 @@ import org.jetbrains.kotlin.descriptors.impl.ValueParameterDescriptorImpl
|
||||
import org.jetbrains.kotlin.diagnostics.Errors
|
||||
import org.jetbrains.kotlin.diagnostics.reportDiagnosticOnce
|
||||
import org.jetbrains.kotlin.psi.*
|
||||
import org.jetbrains.kotlin.resolve.BindingContext
|
||||
import org.jetbrains.kotlin.resolve.BindingTrace
|
||||
import org.jetbrains.kotlin.resolve.MissingSupertypesResolver
|
||||
import org.jetbrains.kotlin.resolve.TemporaryBindingTrace
|
||||
import org.jetbrains.kotlin.resolve.*
|
||||
import org.jetbrains.kotlin.resolve.calls.ArgumentTypeResolver
|
||||
import org.jetbrains.kotlin.resolve.calls.NewCommonSuperTypeCalculator
|
||||
import org.jetbrains.kotlin.resolve.calls.callUtil.toOldSubstitution
|
||||
@@ -29,6 +27,7 @@ import org.jetbrains.kotlin.resolve.calls.components.SuspendConversionStrategy
|
||||
import org.jetbrains.kotlin.resolve.calls.components.isVararg
|
||||
import org.jetbrains.kotlin.resolve.calls.context.BasicCallResolutionContext
|
||||
import org.jetbrains.kotlin.resolve.calls.context.ContextDependency
|
||||
import org.jetbrains.kotlin.resolve.calls.inference.BuilderInferenceSession
|
||||
import org.jetbrains.kotlin.resolve.calls.inference.components.NewTypeSubstitutor
|
||||
import org.jetbrains.kotlin.resolve.calls.inference.components.NewTypeSubstitutorByConstructorMap
|
||||
import org.jetbrains.kotlin.resolve.calls.model.*
|
||||
@@ -46,9 +45,7 @@ import org.jetbrains.kotlin.types.expressions.CoercionStrategy
|
||||
import org.jetbrains.kotlin.types.expressions.DoubleColonExpressionResolver
|
||||
import org.jetbrains.kotlin.types.expressions.ExpressionTypingServices
|
||||
import org.jetbrains.kotlin.types.expressions.typeInfoFactory.createTypeInfo
|
||||
import org.jetbrains.kotlin.types.typeUtil.contains
|
||||
import org.jetbrains.kotlin.types.typeUtil.isUnit
|
||||
import org.jetbrains.kotlin.types.typeUtil.shouldBeUpdated
|
||||
import org.jetbrains.kotlin.types.typeUtil.*
|
||||
import org.jetbrains.kotlin.utils.addToStdlib.safeAs
|
||||
|
||||
class ResolvedAtomCompleter(
|
||||
@@ -89,9 +86,22 @@ class ResolvedAtomCompleter(
|
||||
is ResolvedLambdaAtom -> completeLambda(resolvedAtom)
|
||||
is ResolvedCallAtom -> completeResolvedCall(resolvedAtom, emptyList())
|
||||
is ResolvedSubCallArgument -> completeSubCallArgument(resolvedAtom)
|
||||
is ResolvedExpressionAtom -> completeExpression(resolvedAtom)
|
||||
}
|
||||
}
|
||||
|
||||
// We run completion on expressions only for last statements of block expression to substitute freshly inferred stub types variables
|
||||
fun completeExpression(resolvedAtom: ResolvedExpressionAtom) {
|
||||
val argumentExpression = resolvedAtom.atom.psiExpression
|
||||
val inferenceSession = topLevelCallContext.inferenceSession
|
||||
|
||||
if (argumentExpression !is KtBlockExpression || inferenceSession !is BuilderInferenceSession) return
|
||||
|
||||
val callableReference = argumentExpression.statements.lastOrNull() as? KtCallableReferenceExpression ?: return
|
||||
|
||||
inferenceSession.completeDoubleColonExpression(callableReference, inferenceSession.getNotFixedToInferredTypesSubstitutor())
|
||||
}
|
||||
|
||||
fun completeAll(resolvedAtom: ResolvedAtom) {
|
||||
if (!resolvedAtom.analyzed)
|
||||
return
|
||||
@@ -142,6 +152,14 @@ class ResolvedAtomCompleter(
|
||||
else -> atom.psiKotlinCall.psiCall
|
||||
}
|
||||
|
||||
val callElement = psiCallForResolutionContext.callElement
|
||||
if (callElement is KtExpression) {
|
||||
val recordedType = topLevelCallContext.trace.getType(callElement)
|
||||
if (recordedType != null && recordedType.shouldBeUpdated() && resolvedCall.resultingDescriptor.returnType != null) {
|
||||
topLevelCallContext.trace.recordType(callElement, resolvedCall.resultingDescriptor.returnType)
|
||||
}
|
||||
}
|
||||
|
||||
val resolutionContextForPartialCall =
|
||||
topLevelCallContext.trace[BindingContext.PARTIAL_CALL_RESOLUTION_CONTEXT, psiCallForResolutionContext]
|
||||
|
||||
@@ -383,7 +401,7 @@ class ResolvedAtomCompleter(
|
||||
|
||||
private fun extractCallableReferenceResultTypeInfoFromDescriptor(
|
||||
callableCandidate: CallableReferenceCandidate,
|
||||
recorderDescriptor: CallableDescriptor
|
||||
recordedDescriptor: CallableDescriptor
|
||||
): CallableReferenceResultTypeInfo {
|
||||
val explicitCallableReceiver = when (callableCandidate.explicitReceiverKind) {
|
||||
ExplicitReceiverKind.DISPATCH_RECEIVER -> callableCandidate.dispatchReceiver
|
||||
@@ -391,14 +409,31 @@ class ResolvedAtomCompleter(
|
||||
else -> null
|
||||
}
|
||||
return CallableReferenceResultTypeInfo(
|
||||
recorderDescriptor.dispatchReceiverParameter?.value,
|
||||
recorderDescriptor.extensionReceiverParameter?.value,
|
||||
recordedDescriptor.dispatchReceiverParameter?.value,
|
||||
recordedDescriptor.extensionReceiverParameter?.value,
|
||||
explicitCallableReceiver?.receiver?.receiverValue,
|
||||
TypeSubstitutor.EMPTY,
|
||||
callableCandidate.reflectionCandidateType
|
||||
callableCandidate.reflectionCandidateType.replaceFunctionTypeArgumentsByDescriptor(recordedDescriptor)
|
||||
)
|
||||
}
|
||||
|
||||
@OptIn(ExperimentalStdlibApi::class)
|
||||
private fun KotlinType.replaceFunctionTypeArgumentsByDescriptor(descriptor: CallableDescriptor) =
|
||||
when (descriptor) {
|
||||
is CallableMemberDescriptor -> {
|
||||
val newArgumentTypes = buildList {
|
||||
descriptor.extensionReceiverParameter?.let { add(it.type) }
|
||||
addAll(descriptor.valueParameters.map { it.type })
|
||||
add(descriptor.returnType)
|
||||
}
|
||||
if (newArgumentTypes.size == arguments.size) {
|
||||
replace(arguments.mapIndexed { i, type -> newArgumentTypes[i]?.let { type.replaceType(it) } ?: type })
|
||||
} else this
|
||||
}
|
||||
is ValueDescriptor -> replace(descriptor.type.arguments)
|
||||
else -> this
|
||||
}
|
||||
|
||||
private fun completeCallableReference(resolvedAtom: ResolvedCallableReferenceAtom) {
|
||||
val psiCallArgument = resolvedAtom.atom.psiCallArgument as CallableReferenceKotlinCallArgumentImpl
|
||||
val callableReferenceExpression = psiCallArgument.ktCallableReferenceExpression
|
||||
@@ -415,7 +450,10 @@ class ResolvedAtomCompleter(
|
||||
|
||||
val rawExtensionReceiver = callableCandidate.extensionReceiver
|
||||
|
||||
if (rawExtensionReceiver != null && rawExtensionReceiver.receiver.receiverValue.type.contains { it is StubType }) {
|
||||
val unrestrictedBuilderInferenceSupported =
|
||||
topLevelCallContext.languageVersionSettings.supportsFeature(LanguageFeature.UnrestrictedBuilderInference)
|
||||
|
||||
if (rawExtensionReceiver != null && !unrestrictedBuilderInferenceSupported && rawExtensionReceiver.receiver.receiverValue.type.contains { it is StubTypeForBuilderInference }) {
|
||||
topLevelTrace.reportDiagnosticOnce(Errors.TYPE_INFERENCE_POSTPONED_VARIABLE_IN_RECEIVER_TYPE.on(callableReferenceExpression))
|
||||
return
|
||||
}
|
||||
@@ -439,7 +477,7 @@ class ResolvedAtomCompleter(
|
||||
null, temporaryTrace, tracing, MutableDataFlowInfoForArguments.WithoutArgumentsCheck(DataFlowInfo.EMPTY)
|
||||
)
|
||||
|
||||
resolvedCall.setResultingSubstitutor(resultTypeInfo.substitutor)
|
||||
resolvedCall.setSubstitutor(resultTypeInfo.substitutor)
|
||||
|
||||
recordArgumentAdaptationForCallableReference(resolvedCall, callableCandidate.callableReferenceAdaptation)
|
||||
|
||||
|
||||
@@ -37,11 +37,9 @@ import org.jetbrains.kotlin.resolve.calls.inference.components.NewTypeSubstituto
|
||||
import org.jetbrains.kotlin.resolve.calls.model.*
|
||||
import org.jetbrains.kotlin.resolve.calls.tower.NewResolvedCallImpl
|
||||
import org.jetbrains.kotlin.resolve.scopes.receivers.ExpressionReceiver
|
||||
import org.jetbrains.kotlin.types.KotlinType
|
||||
import org.jetbrains.kotlin.types.TypeProjection
|
||||
import org.jetbrains.kotlin.types.TypeSubstitution
|
||||
import org.jetbrains.kotlin.types.isError
|
||||
import org.jetbrains.kotlin.types.*
|
||||
import org.jetbrains.kotlin.types.typeUtil.asTypeProjection
|
||||
import org.jetbrains.kotlin.types.typeUtil.contains
|
||||
import org.jetbrains.kotlin.utils.addToStdlib.safeAs
|
||||
import org.jetbrains.kotlin.utils.sure
|
||||
|
||||
@@ -335,3 +333,9 @@ fun NewTypeSubstitutor.toOldSubstitution(): TypeSubstitution = object : TypeSubs
|
||||
return isEmpty
|
||||
}
|
||||
}
|
||||
|
||||
fun <D : CallableDescriptor> ResolvedCallImpl<D>.shouldBeSubstituteWithStubTypes() =
|
||||
typeArguments.any { argument -> argument.value.contains { it is StubTypeForBuilderInference } }
|
||||
|| dispatchReceiver?.type?.contains { it is StubTypeForBuilderInference } == true
|
||||
|| extensionReceiver?.type?.contains { it is StubTypeForBuilderInference } == true
|
||||
|| valueArguments.any { argument -> argument.key.type.contains { it is StubTypeForBuilderInference } }
|
||||
|
||||
@@ -38,6 +38,7 @@ import org.jetbrains.kotlin.resolve.multiplatform.ExpectedActualResolver.Compati
|
||||
import org.jetbrains.kotlin.resolve.multiplatform.ExpectedActualResolver.Compatibility.Compatible
|
||||
import org.jetbrains.kotlin.resolve.multiplatform.ExpectedActualResolver.Compatibility.Incompatible
|
||||
import org.jetbrains.kotlin.resolve.multiplatform.ModuleFilter
|
||||
import org.jetbrains.kotlin.resolve.multiplatform.OptionalAnnotationUtil
|
||||
import org.jetbrains.kotlin.resolve.source.PsiSourceFile
|
||||
import org.jetbrains.kotlin.types.KotlinType
|
||||
import org.jetbrains.kotlin.utils.addToStdlib.safeAs
|
||||
@@ -171,7 +172,7 @@ class ExpectedActualDeclarationChecker(
|
||||
val compatibility = ExpectedActualResolver.findActualForExpected(descriptor, module, moduleVisibilityFilter) ?: return
|
||||
|
||||
// Only strong incompatibilities, but this is an OptionalExpectation -- don't report it
|
||||
if (compatibility.allStrongIncompatibilities() && isOptionalAnnotationClass(descriptor)) return
|
||||
if (compatibility.allStrongIncompatibilities() && OptionalAnnotationUtil.isOptionalAnnotationClass(descriptor)) return
|
||||
|
||||
// Only strong incompatibilities, or error won't be reported on actual: report NO_ACTUAL_FOR_EXPECT here
|
||||
if (compatibility.allStrongIncompatibilities() ||
|
||||
@@ -389,41 +390,7 @@ class ExpectedActualDeclarationChecker(
|
||||
}
|
||||
|
||||
companion object {
|
||||
val OPTIONAL_EXPECTATION_FQ_NAME = FqName("kotlin.OptionalExpectation")
|
||||
|
||||
@JvmStatic
|
||||
fun isOptionalAnnotationClass(descriptor: DeclarationDescriptor): Boolean =
|
||||
descriptor is ClassDescriptor &&
|
||||
descriptor.kind == ClassKind.ANNOTATION_CLASS &&
|
||||
descriptor.isExpect &&
|
||||
descriptor.annotations.hasAnnotation(OPTIONAL_EXPECTATION_FQ_NAME)
|
||||
|
||||
// TODO: move to some other place which is accessible both from backend-common and js.serializer
|
||||
@JvmStatic
|
||||
fun shouldGenerateExpectClass(descriptor: ClassDescriptor): Boolean {
|
||||
assert(descriptor.isExpect) { "Not an expected class: $descriptor" }
|
||||
|
||||
if (isOptionalAnnotationClass(descriptor)) {
|
||||
with(ExpectedActualResolver) {
|
||||
return descriptor.findCompatibleActualForExpected(descriptor.module).isEmpty()
|
||||
}
|
||||
}
|
||||
|
||||
return false
|
||||
}
|
||||
|
||||
fun Map<out Compatibility, Collection<MemberDescriptor>>.allStrongIncompatibilities(): Boolean =
|
||||
this.keys.all { it is Incompatible && it.kind == Compatibility.IncompatibilityKind.STRONG }
|
||||
|
||||
private fun <K, V> LinkedHashMap<K, List<V>>.merge(other: Map<K, List<V>>): LinkedHashMap<K, List<V>> {
|
||||
for ((key, newValue) in other) {
|
||||
val oldValue = this[key] ?: emptyList()
|
||||
this[key] = oldValue + newValue
|
||||
}
|
||||
|
||||
return this
|
||||
}
|
||||
|
||||
private fun ModuleInfo.unwrapModuleInfo(): List<ModuleInfo> = if (this is CombinedModuleInfo) this.containedModules else listOf(this)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -14,6 +14,7 @@ import org.jetbrains.kotlin.psi.KtDeclaration
|
||||
import org.jetbrains.kotlin.resolve.BindingContext
|
||||
import org.jetbrains.kotlin.resolve.BindingTrace
|
||||
import org.jetbrains.kotlin.resolve.DescriptorUtils
|
||||
import org.jetbrains.kotlin.resolve.multiplatform.OptionalAnnotationUtil
|
||||
|
||||
object OptionalExpectationChecker {
|
||||
fun check(declaration: KtDeclaration, descriptor: DeclarationDescriptor, trace: BindingTrace) {
|
||||
@@ -34,6 +35,6 @@ object OptionalExpectationChecker {
|
||||
private fun getOptionalExpectationEntry(declaration: KtDeclaration, trace: BindingTrace): KtAnnotationEntry? =
|
||||
declaration.annotationEntries.find { entry ->
|
||||
val annotationDescriptor = trace.get(BindingContext.ANNOTATION, entry)
|
||||
annotationDescriptor?.fqName == ExpectedActualDeclarationChecker.OPTIONAL_EXPECTATION_FQ_NAME
|
||||
annotationDescriptor?.fqName == OptionalAnnotationUtil.OPTIONAL_EXPECTATION_FQ_NAME
|
||||
}
|
||||
}
|
||||
|
||||
@@ -8,14 +8,15 @@ package org.jetbrains.kotlin.resolve.checkers
|
||||
import com.intellij.psi.PsiElement
|
||||
import org.jetbrains.kotlin.descriptors.ClassifierDescriptor
|
||||
import org.jetbrains.kotlin.diagnostics.Errors
|
||||
import org.jetbrains.kotlin.platform.isCommon
|
||||
import org.jetbrains.kotlin.psi.KtFile
|
||||
import org.jetbrains.kotlin.resolve.descriptorUtil.platform
|
||||
import org.jetbrains.kotlin.platform.isCommon
|
||||
import org.jetbrains.kotlin.resolve.multiplatform.OptionalAnnotationUtil
|
||||
import org.jetbrains.kotlin.resolve.multiplatform.isCommonSource
|
||||
|
||||
class OptionalExpectationUsageChecker : ClassifierUsageChecker {
|
||||
override fun check(targetDescriptor: ClassifierDescriptor, element: PsiElement, context: ClassifierUsageCheckerContext) {
|
||||
if (!ExpectedActualDeclarationChecker.isOptionalAnnotationClass(targetDescriptor)) return
|
||||
if (!OptionalAnnotationUtil.isOptionalAnnotationClass(targetDescriptor)) return
|
||||
|
||||
if (!element.isUsageAsAnnotationOrImport()) {
|
||||
context.trace.report(Errors.OPTIONAL_DECLARATION_OUTSIDE_OF_ANNOTATION_ENTRY.on(element))
|
||||
|
||||
@@ -252,10 +252,32 @@ public class LazyClassDescriptor extends ClassDescriptorBase implements ClassDes
|
||||
List<KtTypeParameter> typeParameters = typeParameterList.getParameters();
|
||||
if (typeParameters.isEmpty()) return Collections.emptyList();
|
||||
|
||||
boolean supportClassTypeParameterAnnotations = c.getLanguageVersionSettings().supportsFeature(LanguageFeature.ClassTypeParameterAnnotations);
|
||||
List<TypeParameterDescriptor> parameters = new ArrayList<>(typeParameters.size());
|
||||
|
||||
|
||||
for (int i = 0; i < typeParameters.size(); i++) {
|
||||
parameters.add(new LazyTypeParameterDescriptor(c, this, typeParameters.get(i), i));
|
||||
KtTypeParameter parameter = typeParameters.get(i);
|
||||
Annotations lazyAnnotations;
|
||||
if (supportClassTypeParameterAnnotations) {
|
||||
lazyAnnotations = new LazyAnnotations(
|
||||
new LazyAnnotationsContext(
|
||||
c.getAnnotationResolver(),
|
||||
storageManager,
|
||||
c.getTrace()
|
||||
) {
|
||||
@NotNull
|
||||
@Override
|
||||
public LexicalScope getScope() {
|
||||
return getOuterScope();
|
||||
}
|
||||
},
|
||||
parameter.getAnnotationEntries()
|
||||
);
|
||||
} else {
|
||||
lazyAnnotations = Annotations.Companion.getEMPTY();
|
||||
}
|
||||
|
||||
parameters.add(new LazyTypeParameterDescriptor(c, this, parameter, lazyAnnotations, i));
|
||||
}
|
||||
|
||||
return parameters;
|
||||
|
||||
@@ -18,6 +18,7 @@ package org.jetbrains.kotlin.resolve.lazy.descriptors;
|
||||
|
||||
import kotlin.collections.CollectionsKt;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.kotlin.descriptors.annotations.Annotations;
|
||||
import org.jetbrains.kotlin.descriptors.impl.AbstractLazyTypeParameterDescriptor;
|
||||
import org.jetbrains.kotlin.diagnostics.Errors;
|
||||
import org.jetbrains.kotlin.lexer.KtTokens;
|
||||
@@ -43,11 +44,13 @@ public class LazyTypeParameterDescriptor extends AbstractLazyTypeParameterDescri
|
||||
@NotNull LazyClassContext c,
|
||||
@NotNull LazyClassDescriptor containingDeclaration,
|
||||
@NotNull KtTypeParameter typeParameter,
|
||||
@NotNull Annotations annotations,
|
||||
int index
|
||||
) {
|
||||
super(
|
||||
c.getStorageManager(),
|
||||
containingDeclaration,
|
||||
annotations,
|
||||
typeParameter.getNameAsSafeName(),
|
||||
typeParameter.getVariance(),
|
||||
typeParameter.hasModifier(KtTokens.REIFIED_KEYWORD),
|
||||
|
||||
@@ -16,7 +16,6 @@
|
||||
|
||||
package org.jetbrains.kotlin.resolve.source
|
||||
|
||||
import com.intellij.psi.PsiElement
|
||||
import org.jetbrains.kotlin.descriptors.SourceElement
|
||||
import org.jetbrains.kotlin.psi.KtElement
|
||||
import org.jetbrains.kotlin.psi.KtPureElement
|
||||
@@ -24,5 +23,3 @@ import org.jetbrains.kotlin.psi.KtPureElement
|
||||
class KotlinSourceElement(override val psi: KtElement) : PsiSourceElement
|
||||
|
||||
fun KtPureElement?.toSourceElement(): SourceElement = if (this == null) SourceElement.NO_SOURCE else KotlinSourceElement(psiOrParent)
|
||||
|
||||
fun SourceElement.getPsi(): PsiElement? = (this as? PsiSourceElement)?.psi
|
||||
|
||||
@@ -35,15 +35,14 @@ import org.jetbrains.kotlin.resolve.BindingTrace;
|
||||
import org.jetbrains.kotlin.resolve.DescriptorUtils;
|
||||
import org.jetbrains.kotlin.resolve.calls.checkers.AdditionalTypeChecker;
|
||||
import org.jetbrains.kotlin.resolve.calls.context.ResolutionContext;
|
||||
import org.jetbrains.kotlin.resolve.calls.inference.BuilderInferenceSession;
|
||||
import org.jetbrains.kotlin.resolve.calls.smartcasts.*;
|
||||
import org.jetbrains.kotlin.resolve.constants.*;
|
||||
import org.jetbrains.kotlin.resolve.constants.evaluate.ConstantExpressionEvaluator;
|
||||
import org.jetbrains.kotlin.types.KotlinType;
|
||||
import org.jetbrains.kotlin.types.KotlinTypeKt;
|
||||
import org.jetbrains.kotlin.types.TypeConstructor;
|
||||
import org.jetbrains.kotlin.types.TypeUtils;
|
||||
import org.jetbrains.kotlin.types.*;
|
||||
import org.jetbrains.kotlin.types.checker.KotlinTypeChecker;
|
||||
import org.jetbrains.kotlin.types.expressions.typeInfoFactory.TypeInfoFactoryKt;
|
||||
import org.jetbrains.kotlin.types.typeUtil.TypeUtilsKt;
|
||||
import org.jetbrains.kotlin.util.OperatorNameConventions;
|
||||
|
||||
import java.util.Collection;
|
||||
@@ -287,6 +286,11 @@ public class DataFlowAnalyzer {
|
||||
@NotNull Ref<Boolean> hasError,
|
||||
boolean reportErrorForTypeMismatch
|
||||
) {
|
||||
if (!noExpectedType(c.expectedType) && TypeUtilsKt.contains(expressionType, (type) -> type instanceof StubTypeForBuilderInference)) {
|
||||
if (c.inferenceSession instanceof BuilderInferenceSession) {
|
||||
((BuilderInferenceSession) c.inferenceSession).addExpectedTypeConstraint(expression, expressionType, c.expectedType);
|
||||
}
|
||||
}
|
||||
if (noExpectedType(c.expectedType) || !c.expectedType.getConstructor().isDenotable() ||
|
||||
kotlinTypeChecker.isSubtypeOf(expressionType, c.expectedType)) {
|
||||
return expressionType;
|
||||
|
||||
@@ -114,7 +114,7 @@ class DoubleColonExpressionResolver(
|
||||
} else {
|
||||
val result = resolveDoubleColonLHS(expression, c)
|
||||
|
||||
if (c.inferenceSession is BuilderInferenceSession && result?.type?.contains { it is StubType } == true) {
|
||||
if (c.inferenceSession is BuilderInferenceSession && result?.type?.contains { it is StubTypeForBuilderInference } == true) {
|
||||
c.inferenceSession.addOldCallableReferenceCalls(expression)
|
||||
}
|
||||
|
||||
@@ -548,17 +548,19 @@ class DoubleColonExpressionResolver(
|
||||
val result = getCallableReferenceType(expression, lhs, resolutionResults, c)
|
||||
val doesSomeExtensionReceiverContainsStubType =
|
||||
resolutionResults != null && resolutionResults.resultingCalls.any { resolvedCall ->
|
||||
resolvedCall.extensionReceiver?.type?.contains { it is StubType } == true
|
||||
resolvedCall.extensionReceiver?.type?.contains { it is StubTypeForBuilderInference } == true
|
||||
}
|
||||
|
||||
if (doesSomeExtensionReceiverContainsStubType) {
|
||||
val unrestrictedBuilderInferenceSupported = languageVersionSettings.supportsFeature(LanguageFeature.UnrestrictedBuilderInference)
|
||||
|
||||
if (doesSomeExtensionReceiverContainsStubType && !unrestrictedBuilderInferenceSupported) {
|
||||
c.trace.reportDiagnosticOnce(TYPE_INFERENCE_POSTPONED_VARIABLE_IN_RECEIVER_TYPE.on(expression))
|
||||
return noTypeInfo(c)
|
||||
}
|
||||
|
||||
val dataFlowInfo = (lhs as? DoubleColonLHS.Expression)?.dataFlowInfo ?: c.dataFlowInfo
|
||||
|
||||
if (c.inferenceSession is BuilderInferenceSession && result?.contains { it is StubType } == true) {
|
||||
if (c.inferenceSession is BuilderInferenceSession && result?.contains { it is StubTypeForBuilderInference } == true) {
|
||||
c.inferenceSession.addOldCallableReferenceCalls(expression)
|
||||
}
|
||||
|
||||
|
||||
@@ -13,7 +13,6 @@ class SourceToOutputFilesMap(
|
||||
private val pathConverter: FileToPathConverter
|
||||
) : BasicStringMap<Collection<String>>(storageFile, PathStringDescriptor, StringCollectionExternalizer) {
|
||||
|
||||
@Synchronized
|
||||
operator fun set(sourceFile: File, outputFiles: Collection<File>) {
|
||||
storage[pathConverter.toPath(sourceFile)] = outputFiles.map(pathConverter::toPath)
|
||||
}
|
||||
@@ -24,7 +23,6 @@ class SourceToOutputFilesMap(
|
||||
override fun dumpValue(value: Collection<String>) =
|
||||
value.dumpCollection()
|
||||
|
||||
@Synchronized
|
||||
fun remove(file: File): Collection<File> =
|
||||
get(file).also { storage.remove(pathConverter.toPath(file)) }
|
||||
}
|
||||
@@ -31,7 +31,7 @@ class FileSnapshotMapTest : TestWithWorkingDir() {
|
||||
@After
|
||||
override fun tearDown() {
|
||||
snapshotMap.flush(false)
|
||||
snapshotMap.close()
|
||||
snapshotMap.closeForTest()
|
||||
super.tearDown()
|
||||
}
|
||||
|
||||
|
||||
@@ -29,7 +29,7 @@ class SourceToOutputFilesMapTest : TestWithWorkingDir() {
|
||||
@After
|
||||
override fun tearDown() {
|
||||
stofMap.flush(false)
|
||||
stofMap.close()
|
||||
stofMap.closeForTest()
|
||||
super.tearDown()
|
||||
}
|
||||
|
||||
|
||||
@@ -697,7 +697,3 @@ fun IrExpression?.isPure(
|
||||
|
||||
return false
|
||||
}
|
||||
|
||||
fun IrDeclaration.isFromJava(): Boolean =
|
||||
origin == IrDeclarationOrigin.IR_EXTERNAL_JAVA_DECLARATION_STUB ||
|
||||
parent is IrDeclaration && (parent as IrDeclaration).isFromJava()
|
||||
|
||||
@@ -9,20 +9,27 @@ import org.jetbrains.kotlin.backend.common.BodyLoweringPass
|
||||
import org.jetbrains.kotlin.backend.common.CommonBackendContext
|
||||
import org.jetbrains.kotlin.backend.common.IrElementTransformerVoidWithContext
|
||||
import org.jetbrains.kotlin.backend.common.ir.asInlinable
|
||||
import org.jetbrains.kotlin.backend.common.ir.copyValueParametersFrom
|
||||
import org.jetbrains.kotlin.backend.common.ir.inline
|
||||
import org.jetbrains.kotlin.descriptors.DescriptorVisibilities
|
||||
import org.jetbrains.kotlin.ir.builders.*
|
||||
import org.jetbrains.kotlin.ir.declarations.IrConstructor
|
||||
import org.jetbrains.kotlin.ir.declarations.IrDeclaration
|
||||
import org.jetbrains.kotlin.ir.declarations.IrSymbolOwner
|
||||
import org.jetbrains.kotlin.ir.expressions.IrBody
|
||||
import org.jetbrains.kotlin.ir.expressions.IrConstructorCall
|
||||
import org.jetbrains.kotlin.ir.expressions.IrExpression
|
||||
import org.jetbrains.kotlin.ir.expressions.copyTypeArgumentsFrom
|
||||
import org.jetbrains.kotlin.ir.builders.declarations.buildFun
|
||||
import org.jetbrains.kotlin.ir.declarations.*
|
||||
import org.jetbrains.kotlin.ir.expressions.*
|
||||
import org.jetbrains.kotlin.ir.expressions.impl.IrCompositeImpl
|
||||
import org.jetbrains.kotlin.ir.expressions.impl.IrFunctionReferenceImpl
|
||||
import org.jetbrains.kotlin.ir.symbols.IrFunctionSymbol
|
||||
import org.jetbrains.kotlin.ir.types.IrSimpleType
|
||||
import org.jetbrains.kotlin.ir.types.IrTypeProjection
|
||||
import org.jetbrains.kotlin.ir.types.classifierOrFail
|
||||
import org.jetbrains.kotlin.ir.types.getClass
|
||||
import org.jetbrains.kotlin.ir.util.*
|
||||
import org.jetbrains.kotlin.ir.util.constructedClass
|
||||
import org.jetbrains.kotlin.ir.util.constructors
|
||||
import org.jetbrains.kotlin.ir.util.functions
|
||||
import org.jetbrains.kotlin.ir.util.patchDeclarationParents
|
||||
import org.jetbrains.kotlin.ir.visitors.IrElementTransformerVoid
|
||||
import org.jetbrains.kotlin.ir.visitors.transformChildrenVoid
|
||||
import org.jetbrains.kotlin.name.Name
|
||||
import org.jetbrains.kotlin.util.OperatorNameConventions
|
||||
|
||||
class ArrayConstructorLowering(val context: CommonBackendContext) : BodyLoweringPass {
|
||||
@@ -37,18 +44,20 @@ private class ArrayConstructorTransformer(
|
||||
) : IrElementTransformerVoidWithContext() {
|
||||
|
||||
// Array(size, init) -> Array(size)
|
||||
private fun arrayInlineToSizeConstructor(irConstructor: IrConstructor): IrFunctionSymbol? {
|
||||
val clazz = irConstructor.constructedClass.symbol
|
||||
return when {
|
||||
irConstructor.valueParameters.size != 2 -> null
|
||||
clazz == context.irBuiltIns.arrayClass -> context.ir.symbols.arrayOfNulls // Array<T> has no unary constructor: it can only exist for Array<T?>
|
||||
context.irBuiltIns.primitiveArrays.contains(clazz) -> clazz.constructors.single { it.owner.valueParameters.size == 1 }
|
||||
else -> null
|
||||
companion object {
|
||||
internal fun arrayInlineToSizeConstructor(context: CommonBackendContext, irConstructor: IrConstructor): IrFunctionSymbol? {
|
||||
val clazz = irConstructor.constructedClass.symbol
|
||||
return when {
|
||||
irConstructor.valueParameters.size != 2 -> null
|
||||
clazz == context.irBuiltIns.arrayClass -> context.ir.symbols.arrayOfNulls // Array<T> has no unary constructor: it can only exist for Array<T?>
|
||||
context.irBuiltIns.primitiveArrays.contains(clazz) -> clazz.constructors.single { it.owner.valueParameters.size == 1 }
|
||||
else -> null
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
override fun visitConstructorCall(expression: IrConstructorCall): IrExpression {
|
||||
val sizeConstructor = arrayInlineToSizeConstructor(expression.symbol.owner)
|
||||
val sizeConstructor = arrayInlineToSizeConstructor(context, expression.symbol.owner)
|
||||
?: return super.visitConstructorCall(expression)
|
||||
// inline fun <reified T> Array(size: Int, invokable: (Int) -> T): Array<T> {
|
||||
// val result = arrayOfNulls<T>(size)
|
||||
@@ -90,3 +99,80 @@ private class ArrayConstructorTransformer(
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
object arrayConstuctorWrapper : IrDeclarationOriginImpl("arrayConstuctorWrapper") {}
|
||||
|
||||
class ArrayConstructorReferenceLowering(val context: CommonBackendContext) : BodyLoweringPass {
|
||||
override fun lower(irBody: IrBody, container: IrDeclaration) {
|
||||
irBody.transformChildrenVoid(ArrayConstructorReferenceTransformer(context, container as IrSymbolOwner))
|
||||
}
|
||||
|
||||
private class ArrayConstructorReferenceTransformer(val context: CommonBackendContext, val container: IrSymbolOwner) : IrElementTransformerVoid() {
|
||||
override fun visitFunctionReference(expression: IrFunctionReference): IrExpression {
|
||||
expression.transformChildrenVoid()
|
||||
val target = expression.symbol.owner
|
||||
|
||||
if (target !is IrConstructor) return expression
|
||||
|
||||
if (ArrayConstructorTransformer.arrayInlineToSizeConstructor(context, target) == null) return expression
|
||||
|
||||
return expression.run {
|
||||
IrCompositeImpl(startOffset, endOffset, type, origin).apply {
|
||||
val wrapper = createFunctionReferenceWrapper(expression, target)
|
||||
statements.add(wrapper)
|
||||
statements.add(
|
||||
IrFunctionReferenceImpl(
|
||||
startOffset,
|
||||
endOffset,
|
||||
type,
|
||||
wrapper.symbol,
|
||||
0,
|
||||
valueArgumentsCount,
|
||||
target.symbol,
|
||||
origin
|
||||
)
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun createFunctionReferenceWrapper(expression: IrFunctionReference, target: IrConstructor): IrSimpleFunction {
|
||||
val typeArguments = with(expression.type as IrSimpleType) { arguments }
|
||||
assert(typeArguments.size == 3)
|
||||
val arrayType = (typeArguments[2] as IrTypeProjection).type
|
||||
val arrayElementType = ((arrayType as IrSimpleType).arguments.singleOrNull() as? IrTypeProjection)?.type
|
||||
|
||||
val wrapper = context.irFactory.buildFun {
|
||||
startOffset = expression.startOffset
|
||||
endOffset = expression.endOffset
|
||||
origin = arrayConstuctorWrapper
|
||||
name = Name.special("<array_inline_constructor_wrapper>")
|
||||
visibility = DescriptorVisibilities.LOCAL
|
||||
|
||||
}
|
||||
|
||||
val substitutionMap = target.typeParameters.singleOrNull()?.let { mapOf(it.symbol to arrayElementType!!) } ?: emptyMap()
|
||||
wrapper.copyValueParametersFrom(target, substitutionMap)
|
||||
|
||||
wrapper.returnType = arrayType
|
||||
wrapper.parent = container as IrDeclarationParent
|
||||
wrapper.body = context.irFactory.createBlockBody(expression.startOffset, expression.endOffset).also { body ->
|
||||
with(context.createIrBuilder(wrapper.symbol)) {
|
||||
body.statements.add(irReturn(
|
||||
irCall(target.symbol, arrayType).also { call ->
|
||||
if (call.typeArgumentsCount != 0) {
|
||||
assert(call.typeArgumentsCount == 1)
|
||||
call.putTypeArgument(0, arrayElementType)
|
||||
}
|
||||
call.putValueArgument(0, irGet(wrapper.valueParameters[0]))
|
||||
call.putValueArgument(1, irGet(wrapper.valueParameters[1]))
|
||||
}
|
||||
))
|
||||
}
|
||||
}
|
||||
|
||||
return wrapper
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -20,9 +20,9 @@ import org.jetbrains.kotlin.ir.util.*
|
||||
import org.jetbrains.kotlin.ir.visitors.IrElementTransformerVoid
|
||||
import org.jetbrains.kotlin.ir.visitors.IrElementVisitorVoid
|
||||
import org.jetbrains.kotlin.ir.visitors.acceptChildrenVoid
|
||||
import org.jetbrains.kotlin.resolve.checkers.ExpectedActualDeclarationChecker
|
||||
import org.jetbrains.kotlin.resolve.descriptorUtil.module
|
||||
import org.jetbrains.kotlin.resolve.multiplatform.ExpectedActualResolver
|
||||
import org.jetbrains.kotlin.resolve.multiplatform.OptionalAnnotationUtil
|
||||
|
||||
// `doRemove` means should expect-declaration be removed from IR
|
||||
@OptIn(ObsoleteDescriptorBasedAPI::class)
|
||||
@@ -70,7 +70,7 @@ class ExpectDeclarationRemover(val symbolTable: ReferenceSymbolTable, private va
|
||||
private fun isOptionalAnnotationClass(klass: IrClass): Boolean {
|
||||
return klass.kind == ClassKind.ANNOTATION_CLASS &&
|
||||
klass.isExpect &&
|
||||
klass.annotations.hasAnnotation(ExpectedActualDeclarationChecker.OPTIONAL_EXPECTATION_FQ_NAME)
|
||||
klass.annotations.hasAnnotation(OptionalAnnotationUtil.OPTIONAL_EXPECTATION_FQ_NAME)
|
||||
}
|
||||
|
||||
private fun tryCopyDefaultArguments(declaration: IrValueParameter) {
|
||||
|
||||
@@ -23,8 +23,6 @@ import org.jetbrains.kotlin.ir.visitors.IrElementTransformerVoid
|
||||
import org.jetbrains.kotlin.ir.visitors.transformChildrenVoid
|
||||
|
||||
interface InnerClassesSupport {
|
||||
object FIELD_FOR_OUTER_THIS : IrDeclarationOriginImpl("FIELD_FOR_OUTER_THIS", isSynthetic = true)
|
||||
|
||||
fun getOuterThisField(innerClass: IrClass): IrField
|
||||
fun getInnerClassConstructorWithOuterThisParameter(innerClassConstructor: IrConstructor): IrConstructor
|
||||
fun getInnerClassOriginalPrimaryConstructorOrNull(innerClass: IrClass): IrConstructor?
|
||||
|
||||
@@ -785,9 +785,6 @@ class LocalDeclarationsLowering(
|
||||
}
|
||||
}
|
||||
|
||||
private fun Name.stripSpecialMarkers(): String =
|
||||
if (isSpecial) asString().substring(1, asString().length - 1) else asString()
|
||||
|
||||
private fun suggestNameForCapturedValue(declaration: IrValueDeclaration, usedNames: MutableSet<String>, isExplicitLocalFunction: Boolean = false): Name {
|
||||
if (declaration is IrValueParameter) {
|
||||
if (declaration.name.asString() == "<this>" && declaration.isDispatchReceiver()) {
|
||||
@@ -808,7 +805,7 @@ class LocalDeclarationsLowering(
|
||||
}
|
||||
|
||||
val base = if (declaration.name.isSpecial) {
|
||||
declaration.name.stripSpecialMarkers()
|
||||
declaration.name.asStringStripSpecialMarkers()
|
||||
} else {
|
||||
declaration.name.asString()
|
||||
}
|
||||
@@ -859,9 +856,9 @@ class LocalDeclarationsLowering(
|
||||
val correspondingProperty = parentFun.safeAs<IrSimpleFunction>()?.correspondingPropertySymbol?.owner
|
||||
return when {
|
||||
correspondingProperty != null ->
|
||||
correspondingProperty.name.stripSpecialMarkers()
|
||||
correspondingProperty.name.asStringStripSpecialMarkers()
|
||||
else ->
|
||||
parentFun.name.stripSpecialMarkers()
|
||||
parentFun.name.asStringStripSpecialMarkers()
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -8,14 +8,14 @@ package org.jetbrains.kotlin.backend.common.lower
|
||||
import org.jetbrains.kotlin.backend.common.BodyLoweringPass
|
||||
import org.jetbrains.kotlin.backend.common.FileLoweringPass
|
||||
import org.jetbrains.kotlin.ir.IrElement
|
||||
import org.jetbrains.kotlin.ir.IrStatement
|
||||
import org.jetbrains.kotlin.ir.declarations.IrDeclaration
|
||||
import org.jetbrains.kotlin.ir.declarations.IrFile
|
||||
import org.jetbrains.kotlin.ir.expressions.IrBody
|
||||
import org.jetbrains.kotlin.ir.expressions.IrCall
|
||||
import org.jetbrains.kotlin.ir.expressions.IrExpression
|
||||
import org.jetbrains.kotlin.ir.expressions.IrFunctionExpression
|
||||
import org.jetbrains.kotlin.ir.declarations.IrVariable
|
||||
import org.jetbrains.kotlin.ir.expressions.*
|
||||
import org.jetbrains.kotlin.ir.expressions.impl.IrBlockImpl
|
||||
import org.jetbrains.kotlin.ir.expressions.impl.IrFunctionReferenceImpl
|
||||
import org.jetbrains.kotlin.ir.util.remapTypes
|
||||
import org.jetbrains.kotlin.ir.visitors.IrElementTransformer
|
||||
import org.jetbrains.kotlin.ir.visitors.IrElementTransformerVoid
|
||||
import org.jetbrains.kotlin.ir.visitors.transformChildrenVoid
|
||||
@@ -32,9 +32,23 @@ class ProvisionalFunctionExpressionLowering :
|
||||
irBody.transformChildren(this, ProvisionalFunctionExpressionLoweringContext())
|
||||
}
|
||||
|
||||
override fun visitCall(expression: IrCall, data: ProvisionalFunctionExpressionLoweringContext): IrElement {
|
||||
return super.visitCall(expression, ProvisionalFunctionExpressionLoweringContext(data, expression.startOffset, expression.endOffset))
|
||||
}
|
||||
override fun visitCall(expression: IrCall, data: ProvisionalFunctionExpressionLoweringContext) = super.visitCall(
|
||||
expression,
|
||||
ProvisionalFunctionExpressionLoweringContext(
|
||||
data,
|
||||
expression.startOffset,
|
||||
expression.endOffset
|
||||
)
|
||||
)
|
||||
|
||||
override fun visitVariable(declaration: IrVariable, data: ProvisionalFunctionExpressionLoweringContext) = super.visitVariable(
|
||||
declaration,
|
||||
ProvisionalFunctionExpressionLoweringContext(
|
||||
data,
|
||||
declaration.startOffset,
|
||||
declaration.endOffset
|
||||
)
|
||||
)
|
||||
|
||||
override fun visitFunctionExpression(expression: IrFunctionExpression, data: ProvisionalFunctionExpressionLoweringContext): IrElement {
|
||||
expression.transformChildren(this, ProvisionalFunctionExpressionLoweringContext(data))
|
||||
|
||||
@@ -8,7 +8,6 @@ dependencies {
|
||||
compile(project(":compiler:frontend"))
|
||||
compile(project(":compiler:backend-common"))
|
||||
compile(project(":compiler:ir.tree"))
|
||||
compile(project(":compiler:ir.psi2ir"))
|
||||
compile(project(":compiler:ir.backend.common"))
|
||||
compile(project(":compiler:ir.serialization.common"))
|
||||
compile(project(":compiler:ir.serialization.js"))
|
||||
|
||||
@@ -21,8 +21,8 @@ import org.jetbrains.kotlin.ir.backend.js.lower.calls.CallsLowering
|
||||
import org.jetbrains.kotlin.ir.backend.js.lower.cleanup.CleanupLowering
|
||||
import org.jetbrains.kotlin.ir.backend.js.lower.coroutines.JsSuspendFunctionsLowering
|
||||
import org.jetbrains.kotlin.ir.backend.js.lower.inline.CopyInlineFunctionBodyLowering
|
||||
import org.jetbrains.kotlin.ir.backend.js.lower.inline.jsRecordExtractedLocalClasses
|
||||
import org.jetbrains.kotlin.ir.backend.js.lower.inline.RemoveInlineDeclarationsWithReifiedTypeParametersLowering
|
||||
import org.jetbrains.kotlin.ir.backend.js.lower.inline.jsRecordExtractedLocalClasses
|
||||
import org.jetbrains.kotlin.ir.declarations.IrFile
|
||||
import org.jetbrains.kotlin.ir.declarations.IrModuleFragment
|
||||
|
||||
@@ -192,10 +192,17 @@ private val jsCodeOutliningPhase = makeBodyLoweringPhase(
|
||||
description = "Outline js() calls where JS code references Kotlin locals"
|
||||
)
|
||||
|
||||
private val arrayConstructorReferencePhase = makeBodyLoweringPhase(
|
||||
::ArrayConstructorReferenceLowering,
|
||||
name = "ArrayConstructorReference",
|
||||
description = "Transform `::Array` into a lambda"
|
||||
)
|
||||
|
||||
private val arrayConstructorPhase = makeBodyLoweringPhase(
|
||||
::ArrayConstructorLowering,
|
||||
name = "ArrayConstructor",
|
||||
description = "Transform `Array(size) { index -> value }` into a loop"
|
||||
description = "Transform `Array(size) { index -> value }` into a loop",
|
||||
prerequisite = setOf(arrayConstructorReferencePhase)
|
||||
)
|
||||
|
||||
private val sharedVariablesLoweringPhase = makeBodyLoweringPhase(
|
||||
@@ -721,6 +728,7 @@ private val loweringList = listOf<Lowering>(
|
||||
expectDeclarationsRemovingPhase,
|
||||
stripTypeAliasDeclarationsPhase,
|
||||
jsCodeOutliningPhase,
|
||||
arrayConstructorReferencePhase,
|
||||
arrayConstructorPhase,
|
||||
lateinitNullableFieldsPhase,
|
||||
lateinitDeclarationLoweringPhase,
|
||||
|
||||
@@ -91,20 +91,24 @@ class CallableReferenceLowering(private val context: CommonBackendContext) : Bod
|
||||
}
|
||||
|
||||
private fun buildFunctionReference(expression: IrFunctionReference): Pair<IrClass, IrConstructor> {
|
||||
return CallableReferenceBuilder(expression.symbol.owner, expression, false).build()
|
||||
val target = expression.symbol.owner
|
||||
val reflectionTarget = expression.reflectionTarget?.owner ?: target
|
||||
return CallableReferenceBuilder(target, expression, reflectionTarget).build()
|
||||
}
|
||||
|
||||
private fun buildLambdaReference(function: IrSimpleFunction, expression: IrFunctionExpression): Pair<IrClass, IrConstructor> {
|
||||
return CallableReferenceBuilder(function, expression, true).build()
|
||||
return CallableReferenceBuilder(function, expression, null).build()
|
||||
}
|
||||
}
|
||||
|
||||
private inner class CallableReferenceBuilder(
|
||||
private val function: IrFunction,
|
||||
private val reference: IrExpression,
|
||||
private val isLambda: Boolean
|
||||
private val reflectionTarget: IrFunction?
|
||||
) {
|
||||
|
||||
private val isLambda: Boolean get() = reflectionTarget == null
|
||||
|
||||
private val isSuspendLambda = isLambda && function.isSuspend
|
||||
|
||||
private val superClass = if (isSuspendLambda) context.ir.symbols.coroutineImpl.owner.defaultType else context.irBuiltIns.anyType
|
||||
@@ -362,11 +366,12 @@ class CallableReferenceLowering(private val context: CommonBackendContext) : Bod
|
||||
type = clazz.defaultType
|
||||
}
|
||||
|
||||
// TODO: What name should be in case of constructor? <init> or class name?
|
||||
getter.body = context.irFactory.createBlockBody(
|
||||
UNDEFINED_OFFSET, UNDEFINED_OFFSET, listOf(
|
||||
IrReturnImpl(
|
||||
UNDEFINED_OFFSET, UNDEFINED_OFFSET, nothingType, getter.symbol, IrConstImpl.string(
|
||||
UNDEFINED_OFFSET, UNDEFINED_OFFSET, stringType, function.name.asString()
|
||||
UNDEFINED_OFFSET, UNDEFINED_OFFSET, stringType, reflectionTarget!!.name.asString()
|
||||
)
|
||||
)
|
||||
)
|
||||
|
||||
@@ -16,10 +16,7 @@ import org.jetbrains.kotlin.ir.backend.js.utils.Namer
|
||||
import org.jetbrains.kotlin.ir.builders.declarations.buildConstructor
|
||||
import org.jetbrains.kotlin.ir.builders.declarations.buildField
|
||||
import org.jetbrains.kotlin.ir.builders.declarations.buildValueParameter
|
||||
import org.jetbrains.kotlin.ir.declarations.IrClass
|
||||
import org.jetbrains.kotlin.ir.declarations.IrConstructor
|
||||
import org.jetbrains.kotlin.ir.declarations.IrFactory
|
||||
import org.jetbrains.kotlin.ir.declarations.IrField
|
||||
import org.jetbrains.kotlin.ir.declarations.*
|
||||
import org.jetbrains.kotlin.ir.util.defaultType
|
||||
import org.jetbrains.kotlin.ir.util.dump
|
||||
import org.jetbrains.kotlin.name.Name
|
||||
@@ -37,7 +34,7 @@ class JsInnerClassesSupport(mapping: JsMapping, private val irFactory: IrFactory
|
||||
?: throw AssertionError("No containing class for inner class ${innerClass.dump()}")
|
||||
|
||||
irFactory.buildField {
|
||||
origin = InnerClassesSupport.FIELD_FOR_OUTER_THIS
|
||||
origin = IrDeclarationOrigin.FIELD_FOR_OUTER_THIS
|
||||
name = Name.identifier("\$this")
|
||||
type = outerClass.defaultType
|
||||
visibility = DescriptorVisibilities.PROTECTED
|
||||
|
||||
@@ -40,7 +40,7 @@ import org.jetbrains.kotlin.ir.util.*
|
||||
import org.jetbrains.kotlin.load.java.JvmAnnotationNames
|
||||
import org.jetbrains.kotlin.name.FqName
|
||||
import org.jetbrains.kotlin.name.Name
|
||||
import org.jetbrains.kotlin.resolve.checkers.ExpectedActualDeclarationChecker
|
||||
import org.jetbrains.kotlin.resolve.multiplatform.OptionalAnnotationUtil
|
||||
import org.jetbrains.kotlin.types.TypeSystemCommonBackendContext
|
||||
import org.jetbrains.kotlin.types.model.KotlinTypeMarker
|
||||
import org.jetbrains.org.objectweb.asm.*
|
||||
@@ -480,4 +480,4 @@ private fun loadAnnotationTargets(targetEntry: IrConstructorCall): Set<KotlinTar
|
||||
private val IrClass.isOptionalAnnotationClass: Boolean
|
||||
get() = kind == ClassKind.ANNOTATION_CLASS &&
|
||||
isExpect &&
|
||||
hasAnnotation(ExpectedActualDeclarationChecker.OPTIONAL_EXPECTATION_FQ_NAME)
|
||||
hasAnnotation(OptionalAnnotationUtil.OPTIONAL_EXPECTATION_FQ_NAME)
|
||||
|
||||
@@ -5,7 +5,6 @@
|
||||
|
||||
package org.jetbrains.kotlin.backend.jvm.codegen
|
||||
|
||||
import org.jetbrains.kotlin.backend.common.ir.isFromJava
|
||||
import org.jetbrains.kotlin.backend.common.lower.BOUND_RECEIVER_PARAMETER
|
||||
import org.jetbrains.kotlin.backend.common.lower.SYNTHESIZED_INIT_BLOCK
|
||||
import org.jetbrains.kotlin.backend.jvm.JvmLoweredDeclarationOrigin
|
||||
|
||||
@@ -6,7 +6,6 @@
|
||||
package org.jetbrains.kotlin.backend.jvm.codegen
|
||||
|
||||
import org.jetbrains.kotlin.backend.common.ir.allOverridden
|
||||
import org.jetbrains.kotlin.backend.common.ir.isFromJava
|
||||
import org.jetbrains.kotlin.backend.common.ir.isMethodOfAny
|
||||
import org.jetbrains.kotlin.backend.common.ir.isTopLevel
|
||||
import org.jetbrains.kotlin.backend.common.lower.parentsWithSelf
|
||||
|
||||
@@ -36,10 +36,10 @@ import org.jetbrains.kotlin.load.java.JavaDescriptorVisibilities
|
||||
import org.jetbrains.kotlin.load.kotlin.JvmPackagePartSource
|
||||
import org.jetbrains.kotlin.name.ClassId
|
||||
import org.jetbrains.kotlin.name.FqName
|
||||
import org.jetbrains.kotlin.resolve.checkers.ExpectedActualDeclarationChecker
|
||||
import org.jetbrains.kotlin.resolve.inline.INLINE_ONLY_ANNOTATION_FQ_NAME
|
||||
import org.jetbrains.kotlin.resolve.jvm.AsmTypes
|
||||
import org.jetbrains.kotlin.resolve.jvm.jvmSignature.JvmClassSignature
|
||||
import org.jetbrains.kotlin.resolve.multiplatform.OptionalAnnotationUtil
|
||||
import org.jetbrains.kotlin.resolve.source.PsiSourceElement
|
||||
import org.jetbrains.kotlin.utils.addIfNotNull
|
||||
import org.jetbrains.kotlin.utils.addToStdlib.safeAs
|
||||
@@ -334,7 +334,7 @@ fun IrClass.getVisibilityAccessFlagForClass(): Int {
|
||||
// TODO: Descriptor-based code also checks for `descriptor.isExpect`; we don't represent expect/actual distinction in IR thus far.
|
||||
fun IrClass.isOptionalAnnotationClass(): Boolean =
|
||||
isAnnotationClass &&
|
||||
hasAnnotation(ExpectedActualDeclarationChecker.OPTIONAL_EXPECTATION_FQ_NAME)
|
||||
hasAnnotation(OptionalAnnotationUtil.OPTIONAL_EXPECTATION_FQ_NAME)
|
||||
|
||||
val IrDeclaration.isAnnotatedWithDeprecated: Boolean
|
||||
get() = annotations.hasAnnotation(FqNames.deprecated)
|
||||
|
||||
@@ -7,7 +7,6 @@ package org.jetbrains.kotlin.backend.jvm.lower
|
||||
|
||||
import org.jetbrains.kotlin.backend.common.*
|
||||
import org.jetbrains.kotlin.backend.common.ir.*
|
||||
import org.jetbrains.kotlin.backend.common.lower.InnerClassesSupport
|
||||
import org.jetbrains.kotlin.backend.common.lower.LocalDeclarationsLowering
|
||||
import org.jetbrains.kotlin.backend.common.lower.createIrBuilder
|
||||
import org.jetbrains.kotlin.backend.common.phaser.makeIrFilePhase
|
||||
@@ -113,7 +112,7 @@ private class AddContinuationLowering(context: JvmBackendContext) : SuspendLower
|
||||
addField {
|
||||
name = Name.identifier("this$0")
|
||||
type = it.type
|
||||
origin = InnerClassesSupport.FIELD_FOR_OUTER_THIS
|
||||
origin = IrDeclarationOrigin.FIELD_FOR_OUTER_THIS
|
||||
visibility = JavaDescriptorVisibilities.PACKAGE_VISIBILITY
|
||||
isFinal = true
|
||||
}
|
||||
|
||||
@@ -6,7 +6,6 @@
|
||||
package org.jetbrains.kotlin.backend.jvm.lower
|
||||
|
||||
import org.jetbrains.kotlin.backend.common.ClassLoweringPass
|
||||
import org.jetbrains.kotlin.backend.common.ir.isFromJava
|
||||
import org.jetbrains.kotlin.backend.common.lower.createIrBuilder
|
||||
import org.jetbrains.kotlin.backend.common.phaser.makeIrFilePhase
|
||||
import org.jetbrains.kotlin.backend.jvm.JvmBackendContext
|
||||
|
||||
@@ -383,6 +383,7 @@ internal class FunctionReferenceLowering(private val context: JvmBackendContext)
|
||||
// The type of the reference is KFunction<in A1, ..., in An, out R>
|
||||
private val parameterTypes = (irFunctionReference.type as IrSimpleType).arguments.map { (it as IrTypeProjection).type }
|
||||
private val argumentTypes = parameterTypes.dropLast(1)
|
||||
private val referenceReturnType = parameterTypes.last()
|
||||
|
||||
private val typeArgumentsMap = irFunctionReference.typeSubstitutionMap
|
||||
|
||||
@@ -671,7 +672,7 @@ internal class FunctionReferenceLowering(private val context: JvmBackendContext)
|
||||
functionReferenceClass.addFunction {
|
||||
setSourceRange(if (isLambda) callee else irFunctionReference)
|
||||
name = superMethod.name
|
||||
returnType = callee.returnType
|
||||
returnType = referenceReturnType
|
||||
isSuspend = callee.isSuspend
|
||||
}.apply {
|
||||
overriddenSymbols += superMethod.symbol
|
||||
@@ -703,7 +704,7 @@ internal class FunctionReferenceLowering(private val context: JvmBackendContext)
|
||||
|
||||
body = context.createJvmIrBuilder(symbol, startOffset, endOffset).run {
|
||||
var unboundIndex = 0
|
||||
val call = irCall(callee).apply {
|
||||
val call = irCall(callee.symbol, referenceReturnType).apply {
|
||||
for (typeParameter in irFunctionReference.symbol.owner.allTypeParameters) {
|
||||
putTypeArgument(typeParameter.index, typeArgumentsMap[typeParameter.symbol])
|
||||
}
|
||||
|
||||
@@ -14,10 +14,7 @@ import org.jetbrains.kotlin.codegen.AsmUtil
|
||||
import org.jetbrains.kotlin.ir.builders.declarations.buildConstructor
|
||||
import org.jetbrains.kotlin.ir.builders.declarations.buildField
|
||||
import org.jetbrains.kotlin.ir.builders.declarations.buildValueParameter
|
||||
import org.jetbrains.kotlin.ir.declarations.IrClass
|
||||
import org.jetbrains.kotlin.ir.declarations.IrConstructor
|
||||
import org.jetbrains.kotlin.ir.declarations.IrFactory
|
||||
import org.jetbrains.kotlin.ir.declarations.IrField
|
||||
import org.jetbrains.kotlin.ir.declarations.*
|
||||
import org.jetbrains.kotlin.ir.util.defaultType
|
||||
import org.jetbrains.kotlin.ir.util.dump
|
||||
import org.jetbrains.kotlin.ir.util.parentAsClass
|
||||
@@ -36,7 +33,7 @@ class JvmInnerClassesSupport(private val irFactory: IrFactory) : InnerClassesSup
|
||||
irFactory.buildField {
|
||||
name = Name.identifier("this$0")
|
||||
type = innerClass.parentAsClass.defaultType
|
||||
origin = InnerClassesSupport.FIELD_FOR_OUTER_THIS
|
||||
origin = IrDeclarationOrigin.FIELD_FOR_OUTER_THIS
|
||||
visibility = JavaDescriptorVisibilities.PACKAGE_VISIBILITY
|
||||
isFinal = true
|
||||
}.apply {
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user