Compare commits

...

44 Commits

Author SHA1 Message Date
Ilya Kirillov
69fcfb314d HL API: render local fqNames in reference resolve tests 2021-07-22 15:47:42 +02:00
Ilya Kirillov
8b13931e72 Fix project leaking in tests
The project was leaking via MockApplication -> LowMemoryWatcherManager -> List<Project>
It happened due to unregistered disposable provided to the MockApplication
2021-07-22 14:48:41 +02:00
Ilya Kirillov
6536ba05af HL API: restore SymbolByReferenceTest
Now it is possible as references are working in HL API tests now
2021-07-22 14:48:40 +02:00
Ilya Kirillov
3c2f30f6f7 HL API: generate reference resolve tests
The testdata is taken from corresponding IDE reference resolve tests
2021-07-22 14:48:40 +02:00
Ilya Kirillov
1823745f0f LL API: fix KtPackageProvider package existent checks for tests
Before it was not able to check nested packages for existence

Also, implement unimplemented getKotlinSubPackageFqNames
2021-07-22 14:48:40 +02:00
Ilya Kirillov
0bab74cac9 HL API: fix KtUserType kt -> fir mapping for non-IDEA usages
createType(KtTypeElement) requires some access to IJ services which are unavailable to IJ core
2021-07-22 14:48:40 +02:00
Ilya Kirillov
60b1fe6072 HL API: implement tests for reference resolve 2021-07-22 14:48:40 +02:00
Ilya Kirillov
0fcb4eb4dc FIR IDE: fix containing KtFirSymbolContainingDeclarationProvider for implicit constructors 2021-07-22 14:48:40 +02:00
Ilya Kirillov
45ba5d959a HL API: fix renderer for package symbols 2021-07-22 14:48:40 +02:00
Mikhael Bogdanov
60458214a5 Update ReadMe.md 2021-07-22 12:41:34 +00:00
Elena Lepilkina
e29a67b3a3 [K/N][perf] Added autoreleasepool in swiftinterop benchmarks 2021-07-22 11:37:55 +00:00
Sergey Bogolepov
f8528c5cca [K/N] Dockerfile for building LLVM
Provide a stable environment for building LLVM for Linux
by using Docker. Note that the base image is Ubuntu 16.04,
so after LLVM update building Kotlin/Native on Linux will
require glibc 2.23 or higher.
2021-07-22 10:44:03 +00:00
Leonid Startsev
83c1a75c1e Revert "Revert "Instantiation of annotations for JVM IR with the corresponding feature flag""
Fix incorrectly rebased ce0a3a57df

This reverts commit 3d0126d5
2021-07-21 18:24:07 +03:00
Philipp Smorygo
54b9ad6bf5 Slightly improve Kotlin library podspec
Add additional parameters to Podspec for clarity.
Add ability to skip building by using an environment variable
2021-07-21 18:07:46 +03:00
Ilya Chernikov
db61665ab8 [minor] IR: clean unnecessary ObsoleteDescriptorBasedAPI opt-ins 2021-07-21 18:05:42 +03:00
Dmitriy Novozhilov
a710a8d10f [FE 1.0] Report warning on non-exhaustive when statements only after 1.6
^KT-47709
2021-07-21 17:53:05 +03:00
Igor Laevsky
865ad3698b WASM: Fix flaky test 2021-07-21 16:53:45 +03:00
Mikhael Bogdanov
d8f839a7e4 Properly process separate process inputStream/outputStream 2021-07-21 13:19:31 +00:00
Leonid Startsev
3d0126d5dd Revert "Instantiation of annotations for JVM IR with the corresponding feature flag"
because of incorrect rebase

This reverts commit ce0a3a57
2021-07-21 15:23:24 +03:00
max-kammerer
5b21444805 Update worker11.kt 2021-07-21 13:36:02 +02:00
Leonid Startsev
ce0a3a57df Instantiation of annotations for JVM IR with the corresponding feature flag
Seperate checker for platforms that do not support this language feature yet

Synthetic implementations of annotations are generated on-demand with proper 
equals, hashCode, and annotationType methods

#KT-47699 Fixed
2021-07-21 10:23:51 +00:00
Leonid Startsev
4bc521249b kotlinx.serialization: Support InheritableSerialInfo 2021-07-21 10:06:12 +00:00
Alexander Dudinsky
8eea749231 Accept android licenses in setUp PureAndroidAndJavaConsumeMppLibIT 2021-07-21 12:33:07 +03:00
Nikolay Krasko
a1a1bda5f3 Drop unused runIdeTask and excludeInAndroidStudio from localDependencies 2021-07-21 11:23:56 +02:00
Nikolay Krasko
6a0b71d3e4 Drop old IDEA run configurations 2021-07-21 11:23:56 +02:00
Nikita Bobko
d1e46e8ce7 Delete Kotlin IntelliJ IDEA plugin modules from settings.gradle 2021-07-21 11:23:53 +02:00
Nikita Bobko
39fa2b0baf Delete Kotlin IntelliJ IDEA plugin sources
Kotlin plugin sources were migrated to intellij-community:
https://github.com/JetBrains/intellij-community/tree/master/plugins/kotlin

Preserve `jps-plugin/testData/incremental`
because it's used in `compiler/incremental-compilation-impl/test`

Preserve `idea/testData/multiModuleHighlighting/multiplatform`
because it's used in `MppHighlightingTestDataWithGradleIT`
2021-07-21 11:23:43 +02:00
Elena Lepilkina
b8d74698f1 [K/N][Docs] Update HACKING.md after repositories merging and adding information about debugging and using CLion 2021-07-21 08:39:10 +00:00
Mads Ager
6436a1686d [JVM_IR] Recursively perform constant lowering.
Otherwise constants in child expressions are not transformed.

^KT-47716 Fixed.
2021-07-21 02:11:41 +02:00
Mads Ager
2877f1cabe [JVM_IR] Fix check for inline class property backing in lowering.
The inline class lowering would attempt to lower a companion object
property backing field.

^KT-47762 Fixed.
2021-07-21 01:56:46 +02:00
Dmitry Petrov
46d2e52543 JVM Minor: move uninitialized value check to stack recovery 2021-07-20 19:51:04 +03:00
Dmitry Petrov
e72d24960d JVM we don't merge frames in stack normalization 2021-07-20 19:51:03 +03:00
Dmitry Petrov
91afa3335c JVM represent uninitialized values explicitly in stack normalization 2021-07-20 19:51:02 +03:00
Dmitry Petrov
bb202318ee Minor: regenerate tests 2021-07-20 19:51:01 +03:00
Dmitry Petrov
35b4a9d4cc JVM treat all variable loads as "initialized" in stack normalization 2021-07-20 19:51:00 +03:00
Dmitry Petrov
c8b705fd2d JVM update license for HackedFixStackMethodAnalyzerBase.kt 2021-07-20 19:50:59 +03:00
Dmitry Petrov
8763235053 JVM specially hacked method analyzer for FixStack 2021-07-20 19:50:58 +03:00
Dmitry Petrov
3ecd612ce7 JVM FixStackValue & FixStackInterpreter 2021-07-20 19:50:57 +03:00
Ilya Chernikov
8eb7e719d3 [minor] fix compiler warnings in scripting modules 2021-07-20 19:42:34 +03:00
Roman Golyshev
59304ba70c FIR IDE: use correct out of block modification tracker
Follow-up to eead868cd2
2021-07-20 19:15:38 +03:00
Roman Golyshev
4e67afcaba FIR IDE: Use write lock in KtFirOverrideInfoProvider implementation
`withFir` takes read lock, but checking visibility or implementation
status actually requires resolving declaration to `STATUS` phase. But
resolve cannot be done in `withFir` function, since resolve requires
write lock, and you cannot take both read and write lock

Now we use `withFirWithPossibleResolveInside`, which takes write lock
and allows to perform resolve in it

This should fix failing `FirOverrideImplementTest` tests
in Kotlin IDE plugin
2021-07-20 19:02:26 +03:00
Roman Golyshev
f3bdadb7d9 FIR IDE: Use correct class symbol in getImplementationStatus
The previous check `if (parentClassSymbol !is FirClassSymbol<*>)`
always succeeded, because `parentClassSymbol` was a declaration,
not a symbol
2021-07-20 19:02:24 +03:00
Abduqodiri Qurbonzoda
b65c477e68 Regex.splitToSequence, CharSequence.splitToSequence(Regex) #KT-23351 2021-07-20 14:09:24 +00:00
Abduqodiri Qurbonzoda
1fee6b191f Fix typo in Sequence.constrainOnce() doc 2021-07-20 14:09:24 +00:00
49729 changed files with 5658 additions and 1160419 deletions

View File

@@ -1,20 +0,0 @@
<component name="ProjectRunConfigurationManager">
<configuration default="false" name="IDEA" type="GradleRunConfiguration" factoryName="Gradle" singleton="true" folderName="IDEA">
<ExternalSystemSettings>
<option name="executionName" />
<option name="externalProjectPath" value="$PROJECT_DIR$" />
<option name="externalSystemIdString" value="GRADLE" />
<option name="scriptParameters" value="" />
<option name="taskDescriptions">
<list />
</option>
<option name="taskNames">
<list>
<option value="runIde" />
</list>
</option>
<option name="vmOptions" value="" />
</ExternalSystemSettings>
<method />
</configuration>
</component>

View File

@@ -1,20 +0,0 @@
<component name="ProjectRunConfigurationManager">
<configuration default="false" name="IDEA Ultimate" type="GradleRunConfiguration" factoryName="Gradle" folderName="IDEA">
<ExternalSystemSettings>
<option name="executionName" />
<option name="externalProjectPath" value="$PROJECT_DIR$" />
<option name="externalSystemIdString" value="GRADLE" />
<option name="scriptParameters" value="-P intellijUltimateEnabled" />
<option name="taskDescriptions">
<list />
</option>
<option name="taskNames">
<list>
<option value="runUltimate" />
</list>
</option>
<option name="vmOptions" value="" />
</ExternalSystemSettings>
<method />
</configuration>
</component>

View File

@@ -1,20 +0,0 @@
<component name="ProjectRunConfigurationManager">
<configuration default="false" name="IDEA Ultimate (No ProcessCanceledException) " type="GradleRunConfiguration" factoryName="Gradle" folderName="IDEA">
<ExternalSystemSettings>
<option name="executionName" />
<option name="externalProjectPath" value="$PROJECT_DIR$" />
<option name="externalSystemIdString" value="GRADLE" />
<option name="scriptParameters" value="-PnoPCE" />
<option name="taskDescriptions">
<list />
</option>
<option name="taskNames">
<list>
<option value="runUltimate" />
</list>
</option>
<option name="vmOptions" value="" />
</ExternalSystemSettings>
<method />
</configuration>
</component>

View File

@@ -1,20 +0,0 @@
<component name="ProjectRunConfigurationManager">
<configuration default="false" name="IDEA (No ProcessCanceledException)" type="GradleRunConfiguration" factoryName="Gradle" folderName="IDEA">
<ExternalSystemSettings>
<option name="executionName" />
<option name="externalProjectPath" value="$PROJECT_DIR$" />
<option name="externalSystemIdString" value="GRADLE" />
<option name="scriptParameters" value="-PnoPCE" />
<option name="taskDescriptions">
<list />
</option>
<option name="taskNames">
<list>
<option value="runIde" />
</list>
</option>
<option name="vmOptions" value="" />
</ExternalSystemSettings>
<method />
</configuration>
</component>

View File

@@ -1,19 +0,0 @@
<component name="ProjectRunConfigurationManager">
<configuration default="false" name="IDEA (Not Internal)" type="GradleRunConfiguration" factoryName="Gradle" folderName="IDEA">
<ExternalSystemSettings>
<option name="executionName" />
<option name="externalProjectPath" value="$PROJECT_DIR$" />
<option name="externalSystemIdString" value="GRADLE" />
<option name="scriptParameters" value="-Pidea.is.internal=false" />
<option name="taskDescriptions">
<list />
</option>
<option name="taskNames">
<list>
<option value="runIde" />
</list>
</option>
<option name="vmOptions" value="" />
</ExternalSystemSettings>
</configuration>
</component>

View File

@@ -56,7 +56,7 @@ Alternatively, it is still possible to only provide required JDKs via environmen
from environmental variables - disable Gradle toolchain auto-detection by passing `-Porg.gradle.java.installations.auto-detect=false` option
(or put it into `$GRADLE_USER_HOME/gradle.properties`).
For local development, if you're not working on bytecode generation or the standard library, it's OK to avoid installing JDK 1.6 and JDK 1.7.
For local development, if you're not working on the standard library, it's OK to avoid installing JDK 1.6 and JDK 1.7.
Add `kotlin.build.isObsoleteJdkOverrideEnabled=true` to the `local.properties` file, so build will only use JDK 1.8+. Note, that in this
case, build will have Gradle remote build cache misses for some tasks.

View File

@@ -734,14 +734,6 @@ tasks {
dependsOn(":kotlin-scripting-jsr223-test:embeddableTest")
dependsOn(":kotlin-main-kts-test:test")
dependsOn(":kotlin-main-kts-test:testWithIr")
if (kotlinBuildProperties.getOrNull("attachedIntellijVersion") == null &&
!kotlinBuildProperties.getBoolean("disableKotlinPluginModules", false)
) {
dependsOn(":kotlin-scripting-ide-services-test:test")
dependsOn(":kotlin-scripting-ide-services-test:embeddableTest")
}
dependsOn(":kotlin-scripting-js-test:test")
}

View File

@@ -17,16 +17,11 @@
// usages in build scripts are not tracked properly
@file:Suppress("unused")
import org.gradle.api.GradleException
import org.gradle.api.Project
import org.gradle.api.artifacts.ModuleDependency
import org.gradle.api.artifacts.dsl.RepositoryHandler
import org.gradle.api.artifacts.repositories.IvyArtifactRepository
import org.gradle.api.tasks.JavaExec
import org.gradle.api.tasks.TaskProvider
import org.gradle.kotlin.dsl.DependencyHandlerScope
import org.gradle.kotlin.dsl.extra
import org.gradle.kotlin.dsl.register
import java.io.File
private fun Project.kotlinBuildLocalDependenciesDir(): File =
@@ -146,70 +141,4 @@ fun ModuleDependency.includeIntellijCoreJarDependencies(project: Project, jarsFi
rootProject = project.rootProject
)
fun Project.intellijRootDir() = IntellijRootUtils.getIntellijRootDir(project)
fun DependencyHandlerScope.excludeInAndroidStudio(rootProject: Project, block: DependencyHandlerScope.() -> Unit) {
if (!rootProject.extra.has("versions.androidStudioRelease")) {
block()
}
}
fun Project.runIdeTask(name: String, ideaPluginDir: File, ideaSandboxDir: File, body: JavaExec.() -> Unit): TaskProvider<JavaExec> {
return tasks.register<JavaExec>(name) {
val ideaSandboxConfigDir = File(ideaSandboxDir, "config")
classpath = mainSourceSet.runtimeClasspath
mainClass.set("com.intellij.idea.Main")
workingDir = File(intellijRootDir(), "bin")
jvmArgs(
"-Xmx1250m",
"-XX:ReservedCodeCacheSize=240m",
"-XX:+HeapDumpOnOutOfMemoryError",
"-ea",
"-Didea.debug.mode=true",
"-Didea.system.path=$ideaSandboxDir",
"-Didea.config.path=$ideaSandboxConfigDir",
"-Didea.tooling.debug=true",
"-Dfus.internal.test.mode=true",
"-Dapple.laf.useScreenMenuBar=true",
"-Dapple.awt.graphics.UseQuartz=true",
"-Dsun.io.useCanonCaches=false",
"-Dplugin.path=${ideaPluginDir.absolutePath}"
)
jvmArgs("-Didea.platform.prefix=Idea")
if (rootProject.findProperty("versions.androidStudioRelease") != null) {
jvmArgs("-Didea.platform.prefix=AndroidStudio")
}
if (project.hasProperty("noPCE")) {
jvmArgs("-Didea.ProcessCanceledException=disabled")
}
jvmArgs("-Didea.is.internal=${project.findProperty("idea.is.internal") ?: true}")
project.findProperty("idea.args")?.let { arguments ->
jvmArgs(arguments.toString().split(" "))
}
args()
doFirst {
val disabledPluginsFile = File(ideaSandboxConfigDir, "disabled_plugins.txt")
val disabledPluginsContents = disabledPluginsFile.takeIf { it.isFile }?.readLines()
val filteredContents = disabledPluginsContents?.filterNot { it.contains("org.jetbrains.kotlin") }
if (filteredContents != null && filteredContents.size != disabledPluginsContents.size) {
with(disabledPluginsFile.printWriter()) {
filteredContents.forEach(this::println)
}
}
}
body()
}
}
fun Project.intellijRootDir() = IntellijRootUtils.getIntellijRootDir(project)

View File

@@ -45,7 +45,7 @@ import org.jetbrains.org.objectweb.asm.tree.analysis.Interpreter
import org.jetbrains.org.objectweb.asm.tree.analysis.Value
/**
* @see FlexibleMethodAnalyzer
* @see org.jetbrains.kotlin.codegen.optimization.fixStack.HackedFixStackMethodAnalyzerBase
*/
@Suppress("DuplicatedCode")
open class FastMethodAnalyzer<V : Value>(

View File

@@ -1,346 +0,0 @@
/*
* Copyright 2010-2015 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
*
* ASM: a very small and fast Java bytecode manipulation framework
* Copyright (c) 2000-2011 INRIA, France Telecom
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. Neither the name of the copyright holders nor the names of its
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
* THE POSSIBILITY OF SUCH DAMAGE.
*
*/
package org.jetbrains.kotlin.codegen.optimization.common
import org.jetbrains.kotlin.codegen.inline.insnText
import org.jetbrains.org.objectweb.asm.Opcodes
import org.jetbrains.org.objectweb.asm.Type
import org.jetbrains.org.objectweb.asm.tree.*
import org.jetbrains.org.objectweb.asm.tree.analysis.AnalyzerException
import org.jetbrains.org.objectweb.asm.tree.analysis.Frame
import org.jetbrains.org.objectweb.asm.tree.analysis.Interpreter
import org.jetbrains.org.objectweb.asm.tree.analysis.Value
/**
* This class is a modified version of `org.objectweb.asm.tree.analysis.Analyzer`
*
* @see FastMethodAnalyzer
*
* @author Eric Bruneton
* @author Dmitry Petrov
*/
@Suppress("DuplicatedCode")
open class FlexibleMethodAnalyzer<V : Value>(
private val owner: String,
val method: MethodNode,
protected val interpreter: Interpreter<V>
) {
protected val insnsArray: Array<AbstractInsnNode> = method.instructions.toArray()
private val nInsns = insnsArray.size
val frames: Array<Frame<V>?> = arrayOfNulls(nInsns)
private val handlers: Array<MutableList<TryCatchBlockNode>?> = arrayOfNulls(nInsns)
private val queued = BooleanArray(nInsns)
private val queue = IntArray(nInsns)
private var top = 0
private val singlePredBlock = IntArray(nInsns)
protected open fun newFrame(nLocals: Int, nStack: Int): Frame<V> = Frame(nLocals, nStack)
protected open fun visitControlFlowEdge(insn: Int, successor: Int): Boolean = true
protected open fun visitControlFlowExceptionEdge(insn: Int, successor: Int): Boolean = true
fun analyze(): Array<Frame<V>?> {
if (nInsns == 0) return frames
checkAssertions()
computeExceptionHandlersForEachInsn()
initSinglePredBlocks()
val current = newFrame(method.maxLocals, method.maxStack)
val handler = newFrame(method.maxLocals, method.maxStack)
initControlFlowAnalysis(current, method, owner)
while (top > 0) {
val insn = queue[--top]
val f = frames[insn]!!
queued[insn] = false
val insnNode = method.instructions[insn]
try {
val insnOpcode = insnNode.opcode
val insnType = insnNode.type
if (insnType == AbstractInsnNode.LABEL || insnType == AbstractInsnNode.LINE || insnType == AbstractInsnNode.FRAME) {
visitNopInsn(f, insn)
} else {
current.init(f).execute(insnNode, interpreter)
when {
insnNode is JumpInsnNode ->
visitJumpInsnNode(insnNode, current, insn, insnOpcode)
insnNode is LookupSwitchInsnNode ->
visitLookupSwitchInsnNode(insnNode, current, insn)
insnNode is TableSwitchInsnNode ->
visitTableSwitchInsnNode(insnNode, current, insn)
insnOpcode != Opcodes.ATHROW && (insnOpcode < Opcodes.IRETURN || insnOpcode > Opcodes.RETURN) ->
visitOpInsn(current, insn)
else -> {
}
}
}
handlers[insn]?.forEach { tcb ->
val exnType = Type.getObjectType(tcb.type ?: "java/lang/Throwable")
val jump = tcb.handler.indexOf()
if (visitControlFlowExceptionEdge(insn, tcb.handler.indexOf())) {
handler.init(f)
handler.clearStack()
handler.push(interpreter.newValue(exnType))
mergeControlFlowEdge(insn, jump, handler)
}
}
} catch (e: AnalyzerException) {
throw AnalyzerException(e.node, "Error at instruction #$insn ${insnNode.insnText}: ${e.message}", e)
} catch (e: Exception) {
throw AnalyzerException(insnNode, "Error at instruction #$insn ${insnNode.insnText}: ${e.message}", e)
}
}
return frames
}
private fun initSinglePredBlocks() {
markSinglePredBlockEntries()
markSinglePredBlockBodies()
}
private fun markSinglePredBlockEntries() {
// Method entry point is SPB entry point.
var blockId = 0
singlePredBlock[0] = ++blockId
// Every jump target is SPB entry point.
for (insn in insnsArray) {
when (insn) {
is JumpInsnNode -> {
val labelIndex = insn.label.indexOf()
if (singlePredBlock[labelIndex] == 0) {
singlePredBlock[labelIndex] = ++blockId
}
}
is LookupSwitchInsnNode -> {
insn.dflt?.let { dfltLabel ->
val dfltIndex = dfltLabel.indexOf()
if (singlePredBlock[dfltIndex] == 0) {
singlePredBlock[dfltIndex] = ++blockId
}
}
for (label in insn.labels) {
val labelIndex = label.indexOf()
if (singlePredBlock[labelIndex] == 0) {
singlePredBlock[labelIndex] = ++blockId
}
}
}
is TableSwitchInsnNode -> {
insn.dflt?.let { dfltLabel ->
val dfltIndex = dfltLabel.indexOf()
if (singlePredBlock[dfltIndex] == 0) {
singlePredBlock[dfltIndex] = ++blockId
}
}
for (label in insn.labels) {
val labelIndex = label.indexOf()
if (singlePredBlock[labelIndex] == 0) {
singlePredBlock[labelIndex] = ++blockId
}
}
}
}
}
// Every try-catch block handler entry point is SPB entry point
for (tcb in method.tryCatchBlocks) {
val handlerIndex = tcb.handler.indexOf()
if (singlePredBlock[handlerIndex] == 0) {
singlePredBlock[handlerIndex] = ++blockId
}
}
}
private fun markSinglePredBlockBodies() {
var current = 0
for ((i, insn) in insnsArray.withIndex()) {
if (singlePredBlock[i] == 0) {
singlePredBlock[i] = current
} else {
// Entered a new SPB.
current = singlePredBlock[i]
}
// GOTO, ATHROW, *RETURN instructions terminate current SPB.
when (insn.opcode) {
Opcodes.GOTO,
Opcodes.ATHROW,
in Opcodes.IRETURN..Opcodes.RETURN ->
current = 0
}
}
}
private fun AbstractInsnNode.indexOf() = method.instructions.indexOf(this)
fun getFrame(insn: AbstractInsnNode): Frame<V>? =
frames[insn.indexOf()]
private fun checkAssertions() {
if (insnsArray.any { it.opcode == Opcodes.JSR || it.opcode == Opcodes.RET })
throw AssertionError("Subroutines are deprecated since Java 6")
}
private fun visitOpInsn(current: Frame<V>, insn: Int) {
processControlFlowEdge(current, insn, insn + 1)
}
private fun visitTableSwitchInsnNode(insnNode: TableSwitchInsnNode, current: Frame<V>, insn: Int) {
var jump = insnNode.dflt.indexOf()
processControlFlowEdge(current, insn, jump)
// In most cases order of visiting switch labels should not matter
// The only one is a tableswitch being added in the beginning of coroutine method, these switch' labels may lead
// in the middle of try/catch block, and FixStackAnalyzer is not ready for this (trying to restore stack before it was saved)
// So we just fix the order of labels being traversed: the first one should be one at the method beginning
// Using 'reversed' is because nodes are processed in LIFO order
for (label in insnNode.labels.reversed()) {
jump = label.indexOf()
processControlFlowEdge(current, insn, jump)
}
}
private fun visitLookupSwitchInsnNode(insnNode: LookupSwitchInsnNode, current: Frame<V>, insn: Int) {
var jump = insnNode.dflt.indexOf()
processControlFlowEdge(current, insn, jump)
for (label in insnNode.labels) {
jump = label.indexOf()
processControlFlowEdge(current, insn, jump)
}
}
private fun visitJumpInsnNode(insnNode: JumpInsnNode, current: Frame<V>, insn: Int, insnOpcode: Int) {
if (insnOpcode != Opcodes.GOTO && insnOpcode != Opcodes.JSR) {
processControlFlowEdge(current, insn, insn + 1)
}
val jump = insnNode.label.indexOf()
processControlFlowEdge(current, insn, jump)
}
private fun visitNopInsn(f: Frame<V>, insn: Int) {
processControlFlowEdge(f, insn, insn + 1)
}
private fun processControlFlowEdge(current: Frame<V>, insn: Int, jump: Int) {
if (visitControlFlowEdge(insn, jump)) {
mergeControlFlowEdge(insn, jump, current)
}
}
private fun initControlFlowAnalysis(current: Frame<V>, m: MethodNode, owner: String) {
current.setReturn(interpreter.newValue(Type.getReturnType(m.desc)))
val args = Type.getArgumentTypes(m.desc)
var local = 0
if ((m.access and Opcodes.ACC_STATIC) == 0) {
val ctype = Type.getObjectType(owner)
current.setLocal(local++, interpreter.newValue(ctype))
}
for (arg in args) {
current.setLocal(local++, interpreter.newValue(arg))
if (arg.size == 2) {
current.setLocal(local++, interpreter.newValue(null))
}
}
while (local < m.maxLocals) {
current.setLocal(local++, interpreter.newValue(null))
}
mergeControlFlowEdge(0, 0, current)
}
private fun computeExceptionHandlersForEachInsn() {
for (tcb in method.tryCatchBlocks) {
val begin = tcb.start.indexOf()
val end = tcb.end.indexOf()
for (j in begin until end) {
val insn = insnsArray[j]
if (!insn.isMeaningful) continue
var insnHandlers: MutableList<TryCatchBlockNode>? = handlers[j]
if (insnHandlers == null) {
insnHandlers = ArrayList<TryCatchBlockNode>()
handlers[j] = insnHandlers
}
insnHandlers.add(tcb)
}
}
}
private fun mergeControlFlowEdge(src: Int, dest: Int, frame: Frame<V>) {
val oldFrame = frames[dest]
val changes = when {
oldFrame == null -> {
frames[dest] = newFrame(frame.locals, frame.maxStackSize).apply { init(frame) }
true
}
dest == src + 1 && singlePredBlock[src] == singlePredBlock[dest] -> {
// Forward jump within a single predecessor block, no need to merge.
oldFrame.init(frame)
true
}
else ->
oldFrame.merge(frame, interpreter)
}
if (changes && !queued[dest]) {
queued[dest] = true
queue[top++] = dest
}
}
}

View File

@@ -19,9 +19,6 @@ package org.jetbrains.kotlin.codegen.optimization.fixStack
import com.intellij.util.containers.Stack
import org.jetbrains.kotlin.codegen.inline.isAfterInlineMarker
import org.jetbrains.kotlin.codegen.inline.isBeforeInlineMarker
import org.jetbrains.kotlin.codegen.inline.isMarkedReturn
import org.jetbrains.kotlin.codegen.optimization.common.FlexibleMethodAnalyzer
import org.jetbrains.kotlin.codegen.optimization.common.OptimizationBasicInterpreter
import org.jetbrains.kotlin.codegen.pseudoInsns.PseudoInsn
import org.jetbrains.kotlin.utils.SmartList
import org.jetbrains.org.objectweb.asm.Opcodes
@@ -29,8 +26,6 @@ import org.jetbrains.org.objectweb.asm.tree.AbstractInsnNode
import org.jetbrains.org.objectweb.asm.tree.JumpInsnNode
import org.jetbrains.org.objectweb.asm.tree.LabelNode
import org.jetbrains.org.objectweb.asm.tree.MethodNode
import org.jetbrains.org.objectweb.asm.tree.analysis.AnalyzerException
import org.jetbrains.org.objectweb.asm.tree.analysis.BasicValue
import org.jetbrains.org.objectweb.asm.tree.analysis.Frame
import org.jetbrains.org.objectweb.asm.tree.analysis.Interpreter
import kotlin.math.max
@@ -50,9 +45,14 @@ internal class FixStackAnalyzer(
val maxExtraStackSize: Int get() = analyzer.maxExtraStackSize
fun getStackToSpill(location: AbstractInsnNode) = analyzer.spilledStacks[location]
fun getActualStack(location: AbstractInsnNode) = getFrame(location)?.getStackContent()
fun getActualStackSize(location: AbstractInsnNode) = getFrame(location)?.stackSizeWithExtra ?: DEAD_CODE_STACK_SIZE
fun getStackToSpill(location: AbstractInsnNode): List<FixStackValue>? =
analyzer.spilledStacks[location]
fun getActualStack(location: AbstractInsnNode): List<FixStackValue>? =
getFrame(location)?.getStackContent()
fun getActualStackSize(location: AbstractInsnNode): Int =
getFrame(location)?.stackSizeWithExtra ?: DEAD_CODE_STACK_SIZE
fun getExpectedStackSize(location: AbstractInsnNode): Int {
// We should look for expected stack size at loop entry point markers if available,
@@ -90,9 +90,9 @@ internal class FixStackAnalyzer(
private val analyzer = InternalAnalyzer(owner)
private inner class InternalAnalyzer(owner: String) :
FlexibleMethodAnalyzer<BasicValue>(owner, method, OptimizationBasicInterpreter()) {
HackedFixStackMethodAnalyzerBase<FixStackValue>(owner, method, FixStackInterpreter()) {
val spilledStacks = hashMapOf<AbstractInsnNode, List<BasicValue>>()
val spilledStacks = hashMapOf<AbstractInsnNode, List<FixStackValue>>()
var maxExtraStackSize = 0; private set
override fun visitControlFlowEdge(insn: Int, successor: Int): Boolean {
@@ -101,15 +101,15 @@ internal class FixStackAnalyzer(
return !(insnNode is JumpInsnNode && context.breakContinueGotoNodes.contains(insnNode))
}
override fun newFrame(nLocals: Int, nStack: Int): Frame<BasicValue> =
override fun newFrame(nLocals: Int, nStack: Int): Frame<FixStackValue> =
FixStackFrame(nLocals, nStack)
private fun indexOf(node: AbstractInsnNode) = method.instructions.indexOf(node)
inner class FixStackFrame(nLocals: Int, nStack: Int) : Frame<BasicValue>(nLocals, nStack) {
val extraStack = Stack<BasicValue>()
inner class FixStackFrame(nLocals: Int, nStack: Int) : Frame<FixStackValue>(nLocals, nStack) {
val extraStack = Stack<FixStackValue>()
override fun init(src: Frame<out BasicValue>): Frame<BasicValue> {
override fun init(src: Frame<out FixStackValue>): Frame<FixStackValue> {
extraStack.clear()
extraStack.addAll((src as FixStackFrame).extraStack)
return super.init(src)
@@ -120,7 +120,7 @@ internal class FixStackAnalyzer(
super.clearStack()
}
override fun execute(insn: AbstractInsnNode, interpreter: Interpreter<BasicValue>) {
override fun execute(insn: AbstractInsnNode, interpreter: Interpreter<FixStackValue>) {
when {
PseudoInsn.SAVE_STACK_BEFORE_TRY.isa(insn) ->
executeSaveStackBeforeTry(insn)
@@ -130,10 +130,8 @@ internal class FixStackAnalyzer(
executeBeforeInlineCallMarker(insn)
isAfterInlineMarker(insn) ->
executeAfterInlineCallMarker(insn)
isMarkedReturn(insn) -> {
// KT-9644: might throw "Incompatible return type" on non-local return, in fact we don't care.
if (insn.opcode == Opcodes.RETURN) return
}
insn.opcode == Opcodes.RETURN ->
return
}
super.execute(insn, interpreter)
@@ -141,14 +139,16 @@ internal class FixStackAnalyzer(
val stackSizeWithExtra: Int get() = super.getStackSize() + extraStack.size
fun getStackContent(): List<BasicValue> {
val savedStack = arrayListOf<BasicValue>()
IntRange(0, super.getStackSize() - 1).mapTo(savedStack) { super.getStack(it) }
fun getStackContent(): List<FixStackValue> {
val savedStack = ArrayList<FixStackValue>()
for (i in 0 until super.getStackSize()) {
savedStack.add(super.getStack(i))
}
savedStack.addAll(extraStack)
return savedStack
}
override fun push(value: BasicValue) {
override fun push(value: FixStackValue) {
if (super.getStackSize() < maxStackSize) {
super.push(value)
} else {
@@ -157,19 +157,18 @@ internal class FixStackAnalyzer(
}
}
fun pushAll(values: Collection<BasicValue>) {
fun pushAll(values: Collection<FixStackValue>) {
values.forEach { push(it) }
}
override fun pop(): BasicValue {
return if (extraStack.isNotEmpty()) {
override fun pop(): FixStackValue =
if (extraStack.isNotEmpty()) {
extraStack.pop()
} else {
super.pop()
}
}
override fun setStack(i: Int, value: BasicValue) {
override fun setStack(i: Int, value: FixStackValue) {
if (i < super.getMaxStackSize()) {
super.setStack(i, value)
} else {
@@ -177,29 +176,8 @@ internal class FixStackAnalyzer(
}
}
override fun merge(frame: Frame<out BasicValue>, interpreter: Interpreter<BasicValue>): Boolean {
val other = frame as FixStackFrame
if (stackSizeWithExtra != other.stackSizeWithExtra) {
throw AnalyzerException(null, "Incompatible stack heights")
}
var changed = false
for (i in 0 until stackSize) {
val v0 = super.getStack(i)
val vm = interpreter.merge(v0, other.getStack(i))
if (vm != v0) {
super.setStack(i, vm)
changed = true
}
}
for (i in 0 until extraStack.size) {
val v0 = extraStack[i]
val vm = interpreter.merge(v0, other.extraStack[i])
if (vm != v0) {
extraStack[i] = vm
changed = true
}
}
return changed
override fun merge(frame: Frame<out FixStackValue>, interpreter: Interpreter<FixStackValue>): Boolean {
throw UnsupportedOperationException("Stack normalization should not merge frames")
}
}

View File

@@ -0,0 +1,157 @@
/*
* 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.codegen.optimization.fixStack
import org.jetbrains.kotlin.codegen.inline.insnOpcodeText
import org.jetbrains.org.objectweb.asm.Handle
import org.jetbrains.org.objectweb.asm.Opcodes.*
import org.jetbrains.org.objectweb.asm.Type
import org.jetbrains.org.objectweb.asm.tree.*
import org.jetbrains.org.objectweb.asm.tree.analysis.Interpreter
open class FixStackInterpreter : Interpreter<FixStackValue>(API_VERSION) {
override fun newValue(type: Type?): FixStackValue =
type?.toFixStackValue()
?: FixStackValue.UNINITIALIZED
override fun newOperation(insn: AbstractInsnNode): FixStackValue? =
when (insn.opcode) {
ACONST_NULL ->
FixStackValue.OBJECT
ICONST_M1, ICONST_0, ICONST_1, ICONST_2, ICONST_3, ICONST_4, ICONST_5 ->
FixStackValue.INT
LCONST_0, LCONST_1 ->
FixStackValue.LONG
FCONST_0, FCONST_1, FCONST_2 ->
FixStackValue.FLOAT
DCONST_0, DCONST_1 ->
FixStackValue.DOUBLE
BIPUSH, SIPUSH ->
FixStackValue.INT
LDC -> {
when (val cst = (insn as LdcInsnNode).cst) {
is Int ->
FixStackValue.INT
is Float ->
FixStackValue.FLOAT
is Long ->
FixStackValue.LONG
is Double ->
FixStackValue.DOUBLE
is String, is Handle ->
FixStackValue.OBJECT
is Type -> {
val sort = cst.sort
if (sort == Type.OBJECT || sort == Type.ARRAY || sort == Type.METHOD)
FixStackValue.OBJECT
else
throw IllegalArgumentException("Illegal LDC constant $cst")
}
else ->
throw IllegalArgumentException("Illegal LDC constant $cst")
}
}
GETSTATIC ->
newValue(Type.getType((insn as FieldInsnNode).desc))
NEW ->
newValue(Type.getObjectType((insn as TypeInsnNode).desc))
else ->
throw IllegalArgumentException("Unexpected instruction: " + insn.insnOpcodeText)
}
override fun copyOperation(insn: AbstractInsnNode, value: FixStackValue?): FixStackValue =
when (insn.opcode) {
ILOAD -> FixStackValue.INT
LLOAD -> FixStackValue.LONG
FLOAD -> FixStackValue.FLOAT
DLOAD -> FixStackValue.DOUBLE
ALOAD -> FixStackValue.OBJECT
else -> value!!
}
override fun binaryOperation(insn: AbstractInsnNode, value1: FixStackValue?, value2: FixStackValue?): FixStackValue? =
when (insn.opcode) {
IALOAD, BALOAD, CALOAD, SALOAD, IADD, ISUB, IMUL, IDIV, IREM, ISHL, ISHR, IUSHR, IAND, IOR, IXOR ->
FixStackValue.INT
FALOAD, FADD, FSUB, FMUL, FDIV, FREM ->
FixStackValue.FLOAT
LALOAD, LADD, LSUB, LMUL, LDIV, LREM, LSHL, LSHR, LUSHR, LAND, LOR, LXOR ->
FixStackValue.LONG
DALOAD, DADD, DSUB, DMUL, DDIV, DREM ->
FixStackValue.DOUBLE
AALOAD ->
FixStackValue.OBJECT
LCMP, FCMPL, FCMPG, DCMPL, DCMPG ->
FixStackValue.INT
IF_ICMPEQ, IF_ICMPNE, IF_ICMPLT, IF_ICMPGE, IF_ICMPGT, IF_ICMPLE, IF_ACMPEQ, IF_ACMPNE, PUTFIELD ->
null
else ->
throw IllegalArgumentException("Unexpected instruction: " + insn.insnOpcodeText)
}
override fun ternaryOperation(
insn: AbstractInsnNode,
value1: FixStackValue?,
value2: FixStackValue?,
value3: FixStackValue?
): FixStackValue? =
null
override fun naryOperation(insn: AbstractInsnNode, values: List<FixStackValue?>): FixStackValue? =
when (insn.opcode) {
MULTIANEWARRAY ->
newValue(Type.getType((insn as MultiANewArrayInsnNode).desc))
INVOKEDYNAMIC ->
newValue(Type.getReturnType((insn as InvokeDynamicInsnNode).desc))
else ->
newValue(Type.getReturnType((insn as MethodInsnNode).desc))
}
override fun returnOperation(insn: AbstractInsnNode?, value: FixStackValue?, expected: FixStackValue?) {
}
override fun unaryOperation(insn: AbstractInsnNode, value: FixStackValue?): FixStackValue? =
when (insn.opcode) {
INEG, IINC, L2I, F2I, D2I, I2B, I2C, I2S ->
FixStackValue.INT
FNEG, I2F, L2F, D2F ->
FixStackValue.FLOAT
LNEG, I2L, F2L, D2L ->
FixStackValue.LONG
DNEG, I2D, L2D, F2D ->
FixStackValue.DOUBLE
IFEQ, IFNE, IFLT, IFGE, IFGT, IFLE, TABLESWITCH, LOOKUPSWITCH, IRETURN, LRETURN, FRETURN, DRETURN, ARETURN, PUTSTATIC ->
null
GETFIELD ->
newValue(Type.getType((insn as FieldInsnNode).desc))
NEWARRAY ->
FixStackValue.OBJECT
ANEWARRAY -> {
FixStackValue.OBJECT
}
ARRAYLENGTH ->
FixStackValue.INT
ATHROW ->
null
CHECKCAST ->
FixStackValue.OBJECT
INSTANCEOF ->
FixStackValue.INT
MONITORENTER, MONITOREXIT, IFNULL, IFNONNULL ->
null
else ->
throw IllegalArgumentException("Unexpected instruction: " + insn.insnOpcodeText)
}
override fun merge(v: FixStackValue?, w: FixStackValue?): FixStackValue? =
when {
v == w -> v
v == null -> w
w == null -> v
else -> throw AssertionError("Mismatching value kinds: $v != $w")
}
}

View File

@@ -0,0 +1,38 @@
/*
* 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.codegen.optimization.fixStack
import org.jetbrains.org.objectweb.asm.Opcodes
import org.jetbrains.org.objectweb.asm.Type
import org.jetbrains.org.objectweb.asm.tree.analysis.Value
enum class FixStackValue(
private val _size: Int,
val loadOpcode: Int,
val storeOpcode: Int,
val popOpcode: Int
) : Value {
INT(1, Opcodes.ILOAD, Opcodes.ISTORE, Opcodes.POP),
LONG(2, Opcodes.LLOAD, Opcodes.LSTORE, Opcodes.POP2),
FLOAT(1, Opcodes.FLOAD, Opcodes.FSTORE, Opcodes.POP),
DOUBLE(2, Opcodes.DLOAD, Opcodes.DSTORE, Opcodes.POP2),
OBJECT(1, Opcodes.ALOAD, Opcodes.ASTORE, Opcodes.POP),
UNINITIALIZED(1, -1, -1, -1)
;
override fun getSize(): Int = _size
}
fun Type.toFixStackValue(): FixStackValue? =
when (this.sort) {
Type.VOID -> null
Type.BOOLEAN, Type.BYTE, Type.CHAR, Type.SHORT, Type.INT -> FixStackValue.INT
Type.LONG -> FixStackValue.LONG
Type.FLOAT -> FixStackValue.FLOAT
Type.DOUBLE -> FixStackValue.DOUBLE
Type.OBJECT, Type.ARRAY, Type.METHOD -> FixStackValue.OBJECT
else -> throw AssertionError("Unexpected type: $this")
}

View File

@@ -0,0 +1,318 @@
/*
* 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.
*
* ASM: a very small and fast Java bytecode manipulation framework
* Copyright (c) 2000-2011 INRIA, France Telecom
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. Neither the name of the copyright holders nor the names of its
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
* THE POSSIBILITY OF SUCH DAMAGE.
*/
package org.jetbrains.kotlin.codegen.optimization.fixStack
import org.jetbrains.kotlin.codegen.inline.insnText
import org.jetbrains.org.objectweb.asm.Opcodes
import org.jetbrains.org.objectweb.asm.Type
import org.jetbrains.org.objectweb.asm.tree.*
import org.jetbrains.org.objectweb.asm.tree.analysis.AnalyzerException
import org.jetbrains.org.objectweb.asm.tree.analysis.Frame
import org.jetbrains.org.objectweb.asm.tree.analysis.Interpreter
import org.jetbrains.org.objectweb.asm.tree.analysis.Value
/**
* @see org.jetbrains.kotlin.codegen.optimization.common.FastMethodAnalyzer
*/
@Suppress("DuplicatedCode")
internal open class HackedFixStackMethodAnalyzerBase<V : Value>(
private val owner: String,
val method: MethodNode,
protected val interpreter: Interpreter<V>
) {
protected val insnsArray: Array<AbstractInsnNode> = method.instructions.toArray()
private val nInsns = insnsArray.size
private val frames: Array<Frame<V>?> = arrayOfNulls(nInsns)
private val handlers: Array<MutableList<TryCatchBlockNode>?> = arrayOfNulls(nInsns)
private val queued = BooleanArray(nInsns)
private val queue = IntArray(nInsns)
private var top = 0
private val singlePredBlock = IntArray(nInsns)
protected open fun newFrame(nLocals: Int, nStack: Int): Frame<V> = Frame(nLocals, nStack)
protected open fun visitControlFlowEdge(insn: Int, successor: Int): Boolean = true
protected open fun visitControlFlowExceptionEdge(insn: Int, successor: Int): Boolean = true
fun analyze(): Array<Frame<V>?> {
if (nInsns == 0) return frames
// This is a very specific version of method bytecode analyzer that doesn't perform any DFA,
// but infers stack types for reachable instructions instead.
checkAssertions()
computeExceptionEdges()
initSinglePredBlocks()
val current = newFrame(method.maxLocals, method.maxStack)
val handler = newFrame(method.maxLocals, method.maxStack)
initControlFlowAnalysis(current, method, owner)
while (top > 0) {
val insn = queue[--top]
val f = frames[insn]!!
queued[insn] = false
val insnNode = method.instructions[insn]
val insnOpcode = insnNode.opcode
val insnType = insnNode.type
try {
if (insnType == AbstractInsnNode.LABEL || insnType == AbstractInsnNode.LINE || insnType == AbstractInsnNode.FRAME) {
visitNopInsn(f, insn)
} else {
current.init(f).execute(insnNode, interpreter)
when {
insnNode is JumpInsnNode ->
visitJumpInsnNode(insnNode, current, insn, insnOpcode)
insnNode is LookupSwitchInsnNode ->
visitLookupSwitchInsnNode(insnNode, current, insn)
insnNode is TableSwitchInsnNode ->
visitTableSwitchInsnNode(insnNode, current, insn)
insnOpcode != Opcodes.ATHROW && (insnOpcode < Opcodes.IRETURN || insnOpcode > Opcodes.RETURN) ->
visitOpInsn(current, insn)
else -> {
}
}
}
handlers[insn]?.forEach { tcb ->
val exnType = Type.getObjectType(tcb.type ?: "java/lang/Throwable")
val jump = tcb.handler.indexOf()
if (visitControlFlowExceptionEdge(insn, tcb.handler.indexOf())) {
handler.init(f)
handler.clearStack()
handler.push(interpreter.newValue(exnType))
mergeControlFlowEdge(jump, handler)
}
}
} catch (e: AnalyzerException) {
throw AnalyzerException(e.node, "Error at instruction #$insn ${insnNode.insnText}: ${e.message}", e)
} catch (e: Exception) {
throw AnalyzerException(insnNode, "Error at instruction #$insn ${insnNode.insnText}: ${e.message}", e)
}
}
return frames
}
private fun initSinglePredBlocks() {
markSinglePredBlockEntries()
markSinglePredBlockBodies()
}
private fun markSinglePredBlockEntries() {
// Method entry point is SPB entry point.
var blockId = 0
singlePredBlock[0] = ++blockId
// Every jump target is SPB entry point.
for (insn in insnsArray) {
when (insn) {
is JumpInsnNode -> {
val labelIndex = insn.label.indexOf()
if (singlePredBlock[labelIndex] == 0) {
singlePredBlock[labelIndex] = ++blockId
}
}
is LookupSwitchInsnNode -> {
insn.dflt?.let { dfltLabel ->
val dfltIndex = dfltLabel.indexOf()
if (singlePredBlock[dfltIndex] == 0) {
singlePredBlock[dfltIndex] = ++blockId
}
}
for (label in insn.labels) {
val labelIndex = label.indexOf()
if (singlePredBlock[labelIndex] == 0) {
singlePredBlock[labelIndex] = ++blockId
}
}
}
is TableSwitchInsnNode -> {
insn.dflt?.let { dfltLabel ->
val dfltIndex = dfltLabel.indexOf()
if (singlePredBlock[dfltIndex] == 0) {
singlePredBlock[dfltIndex] = ++blockId
}
}
for (label in insn.labels) {
val labelIndex = label.indexOf()
if (singlePredBlock[labelIndex] == 0) {
singlePredBlock[labelIndex] = ++blockId
}
}
}
}
}
// Every try-catch block handler entry point is SPB entry point
for (tcb in method.tryCatchBlocks) {
val handlerIndex = tcb.handler.indexOf()
if (singlePredBlock[handlerIndex] == 0) {
singlePredBlock[handlerIndex] = ++blockId
}
}
}
private fun markSinglePredBlockBodies() {
var current = 0
for ((i, insn) in insnsArray.withIndex()) {
if (singlePredBlock[i] == 0) {
singlePredBlock[i] = current
} else {
// Entered a new SPB.
current = singlePredBlock[i]
}
// GOTO, ATHROW, *RETURN instructions terminate current SPB.
when (insn.opcode) {
Opcodes.GOTO,
Opcodes.ATHROW,
in Opcodes.IRETURN..Opcodes.RETURN ->
current = 0
}
}
}
private fun AbstractInsnNode.indexOf() = method.instructions.indexOf(this)
fun getFrame(insn: AbstractInsnNode): Frame<V>? =
frames[insn.indexOf()]
private fun checkAssertions() {
if (insnsArray.any { it.opcode == Opcodes.JSR || it.opcode == Opcodes.RET })
throw AssertionError("Subroutines are deprecated since Java 6")
}
private fun visitOpInsn(current: Frame<V>, insn: Int) {
processControlFlowEdge(current, insn, insn + 1)
}
private fun visitTableSwitchInsnNode(insnNode: TableSwitchInsnNode, current: Frame<V>, insn: Int) {
var jump = insnNode.dflt.indexOf()
processControlFlowEdge(current, insn, jump)
// In most cases order of visiting switch labels should not matter
// The only one is a tableswitch being added in the beginning of coroutine method, these switch' labels may lead
// in the middle of try/catch block, and FixStackAnalyzer is not ready for this (trying to restore stack before it was saved)
// So we just fix the order of labels being traversed: the first one should be one at the method beginning
// Using 'reversed' is because nodes are processed in LIFO order
for (label in insnNode.labels.reversed()) {
jump = label.indexOf()
processControlFlowEdge(current, insn, jump)
}
}
private fun visitLookupSwitchInsnNode(insnNode: LookupSwitchInsnNode, current: Frame<V>, insn: Int) {
var jump = insnNode.dflt.indexOf()
processControlFlowEdge(current, insn, jump)
for (label in insnNode.labels) {
jump = label.indexOf()
processControlFlowEdge(current, insn, jump)
}
}
private fun visitJumpInsnNode(insnNode: JumpInsnNode, current: Frame<V>, insn: Int, insnOpcode: Int) {
if (insnOpcode != Opcodes.GOTO && insnOpcode != Opcodes.JSR) {
processControlFlowEdge(current, insn, insn + 1)
}
val jump = insnNode.label.indexOf()
processControlFlowEdge(current, insn, jump)
}
private fun visitNopInsn(f: Frame<V>, insn: Int) {
processControlFlowEdge(f, insn, insn + 1)
}
private fun processControlFlowEdge(current: Frame<V>, insn: Int, jump: Int) {
if (visitControlFlowEdge(insn, jump)) {
mergeControlFlowEdge(jump, current)
}
}
private fun initControlFlowAnalysis(current: Frame<V>, m: MethodNode, owner: String) {
current.setReturn(interpreter.newValue(Type.getReturnType(m.desc)))
val args = Type.getArgumentTypes(m.desc)
var local = 0
if ((m.access and Opcodes.ACC_STATIC) == 0) {
val ctype = Type.getObjectType(owner)
current.setLocal(local++, interpreter.newValue(ctype))
}
for (arg in args) {
current.setLocal(local++, interpreter.newValue(arg))
if (arg.size == 2) {
current.setLocal(local++, interpreter.newValue(null))
}
}
while (local < m.maxLocals) {
current.setLocal(local++, interpreter.newValue(null))
}
mergeControlFlowEdge(0, current)
}
private fun computeExceptionEdges() {
for (tcb in method.tryCatchBlocks) {
// Don't have to visit same exception handler multiple times - we care only about stack state at TCB start.
val start = tcb.start.indexOf()
var insnHandlers: MutableList<TryCatchBlockNode>? = handlers[start]
if (insnHandlers == null) {
insnHandlers = ArrayList()
handlers[start] = insnHandlers
}
insnHandlers.add(tcb)
}
}
private fun mergeControlFlowEdge(dest: Int, frame: Frame<V>) {
val destFrame = frames[dest]
if (destFrame == null) {
// Don't have to visit same instruction multiple times - we care only about "initial" stack state.
frames[dest] = newFrame(frame.locals, frame.maxStackSize).apply { init(frame) }
if (!queued[dest]) {
queued[dest] = true
queue[top++] = dest
}
}
}
}

View File

@@ -18,7 +18,6 @@ package org.jetbrains.kotlin.codegen.optimization.fixStack
import org.jetbrains.org.objectweb.asm.tree.AbstractInsnNode
import org.jetbrains.org.objectweb.asm.tree.MethodNode
import org.jetbrains.org.objectweb.asm.tree.analysis.BasicValue
import kotlin.math.max
internal class LocalVariablesManager(val context: FixStackContext, val methodNode: MethodNode) {
@@ -39,7 +38,10 @@ internal class LocalVariablesManager(val context: FixStackContext, val methodNod
methodNode.maxLocals = max(methodNode.maxLocals, newValue)
}
fun allocateVariablesForSaveStackMarker(saveStackMarker: AbstractInsnNode, savedStackValues: List<BasicValue>): SavedStackDescriptor {
fun allocateVariablesForSaveStackMarker(
saveStackMarker: AbstractInsnNode,
savedStackValues: List<FixStackValue>
): SavedStackDescriptor {
val numRestoreStackMarkers = context.restoreStackMarkersForSaveMarker[saveStackMarker]!!.size
return allocateNewHandle(numRestoreStackMarkers, saveStackMarker, savedStackValues)
}
@@ -47,10 +49,10 @@ internal class LocalVariablesManager(val context: FixStackContext, val methodNod
private fun allocateNewHandle(
numRestoreStackMarkers: Int,
saveStackMarker: AbstractInsnNode,
savedStackValues: List<BasicValue>
savedStackValues: List<FixStackValue>
): SavedStackDescriptor {
if (savedStackValues.any { it.type == null }) {
throw AssertionError("Uninitialized value on stack at ${methodNode.instructions.indexOf(saveStackMarker)}")
if (savedStackValues.any { it == FixStackValue.UNINITIALIZED }) {
throw AssertionError("Uninitialized value on stack at ${methodNode.instructions.indexOf(saveStackMarker)}: $savedStackValues")
}
val firstUnusedLocalVarIndex = getFirstUnusedLocalVariableIndex()
@@ -78,7 +80,7 @@ internal class LocalVariablesManager(val context: FixStackContext, val methodNod
fun allocateVariablesForBeforeInlineMarker(
beforeInlineMarker: AbstractInsnNode,
savedStackValues: List<BasicValue>
savedStackValues: List<FixStackValue>
): SavedStackDescriptor {
return allocateNewHandle(1, beforeInlineMarker, savedStackValues)
}
@@ -101,7 +103,7 @@ internal class LocalVariablesManager(val context: FixStackContext, val methodNod
}
}
fun createReturnValueVariable(returnValue: BasicValue): Int {
fun createReturnValueVariable(returnValue: FixStackValue): Int {
val returnValueIndex = getFirstUnusedLocalVariableIndex()
updateMaxLocals(returnValueIndex + returnValue.size)
return returnValueIndex

View File

@@ -54,10 +54,10 @@ fun <V : Value> Frame<V>.peekWords(size1: Int, size2: Int): List<V>? {
}
class SavedStackDescriptor(
val savedValues: List<BasicValue>,
val savedValues: List<FixStackValue>,
val firstLocalVarIndex: Int
) {
private val savedValuesSize = savedValues.fold(0, { size, value -> size + value.size })
private val savedValuesSize = savedValues.fold(0) { size, value -> size + value.size }
val firstUnusedLocalVarIndex = firstLocalVarIndex + savedValuesSize
override fun toString(): String =
@@ -88,13 +88,13 @@ fun restoreStackWithReturnValue(
methodNode: MethodNode,
nodeToReplace: AbstractInsnNode,
savedStackDescriptor: SavedStackDescriptor,
returnValue: BasicValue,
returnValue: FixStackValue,
returnValueLocalVarIndex: Int
) {
with(methodNode.instructions) {
insertBefore(nodeToReplace, VarInsnNode(returnValue.type.getOpcode(Opcodes.ISTORE), returnValueLocalVarIndex))
insertBefore(nodeToReplace, VarInsnNode(returnValue.storeOpcode, returnValueLocalVarIndex))
generateLoadInstructions(methodNode, nodeToReplace, savedStackDescriptor)
insertBefore(nodeToReplace, VarInsnNode(returnValue.type.getOpcode(Opcodes.ILOAD), returnValueLocalVarIndex))
insertBefore(nodeToReplace, VarInsnNode(returnValue.loadOpcode, returnValueLocalVarIndex))
remove(nodeToReplace)
}
}
@@ -102,10 +102,7 @@ fun restoreStackWithReturnValue(
fun generateLoadInstructions(methodNode: MethodNode, location: AbstractInsnNode, savedStackDescriptor: SavedStackDescriptor) {
var localVarIndex = savedStackDescriptor.firstLocalVarIndex
for (value in savedStackDescriptor.savedValues) {
methodNode.instructions.insertBefore(
location,
VarInsnNode(value.type.getOpcode(Opcodes.ILOAD), localVarIndex)
)
methodNode.instructions.insertBefore(location, VarInsnNode(value.loadOpcode, localVarIndex))
localVarIndex += value.size
}
}
@@ -114,10 +111,7 @@ fun generateStoreInstructions(methodNode: MethodNode, location: AbstractInsnNode
var localVarIndex = savedStackDescriptor.firstUnusedLocalVarIndex
for (value in savedStackDescriptor.savedValues.asReversed()) {
localVarIndex -= value.size
methodNode.instructions.insertBefore(
location,
VarInsnNode(value.type.getOpcode(Opcodes.ISTORE), localVarIndex)
)
methodNode.instructions.insertBefore(location, VarInsnNode(value.storeOpcode, localVarIndex))
}
}
@@ -146,10 +140,10 @@ fun replaceAlwaysTrueIfeqWithGoto(methodNode: MethodNode, node: AbstractInsnNode
}
}
fun replaceMarkerWithPops(methodNode: MethodNode, node: AbstractInsnNode, expectedStackSize: Int, stackContent: List<BasicValue>) {
fun replaceMarkerWithPops(methodNode: MethodNode, node: AbstractInsnNode, expectedStackSize: Int, stackContent: List<FixStackValue>) {
with(methodNode.instructions) {
for (stackValue in stackContent.subList(expectedStackSize, stackContent.size)) {
insert(node, getPopInstruction(stackValue))
insert(node, InsnNode(stackValue.popOpcode))
}
remove(node)
}

View File

@@ -417,10 +417,15 @@ class KotlinCoreEnvironment private constructor(
companion object {
private val LOG = Logger.getInstance(KotlinCoreEnvironment::class.java)
private val APPLICATION_LOCK = Object()
@PublishedApi
internal val APPLICATION_LOCK = Object()
private var ourApplicationEnvironment: KotlinCoreApplicationEnvironment? = null
private var ourProjectCount = 0
inline fun <R> underApplicationLock(action: () -> R): R =
synchronized(APPLICATION_LOCK) { action() }
@JvmStatic
fun createForProduction(
parentDisposable: Disposable, configuration: CompilerConfiguration, configFiles: EnvironmentConfigFiles
@@ -493,10 +498,9 @@ class KotlinCoreEnvironment private constructor(
): KotlinCoreApplicationEnvironment {
synchronized(APPLICATION_LOCK) {
if (ourApplicationEnvironment == null) {
val disposable = Disposer.newDisposable()
ourApplicationEnvironment = createApplicationEnvironment(disposable, configuration, unitTestMode)
ourApplicationEnvironment = createApplicationEnvironment(parentDisposable, configuration, unitTestMode)
ourProjectCount = 0
Disposer.register(disposable, Disposable {
Disposer.register(parentDisposable, Disposable {
synchronized(APPLICATION_LOCK) {
ourApplicationEnvironment = null
}

View File

@@ -490,10 +490,9 @@ class KotlinCoreEnvironment private constructor(
): KotlinCoreApplicationEnvironment {
synchronized(APPLICATION_LOCK) {
if (ourApplicationEnvironment == null) {
val disposable = Disposer.newDisposable()
ourApplicationEnvironment = createApplicationEnvironment(disposable, configuration, unitTestMode)
ourProjectCount = 0
Disposer.register(disposable, Disposable {
Disposer.register(parentDisposable, Disposable {
synchronized(APPLICATION_LOCK) {
ourApplicationEnvironment = null
}

View File

@@ -1103,6 +1103,12 @@ public class FirOldFrontendDiagnosticsTestGenerated extends AbstractFirDiagnosti
runTest("compiler/testData/diagnostics/tests/annotations/ConstructorCall.kt");
}
@Test
@TestMetadata("ConstructorCallAllowed.kt")
public void testConstructorCallAllowed() throws Exception {
runTest("compiler/testData/diagnostics/tests/annotations/ConstructorCallAllowed.kt");
}
@Test
@TestMetadata("DanglingMixed.kt")
public void testDanglingMixed() throws Exception {
@@ -31681,6 +31687,12 @@ public class FirOldFrontendDiagnosticsTestGenerated extends AbstractFirDiagnosti
runTest("compiler/testData/diagnostics/tests/when/NonExhaustiveWarningNull.kt");
}
@Test
@TestMetadata("nonExhaustiveWhenStatement_1_5.kt")
public void testNonExhaustiveWhenStatement_1_5() throws Exception {
runTest("compiler/testData/diagnostics/tests/when/nonExhaustiveWhenStatement_1_5.kt");
}
@Test
@TestMetadata("nonExhaustiveWhenStatement_1_6.kt")
public void testNonExhaustiveWhenStatement_1_6() throws Exception {

View File

@@ -1103,6 +1103,12 @@ public class FirOldFrontendDiagnosticsWithLightTreeTestGenerated extends Abstrac
runTest("compiler/testData/diagnostics/tests/annotations/ConstructorCall.kt");
}
@Test
@TestMetadata("ConstructorCallAllowed.kt")
public void testConstructorCallAllowed() throws Exception {
runTest("compiler/testData/diagnostics/tests/annotations/ConstructorCallAllowed.kt");
}
@Test
@TestMetadata("DanglingMixed.kt")
public void testDanglingMixed() throws Exception {
@@ -31681,6 +31687,12 @@ public class FirOldFrontendDiagnosticsWithLightTreeTestGenerated extends Abstrac
runTest("compiler/testData/diagnostics/tests/when/NonExhaustiveWarningNull.kt");
}
@Test
@TestMetadata("nonExhaustiveWhenStatement_1_5.kt")
public void testNonExhaustiveWhenStatement_1_5() throws Exception {
runTest("compiler/testData/diagnostics/tests/when/nonExhaustiveWhenStatement_1_5.kt");
}
@Test
@TestMetadata("nonExhaustiveWhenStatement_1_6.kt")
public void testNonExhaustiveWhenStatement_1_6() throws Exception {

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2010-2020 JetBrains s.r.o. and Kotlin Programming Language contributors.
* 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.
*/

View File

@@ -380,6 +380,76 @@ public class FirBlackBoxCodegenTestGenerated extends AbstractFirBlackBoxCodegenT
}
}
@Nested
@TestMetadata("compiler/testData/codegen/box/annotations/instances")
@TestDataPath("$PROJECT_ROOT")
public class Instances {
@Test
public void testAllFilesPresentInInstances() throws Exception {
KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("compiler/testData/codegen/box/annotations/instances"), Pattern.compile("^(.+)\\.kt$"), null, TargetBackend.JVM_IR, true);
}
@Test
@TestMetadata("annotationEnclosingName.kt")
public void testAnnotationEnclosingName() throws Exception {
runTest("compiler/testData/codegen/box/annotations/instances/annotationEnclosingName.kt");
}
@Test
@TestMetadata("annotationEqHc.kt")
public void testAnnotationEqHc() throws Exception {
runTest("compiler/testData/codegen/box/annotations/instances/annotationEqHc.kt");
}
@Test
@TestMetadata("annotationInstances.kt")
public void testAnnotationInstances() throws Exception {
runTest("compiler/testData/codegen/box/annotations/instances/annotationInstances.kt");
}
@Test
@TestMetadata("annotationInstancesEmptyDefault.kt")
public void testAnnotationInstancesEmptyDefault() throws Exception {
runTest("compiler/testData/codegen/box/annotations/instances/annotationInstancesEmptyDefault.kt");
}
@Test
@TestMetadata("annotationToString.kt")
public void testAnnotationToString() throws Exception {
runTest("compiler/testData/codegen/box/annotations/instances/annotationToString.kt");
}
@Test
@TestMetadata("annotationType.kt")
public void testAnnotationType() throws Exception {
runTest("compiler/testData/codegen/box/annotations/instances/annotationType.kt");
}
@Test
@TestMetadata("javaAnnotation.kt")
public void testJavaAnnotation() throws Exception {
runTest("compiler/testData/codegen/box/annotations/instances/javaAnnotation.kt");
}
@Test
@TestMetadata("multifileEqHc.kt")
public void testMultifileEqHc() throws Exception {
runTest("compiler/testData/codegen/box/annotations/instances/multifileEqHc.kt");
}
@Test
@TestMetadata("multimoduleInlining.kt")
public void testMultimoduleInlining() throws Exception {
runTest("compiler/testData/codegen/box/annotations/instances/multimoduleInlining.kt");
}
@Test
@TestMetadata("multiplatformInstantiation.kt")
public void testMultiplatformInstantiation() throws Exception {
runTest("compiler/testData/codegen/box/annotations/instances/multiplatformInstantiation.kt");
}
}
@Nested
@TestMetadata("compiler/testData/codegen/box/annotations/kClassMapping")
@TestDataPath("$PROJECT_ROOT")
@@ -18910,6 +18980,12 @@ public class FirBlackBoxCodegenTestGenerated extends AbstractFirBlackBoxCodegenT
runTest("compiler/testData/codegen/box/inlineClasses/kt47609.kt");
}
@Test
@TestMetadata("kt47762.kt")
public void testKt47762() throws Exception {
runTest("compiler/testData/codegen/box/inlineClasses/kt47762.kt");
}
@Test
@TestMetadata("mangledDefaultParameterFunction.kt")
public void testMangledDefaultParameterFunction() throws Exception {
@@ -42454,6 +42530,12 @@ public class FirBlackBoxCodegenTestGenerated extends AbstractFirBlackBoxCodegenT
runTest("compiler/testData/codegen/box/unsignedTypes/kt43286a.kt");
}
@Test
@TestMetadata("kt47716.kt")
public void testKt47716() throws Exception {
runTest("compiler/testData/codegen/box/unsignedTypes/kt47716.kt");
}
@Test
@TestMetadata("literalEqualsNullableUnsigned.kt")
public void testLiteralEqualsNullableUnsigned() throws Exception {

View File

@@ -25,6 +25,28 @@ public class FirBlackBoxInlineCodegenTestGenerated extends AbstractFirBlackBoxIn
KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("compiler/testData/codegen/boxInline"), Pattern.compile("^(.+)\\.kt$"), null, TargetBackend.JVM_IR, true);
}
@Nested
@TestMetadata("compiler/testData/codegen/boxInline/annotations")
@TestDataPath("$PROJECT_ROOT")
public class Annotations {
@Test
public void testAllFilesPresentInAnnotations() throws Exception {
KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("compiler/testData/codegen/boxInline/annotations"), Pattern.compile("^(.+)\\.kt$"), null, TargetBackend.JVM_IR, true);
}
@Test
@TestMetadata("annotationInstanceInlining.kt")
public void testAnnotationInstanceInlining() throws Exception {
runTest("compiler/testData/codegen/boxInline/annotations/annotationInstanceInlining.kt");
}
@Test
@TestMetadata("instanceInAnonymousClass.kt")
public void testInstanceInAnonymousClass() throws Exception {
runTest("compiler/testData/codegen/boxInline/annotations/instanceInAnonymousClass.kt");
}
}
@Nested
@TestMetadata("compiler/testData/codegen/boxInline/anonymousObject")
@TestDataPath("$PROJECT_ROOT")

View File

@@ -37,10 +37,8 @@ import org.jetbrains.kotlin.lexer.KtTokens
import org.jetbrains.kotlin.psi.*
import org.jetbrains.kotlin.psi.psiUtil.containingClassOrObject
import org.jetbrains.kotlin.psi.psiUtil.forEachDescendantOfType
import org.jetbrains.kotlin.resolve.*
import org.jetbrains.kotlin.resolve.BindingContext.*
import org.jetbrains.kotlin.resolve.BindingTrace
import org.jetbrains.kotlin.resolve.DescriptorToSourceUtils
import org.jetbrains.kotlin.resolve.DescriptorUtils
import org.jetbrains.kotlin.resolve.bindingContextUtil.getEnclosingDescriptor
import org.jetbrains.kotlin.resolve.bindingContextUtil.isUsedAsExpression
import org.jetbrains.kotlin.resolve.bindingContextUtil.isUsedAsResultOfLambda
@@ -56,7 +54,6 @@ import org.jetbrains.kotlin.resolve.calls.util.isSingleUnderscore
import org.jetbrains.kotlin.resolve.checkers.PlatformDiagnosticSuppressor
import org.jetbrains.kotlin.resolve.descriptorUtil.isEffectivelyExternal
import org.jetbrains.kotlin.resolve.descriptorUtil.module
import org.jetbrains.kotlin.resolve.indexOrMinusOne
import org.jetbrains.kotlin.resolve.scopes.receivers.ExtensionReceiver
import org.jetbrains.kotlin.types.KotlinType
import org.jetbrains.kotlin.types.TypeUtils.*
@@ -1025,20 +1022,16 @@ class ControlFlowInformationProviderImpl private constructor(
}
continue
}
if (!usedAsExpression && missingCases.isNotEmpty()) {
val kind = when {
WhenChecker.getClassDescriptorOfTypeIfSealed(subjectType) != null -> AlgebraicTypeKind.Sealed
WhenChecker.getClassDescriptorOfTypeIfEnum(subjectType) != null -> AlgebraicTypeKind.Enum
subjectType?.isBooleanOrNullableBoolean() == true -> AlgebraicTypeKind.Boolean
else -> null
}
if (!usedAsExpression) {
if (kind != null) {
if (languageVersionSettings.supportsFeature(LanguageFeature.ProhibitNonExhaustiveWhenOnAlgebraicTypes)) {
trace.report(NO_ELSE_IN_WHEN.on(element, missingCases))
} else {
trace.report(NON_EXHAUSTIVE_WHEN_STATEMENT.on(element, kind.displayName, missingCases))
}
}
if (!usedAsExpression) {
if (languageVersionSettings.supportsFeature(LanguageFeature.WarnAboutNonExhaustiveWhenOnAlgebraicTypes)) {
// report warnings on all non-exhaustive when's with algebraic subject
checkExhaustiveWhenStatement(subjectType, element, missingCases)
} else {
// report info if subject is sealed class and warning if it is enum
checkWhenStatement(subjectType, element, context)
}
}
}
@@ -1046,6 +1039,49 @@ class ControlFlowInformationProviderImpl private constructor(
}
}
private fun checkWhenStatement(
subjectType: KotlinType?,
element: KtWhenExpression,
context: BindingContext
) {
val enumClassDescriptor = WhenChecker.getClassDescriptorOfTypeIfEnum(subjectType)
if (enumClassDescriptor != null) {
val enumMissingCases = WhenChecker.getEnumMissingCases(element, context, enumClassDescriptor)
if (enumMissingCases.isNotEmpty()) {
trace.report(NON_EXHAUSTIVE_WHEN.on(element, enumMissingCases))
}
}
val sealedClassDescriptor = WhenChecker.getClassDescriptorOfTypeIfSealed(subjectType)
if (sealedClassDescriptor != null) {
val sealedMissingCases = WhenChecker.getSealedMissingCases(element, context, sealedClassDescriptor)
if (sealedMissingCases.isNotEmpty()) {
trace.report(NON_EXHAUSTIVE_WHEN_ON_SEALED_CLASS.on(element, sealedMissingCases))
}
}
}
private fun checkExhaustiveWhenStatement(
subjectType: KotlinType?,
element: KtWhenExpression,
missingCases: List<WhenMissingCase>
) {
if (missingCases.isEmpty()) return
val kind = when {
WhenChecker.getClassDescriptorOfTypeIfSealed(subjectType) != null -> AlgebraicTypeKind.Sealed
WhenChecker.getClassDescriptorOfTypeIfEnum(subjectType) != null -> AlgebraicTypeKind.Enum
subjectType?.isBooleanOrNullableBoolean() == true -> AlgebraicTypeKind.Boolean
else -> null
}
if (kind != null) {
if (languageVersionSettings.supportsFeature(LanguageFeature.ProhibitNonExhaustiveWhenOnAlgebraicTypes)) {
trace.report(NO_ELSE_IN_WHEN.on(element, missingCases))
} else {
trace.report(NON_EXHAUSTIVE_WHEN_STATEMENT.on(element, kind.displayName, missingCases))
}
}
}
private enum class AlgebraicTypeKind(val displayName: String) {
Sealed("sealed class/interface"),
Enum("enum"),

View File

@@ -1,17 +1,6 @@
/*
* Copyright 2010-2017 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
* 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.resolve.calls
@@ -238,7 +227,8 @@ class CallExpressionResolver(
if (functionDescriptor is ConstructorDescriptor) {
val constructedClass = functionDescriptor.constructedClass
if (DescriptorUtils.isAnnotationClass(constructedClass) && !canInstantiateAnnotationClass(callExpression, context.trace)) {
context.trace.report(ANNOTATION_CLASS_CONSTRUCTOR_CALL.on(callExpression))
val supported = context.languageVersionSettings.supportsFeature(LanguageFeature.InstantiationOfAnnotationClasses) && constructedClass.declaredTypeParameters.isEmpty()
if (!supported) context.trace.report(ANNOTATION_CLASS_CONSTRUCTOR_CALL.on(callExpression))
}
if (DescriptorUtils.isEnumClass(constructedClass)) {
context.trace.report(ENUM_CLASS_CONSTRUCTOR_CALL.on(callExpression))
@@ -515,7 +505,7 @@ class CallExpressionResolver(
companion object {
private fun canInstantiateAnnotationClass(expression: KtCallExpression, trace: BindingTrace): Boolean {
fun canInstantiateAnnotationClass(expression: KtCallExpression, trace: BindingTrace): Boolean {
//noinspection unchecked
var parent: PsiElement? = PsiTreeUtil.getParentOfType(expression, KtValueArgument::class.java, KtParameter::class.java)
if (parent is KtValueArgument) {

View File

@@ -0,0 +1,40 @@
/*
* 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.resolve.calls.checkers
import com.intellij.psi.PsiElement
import org.jetbrains.kotlin.config.LanguageFeature
import org.jetbrains.kotlin.descriptors.ConstructorDescriptor
import org.jetbrains.kotlin.diagnostics.Errors
import org.jetbrains.kotlin.psi.KtCallExpression
import org.jetbrains.kotlin.resolve.DescriptorUtils
import org.jetbrains.kotlin.resolve.calls.CallExpressionResolver
import org.jetbrains.kotlin.resolve.calls.model.ResolvedCall
/**
* Additional checker that prohibits usage of LanguageFeature.InstantiationOfAnnotationClasses on backends
* that do not support this feature yet
*/
object InstantiationOfAnnotationClassesCallChecker : CallChecker {
override fun check(resolvedCall: ResolvedCall<*>, reportOn: PsiElement, context: CallCheckerContext) {
if (!context.languageVersionSettings.supportsFeature(LanguageFeature.InstantiationOfAnnotationClasses)) return
val calledDescriptor = resolvedCall.resultingDescriptor as? ConstructorDescriptor ?: return
val constructedClass = calledDescriptor.constructedClass
val expression = resolvedCall.call.callElement as? KtCallExpression ?: return
if (DescriptorUtils.isAnnotationClass(constructedClass) && !CallExpressionResolver.canInstantiateAnnotationClass(
expression,
context.trace
)
) {
val supported = constructedClass.declaredTypeParameters.isEmpty()
if (supported) {
context.trace.report(Errors.ANNOTATION_CLASS_CONSTRUCTOR_CALL.on(expression))
} else {
// already reported in CallExpressionResolver.getCallExpressionTypeInfoWithoutFinalTypeCheck
}
}
}
}

View File

@@ -0,0 +1,208 @@
/*
* 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.backend.common.lower
import org.jetbrains.kotlin.backend.common.BackendContext
import org.jetbrains.kotlin.backend.common.FileLoweringPass
import org.jetbrains.kotlin.backend.common.IrElementTransformerVoidWithContext
import org.jetbrains.kotlin.backend.common.deepCopyWithVariables
import org.jetbrains.kotlin.backend.common.ir.copyTo
import org.jetbrains.kotlin.backend.common.ir.createImplicitParameterDeclarationWithWrappedDescriptor
import org.jetbrains.kotlin.descriptors.DescriptorVisibilities
import org.jetbrains.kotlin.descriptors.Modality
import org.jetbrains.kotlin.ir.UNDEFINED_OFFSET
import org.jetbrains.kotlin.ir.builders.*
import org.jetbrains.kotlin.ir.builders.declarations.*
import org.jetbrains.kotlin.ir.declarations.*
import org.jetbrains.kotlin.ir.expressions.IrConstructorCall
import org.jetbrains.kotlin.ir.expressions.IrExpression
import org.jetbrains.kotlin.ir.expressions.IrGetValue
import org.jetbrains.kotlin.ir.expressions.impl.IrConstructorCallImpl
import org.jetbrains.kotlin.ir.expressions.impl.IrDelegatingConstructorCallImpl
import org.jetbrains.kotlin.ir.expressions.impl.IrGetValueImpl
import org.jetbrains.kotlin.ir.expressions.impl.IrSetFieldImpl
import org.jetbrains.kotlin.ir.types.IrType
import org.jetbrains.kotlin.ir.types.classOrNull
import org.jetbrains.kotlin.ir.types.isKClass
import org.jetbrains.kotlin.ir.util.*
import org.jetbrains.kotlin.ir.visitors.transformChildrenVoid
import org.jetbrains.kotlin.name.Name
val ANNOTATION_IMPLEMENTATION = object : IrDeclarationOriginImpl("ANNOTATION_IMPLEMENTATION", isSynthetic = true) {}
class AnnotationImplementationLowering(
val transformer: (IrFile) -> AnnotationImplementationTransformer
) : FileLoweringPass {
override fun lower(irFile: IrFile) {
val tf = transformer(irFile)
irFile.transformChildrenVoid(tf)
tf.implementations.values.forEach {
val parentClass = it.parent as IrDeclarationContainer
parentClass.declarations += it
}
}
}
open class AnnotationImplementationTransformer(val context: BackendContext, val irFile: IrFile) : IrElementTransformerVoidWithContext() {
internal val implementations: MutableMap<IrClass, IrClass> = mutableMapOf()
override fun visitConstructorCall(expression: IrConstructorCall): IrExpression {
val constructedClass = expression.type.classOrNull?.owner ?: return expression
if (!constructedClass.isAnnotationClass) return expression
if (constructedClass.typeParameters.isNotEmpty()) return expression // Not supported yet
val implClass = implementations.getOrPut(constructedClass) { createAnnotationImplementation(constructedClass) }
val ctor = implClass.constructors.single()
val newCall = IrConstructorCallImpl.fromSymbolOwner(
expression.startOffset,
expression.endOffset,
implClass.defaultType,
ctor.symbol,
)
newCall.copyTypeAndValueArgumentsFrom(expression)
newCall.transformChildrenVoid() // for annotations in annotations
return newCall
}
private fun createAnnotationImplementation(annotationClass: IrClass): IrClass {
val localDeclarationParent = currentClass?.scope?.getLocalDeclarationParent() as? IrClass
val parentFqName = annotationClass.fqNameWhenAvailable!!.asString().replace('.', '_')
val wrapperName = Name.identifier("annotationImpl\$$parentFqName$0")
val subclass = context.irFactory.buildClass {
name = wrapperName
origin = ANNOTATION_IMPLEMENTATION
// It can be seen from inline functions and multiple classes within one file
// JavaDescriptorVisibilities.PACKAGE_VISIBILITY also can be used here, like in SAM, but that's not a big difference
// since declaration is synthetic anyway
visibility = DescriptorVisibilities.INTERNAL
}.apply {
parent = localDeclarationParent ?: irFile
createImplicitParameterDeclarationWithWrappedDescriptor()
superTypes = listOf(annotationClass.defaultType)
}
val ctor = subclass.addConstructor {
visibility = DescriptorVisibilities.PUBLIC
}
val (originalProps, implementationProps) = implementAnnotationProperties(subclass, annotationClass, ctor)
implementEqualsAndHashCode(annotationClass, subclass, originalProps, implementationProps)
implementPlatformSpecificParts(annotationClass, subclass)
return subclass
}
fun implementAnnotationProperties(implClass: IrClass, annotationClass: IrClass, generatedConstructor: IrConstructor): Pair<List<IrProperty>, List<IrProperty>> {
val ctorBody = context.irFactory.createBlockBody(
UNDEFINED_OFFSET, UNDEFINED_OFFSET, listOf(
IrDelegatingConstructorCallImpl(
UNDEFINED_OFFSET, UNDEFINED_OFFSET, context.irBuiltIns.unitType, context.irBuiltIns.anyClass.constructors.single(),
typeArgumentsCount = 0, valueArgumentsCount = 0
)
)
)
generatedConstructor.body = ctorBody
val properties = annotationClass.getAnnotationProperties()
return properties to properties.map { property ->
val propType = property.getter!!.returnType
val propName = property.name
val field = context.irFactory.buildField {
name = propName
type = propType
origin = ANNOTATION_IMPLEMENTATION
isFinal = true
visibility = DescriptorVisibilities.PRIVATE
}.also { it.parent = implClass }
val parameter = generatedConstructor.addValueParameter(propName.asString(), propType)
// VALUE_FROM_PARAMETER
val originalParameter = ((property.backingField?.initializer?.expression as? IrGetValue)?.symbol?.owner as? IrValueParameter)
if (originalParameter?.defaultValue != null) {
parameter.defaultValue = originalParameter.defaultValue!!.deepCopyWithVariables().also { it.transformChildrenVoid() }
}
ctorBody.statements += IrSetFieldImpl(
UNDEFINED_OFFSET, UNDEFINED_OFFSET, field.symbol,
IrGetValueImpl(UNDEFINED_OFFSET, UNDEFINED_OFFSET, implClass.thisReceiver!!.symbol),
IrGetValueImpl(UNDEFINED_OFFSET, UNDEFINED_OFFSET, parameter.symbol),
context.irBuiltIns.unitType,
)
val prop = implClass.addProperty {
name = propName
isVar = false
origin = ANNOTATION_IMPLEMENTATION
}.apply {
backingField = field
parent = implClass
}
prop.addGetter {
name = propName // Annotation value getter should be named 'x', not 'getX'
returnType = propType.kClassToJClassIfNeeded() // On JVM, annotation store j.l.Class even if declared with KClass
origin = ANNOTATION_IMPLEMENTATION
visibility = DescriptorVisibilities.PUBLIC
modality = Modality.FINAL
}.apply {
dispatchReceiverParameter = implClass.thisReceiver!!.copyTo(this)
body = context.createIrBuilder(symbol).irBlockBody {
var value: IrExpression = irGetField(irGet(dispatchReceiverParameter!!), field)
if (propType.isKClass()) value = this.kClassExprToJClassIfNeeded(value)
+irReturn(value)
}
}
prop
}
}
fun IrClass.getAnnotationProperties(): List<IrProperty> {
// For some weird reason, annotations defined in other IrFiles, do not have IrProperties in declarations.
// (although annotations imported from Java do have)
val props = declarations.filterIsInstance<IrProperty>()
if (props.isNotEmpty()) return props
return declarations.filterIsInstance<IrSimpleFunction>().filter { it.origin == IrDeclarationOrigin.DEFAULT_PROPERTY_ACCESSOR }
.mapNotNull { it.correspondingPropertySymbol?.owner }
}
open fun IrType.kClassToJClassIfNeeded(): IrType = this
open fun IrBuilderWithScope.kClassExprToJClassIfNeeded(irExpression: IrExpression): IrExpression = irExpression
open fun generatedEquals(irBuilder: IrBlockBodyBuilder, type: IrType, arg1: IrExpression, arg2: IrExpression): IrExpression =
irBuilder.irEquals(arg1, arg2)
@Suppress("UNUSED_VARIABLE")
fun implementEqualsAndHashCode(annotationClass: IrClass, implClass: IrClass, originalProps: List<IrProperty>, childProps: List<IrProperty>) {
val creator = MethodsFromAnyGeneratorForLowerings(context, implClass, ANNOTATION_IMPLEMENTATION)
val generator =
creator.LoweringDataClassMemberGenerator(
nameForToString = "@" + annotationClass.fqNameWhenAvailable!!.asString(),
typeForEquals = annotationClass.defaultType
) { type, a, b ->
generatedEquals(this, type, a, b)
}
// Manual implementation of equals is required for two reasons:
// 1. `other` should be casted to interface instead of implementation
// 2. Properties should be retrieved using getters without accessing backing fields
// (DataClassMembersGenerator typically tries to access fields)
val eqFun = creator.createEqualsMethodDeclaration()
generator.generateEqualsUsingGetters(eqFun, annotationClass.defaultType, originalProps)
val hcFun = creator.createHashCodeMethodDeclaration()
generator.generateHashCodeMethod(hcFun, childProps)
val toStringFun = creator.createToStringMethodDeclaration()
generator.generateToStringMethod(toStringFun, childProps)
}
open fun implementPlatformSpecificParts(annotationClass: IrClass, implClass: IrClass) {}
}

View File

@@ -0,0 +1,121 @@
/*
* 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.backend.common.lower
import org.jetbrains.kotlin.backend.common.BackendContext
import org.jetbrains.kotlin.descriptors.FunctionDescriptor
import org.jetbrains.kotlin.descriptors.TypeParameterDescriptor
import org.jetbrains.kotlin.descriptors.ValueParameterDescriptor
import org.jetbrains.kotlin.ir.builders.*
import org.jetbrains.kotlin.ir.builders.declarations.addFunction
import org.jetbrains.kotlin.ir.builders.declarations.addValueParameter
import org.jetbrains.kotlin.ir.declarations.*
import org.jetbrains.kotlin.ir.expressions.IrExpression
import org.jetbrains.kotlin.ir.expressions.IrMemberAccessExpression
import org.jetbrains.kotlin.ir.symbols.IrSimpleFunctionSymbol
import org.jetbrains.kotlin.ir.types.IrType
import org.jetbrains.kotlin.ir.types.getClass
import org.jetbrains.kotlin.ir.types.isArray
import org.jetbrains.kotlin.ir.util.DataClassMembersGenerator
import org.jetbrains.kotlin.ir.util.functions
import org.jetbrains.kotlin.ir.util.isPrimitiveArray
class MethodsFromAnyGeneratorForLowerings(val context: BackendContext, val irClass: IrClass, val origin: IrDeclarationOrigin) {
fun createToStringMethodDeclaration(): IrSimpleFunction = irClass.addFunction("toString", context.irBuiltIns.stringType).apply {
overriddenSymbols = irClass.collectOverridenSymbols { it.isToString() }
}
fun createHashCodeMethodDeclaration(): IrSimpleFunction = irClass.addFunction("hashCode", context.irBuiltIns.intType).apply {
overriddenSymbols = irClass.collectOverridenSymbols { it.isHashCode() }
}
fun createEqualsMethodDeclaration(): IrSimpleFunction = irClass.addFunction("equals", context.irBuiltIns.booleanType).apply {
overriddenSymbols = irClass.collectOverridenSymbols { it.isEquals(context) }
addValueParameter("other", context.irBuiltIns.anyNType)
}
inner class LoweringDataClassMemberGenerator(
val nameForToString: String,
val typeForEquals: IrType,
val selectEquals: IrBlockBodyBuilder.(IrType, IrExpression, IrExpression) -> IrExpression,
) :
DataClassMembersGenerator(
IrGeneratorContextBase(context.irBuiltIns),
context.ir.symbols.externalSymbolTable,
irClass,
origin
) {
override fun declareSimpleFunction(startOffset: Int, endOffset: Int, functionDescriptor: FunctionDescriptor): IrFunction {
error("Descriptor API shouldn't be used in lowerings")
}
override fun generateSyntheticFunctionParameterDeclarations(irFunction: IrFunction) {
// no-op — irFunction from lowering should already have necessary parameters
}
override fun getProperty(parameter: ValueParameterDescriptor?, irValueParameter: IrValueParameter?): IrProperty? {
error("Descriptor API shouldn't be used in lowerings")
}
override fun transform(typeParameterDescriptor: TypeParameterDescriptor): IrType {
error("Descriptor API shouldn't be used in lowerings")
}
override fun getHashCodeFunctionInfo(type: IrType): HashCodeFunctionInfo {
val symbol = if (type.isArray() || type.isPrimitiveArray()) {
context.irBuiltIns.dataClassArrayMemberHashCodeSymbol
} else {
context.irBuiltIns.anyClass.functions.single { it.owner.name.asString() == "hashCode" }
}
return object : HashCodeFunctionInfo {
override val symbol: IrSimpleFunctionSymbol = symbol
override fun commitSubstituted(irMemberAccessExpression: IrMemberAccessExpression<*>) {}
}
}
override fun IrClass.classNameForToString(): String = nameForToString
fun generateEqualsUsingGetters(equalsFun: IrSimpleFunction, typeForEquals: IrType, properties: List<IrProperty>) = equalsFun.apply {
body = this@MethodsFromAnyGeneratorForLowerings.context.createIrBuilder(symbol).irBlockBody {
val irType = typeForEquals
fun irOther() = irGet(valueParameters[0])
fun irThis() = irGet(dispatchReceiverParameter!!)
fun IrProperty.get(receiver: IrExpression) = irCall(getter!!).apply {
dispatchReceiver = receiver
}
+irIfThenReturnFalse(irNotIs(irOther(), irType))
val otherWithCast = irTemporary(irAs(irOther(), irType), "other_with_cast")
for (property in properties) {
val arg1 = property.get(irThis())
val arg2 = property.get(irGet(irType, otherWithCast.symbol))
+irIfThenReturnFalse(irNot(selectEquals(property.getter?.returnType ?: property.backingField!!.type, arg1, arg2)))
}
+irReturnTrue()
}
}
}
companion object {
fun IrFunction.isToString(): Boolean =
name.asString() == "toString" && extensionReceiverParameter == null && valueParameters.isEmpty()
fun IrFunction.isHashCode() =
name.asString() == "hashCode" && extensionReceiverParameter == null && valueParameters.isEmpty()
fun IrFunction.isEquals(context: BackendContext) =
name.asString() == "equals" &&
extensionReceiverParameter == null &&
valueParameters.singleOrNull()?.type == context.irBuiltIns.anyNType
fun IrClass.collectOverridenSymbols(predicate: (IrFunction) -> Boolean): List<IrSimpleFunctionSymbol> =
superTypes.mapNotNull { it.getClass()?.functions?.singleOrNull(predicate)?.symbol }
}
}

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2010-2020 JetBrains s.r.o. and Kotlin Programming Language contributors.
* 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.
*/
@@ -12,6 +12,7 @@ import org.jetbrains.kotlin.backend.common.ScopeWithIr
import org.jetbrains.kotlin.backend.common.ir.addFakeOverrides
import org.jetbrains.kotlin.backend.common.ir.copyTo
import org.jetbrains.kotlin.backend.common.ir.createImplicitParameterDeclarationWithWrappedDescriptor
import org.jetbrains.kotlin.backend.common.lower.MethodsFromAnyGeneratorForLowerings.Companion.isHashCode
import org.jetbrains.kotlin.descriptors.ClassKind
import org.jetbrains.kotlin.descriptors.DescriptorVisibilities
import org.jetbrains.kotlin.descriptors.DescriptorVisibility
@@ -273,8 +274,9 @@ class SamEqualsHashCodeMethodsGenerator(
fun generate() {
generateGetFunctionDelegate()
generateEquals()
generateHashCode()
val anyGenerator = MethodsFromAnyGeneratorForLowerings(context, klass, IrDeclarationOrigin.SYNTHETIC_GENERATED_SAM_IMPLEMENTATION)
generateEquals(anyGenerator)
generateHashCode(anyGenerator)
}
private fun generateGetFunctionDelegate() {
@@ -286,17 +288,9 @@ class SamEqualsHashCodeMethodsGenerator(
}
}
private fun generateEquals() {
klass.addFunction("equals", builtIns.booleanType).apply {
overriddenSymbols = klass.superTypes.mapNotNull {
it.getClass()?.functions?.singleOrNull {
it.name.asString() == "equals" &&
it.extensionReceiverParameter == null &&
it.valueParameters.singleOrNull()?.type == builtIns.anyNType
}?.symbol
}
val other = addValueParameter("other", builtIns.anyNType)
private fun generateEquals(anyGenerator: MethodsFromAnyGeneratorForLowerings) {
anyGenerator.createEqualsMethodDeclaration().apply {
val other = valueParameters[0]
body = context.createIrBuilder(symbol).run {
irExprBody(
irIfThenElse(
@@ -322,16 +316,9 @@ class SamEqualsHashCodeMethodsGenerator(
}
}
private fun generateHashCode() {
klass.addFunction("hashCode", builtIns.intType).apply {
fun isHashCode(function: IrSimpleFunction) =
function.name.asString() == "hashCode" && function.extensionReceiverParameter == null && function.valueParameters.isEmpty()
overriddenSymbols = klass.superTypes.mapNotNull {
it.getClass()?.functions?.singleOrNull(::isHashCode)?.symbol
}
val hashCode = context.irBuiltIns.functionClass.owner.functions.single(::isHashCode).symbol
private fun generateHashCode(anyGenerator: MethodsFromAnyGeneratorForLowerings) {
anyGenerator.createHashCodeMethodDeclaration().apply {
val hashCode = context.irBuiltIns.functionClass.owner.functions.single{ it.isHashCode() }.symbol
body = context.createIrBuilder(symbol).run {
irExprBody(
irCall(hashCode).also {

View File

@@ -6,11 +6,10 @@
package org.jetbrains.kotlin.ir.backend.js
import org.jetbrains.kotlin.builtins.PrimitiveType
import org.jetbrains.kotlin.ir.ObsoleteDescriptorBasedAPI
import org.jetbrains.kotlin.ir.IrBuiltIns
import org.jetbrains.kotlin.ir.declarations.IrFunction
import org.jetbrains.kotlin.ir.declarations.IrProperty
import org.jetbrains.kotlin.ir.declarations.IrSimpleFunction
import org.jetbrains.kotlin.ir.descriptors.IrBuiltInsOverDescriptors
import org.jetbrains.kotlin.ir.symbols.IrSimpleFunctionSymbol
import org.jetbrains.kotlin.ir.types.isLong
import org.jetbrains.kotlin.ir.util.constructors
@@ -22,8 +21,7 @@ import org.jetbrains.kotlin.psi2ir.findSingleFunction
import org.jetbrains.kotlin.util.capitalizeDecapitalize.toLowerCaseAsciiOnly
import java.util.*
@OptIn(ObsoleteDescriptorBasedAPI::class)
class JsIntrinsics(private val irBuiltIns: IrBuiltInsOverDescriptors, val context: JsIrBackendContext) {
class JsIntrinsics(private val irBuiltIns: IrBuiltIns, val context: JsIrBackendContext) {
// TODO: Should we drop operator intrinsics in favor of IrDynamicOperatorExpression?

View File

@@ -25,7 +25,6 @@ import org.jetbrains.kotlin.ir.builders.declarations.addFunction
import org.jetbrains.kotlin.ir.declarations.*
import org.jetbrains.kotlin.ir.declarations.impl.IrExternalPackageFragmentImpl
import org.jetbrains.kotlin.ir.declarations.impl.IrFileImpl
import org.jetbrains.kotlin.ir.descriptors.IrBuiltInsOverDescriptors
import org.jetbrains.kotlin.ir.expressions.IrCall
import org.jetbrains.kotlin.ir.symbols.IrClassSymbol
import org.jetbrains.kotlin.ir.symbols.IrClassifierSymbol
@@ -178,8 +177,7 @@ class JsIrBackendContext(
private val coroutineIntrinsicsPackage = module.getPackage(COROUTINE_INTRINSICS_PACKAGE_FQNAME)
val dynamicType: IrDynamicType = IrDynamicTypeImpl(null, emptyList(), Variance.INVARIANT)
@OptIn(ObsoleteDescriptorBasedAPI::class)
val intrinsics = JsIntrinsics(irBuiltIns as IrBuiltInsOverDescriptors, this)
val intrinsics = JsIntrinsics(irBuiltIns, this)
override val sharedVariablesManager = JsSharedVariablesManager(this)

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2010-2020 JetBrains s.r.o. and Kotlin Programming Language contributors.
* 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.
*/
@@ -324,6 +324,7 @@ private val jvmFilePhases = listOf(
inventNamesForLocalClassesPhase,
kCallableNamePropertyPhase,
annotationPhase,
annotationImplementationPhase,
polymorphicSignaturePhase,
varargPhase,

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2010-2019 JetBrains s.r.o. and Kotlin Programming Language contributors.
* 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.
*/
@@ -802,19 +802,30 @@ class JvmSymbols(
}
}
private fun IrClass.addArraysEqualsFunction(arrayType: IrSimpleType) {
addFunction("equals", irBuiltIns.booleanType, isStatic = true).apply {
addValueParameter("a", arrayType)
addValueParameter("b", arrayType)
}
}
val arraysClass: IrClassSymbol =
createClass(FqName("java.util.Arrays")) { irClass ->
irClass.addArraysCopyOfFunction(booleanArrayType)
irClass.addArraysCopyOfFunction(byteArrayType)
irClass.addArraysCopyOfFunction(charArrayType)
irClass.addArraysCopyOfFunction(shortArrayType)
irClass.addArraysCopyOfFunction(intArrayType)
irClass.addArraysCopyOfFunction(longArrayType)
irClass.addArraysCopyOfFunction(floatArrayType)
irClass.addArraysCopyOfFunction(doubleArrayType)
// public static <T> T[] copyOf(T[] original, int newLength)
irClass.addArraysCopyOfFunction(arrayOfAnyNType)
for (type in listOf(
booleanArrayType,
byteArrayType,
charArrayType,
shortArrayType,
intArrayType,
longArrayType,
floatArrayType,
doubleArrayType,
arrayOfAnyNType
)) {
irClass.addArraysCopyOfFunction(type)
irClass.addArraysEqualsFunction(type)
}
}
fun getArraysCopyOfFunction(arrayType: IrSimpleType): IrSimpleFunctionSymbol {

View File

@@ -52,6 +52,7 @@ class ConstLowering(val context: JvmBackendContext) : IrElementTransformerVoid()
private fun IrExpression.lowerConstRead(receiver: IrExpression?, field: IrField?): IrExpression? {
val value = field?.constantValue() ?: return null
transformChildrenVoid()
val resultExpression = if (context.state.shouldInlineConstVals)
value.copyWithOffsets(startOffset, endOffset)
else

View File

@@ -0,0 +1,88 @@
/*
* Copyright 2010-2021 JetBrains s.r.o. and Kotlin Programming Language contributors.
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
*/
package org.jetbrains.kotlin.backend.jvm.lower
import org.jetbrains.kotlin.backend.common.lower.ANNOTATION_IMPLEMENTATION
import org.jetbrains.kotlin.backend.common.lower.AnnotationImplementationLowering
import org.jetbrains.kotlin.backend.common.lower.AnnotationImplementationTransformer
import org.jetbrains.kotlin.backend.common.phaser.makeIrFilePhase
import org.jetbrains.kotlin.backend.jvm.JvmBackendContext
import org.jetbrains.kotlin.backend.jvm.ir.createJvmIrBuilder
import org.jetbrains.kotlin.backend.jvm.lower.FunctionReferenceLowering.Companion.javaClassReference
import org.jetbrains.kotlin.ir.builders.*
import org.jetbrains.kotlin.ir.builders.declarations.addFunction
import org.jetbrains.kotlin.ir.declarations.IrClass
import org.jetbrains.kotlin.ir.declarations.IrFile
import org.jetbrains.kotlin.ir.declarations.IrFunction
import org.jetbrains.kotlin.ir.expressions.IrExpression
import org.jetbrains.kotlin.ir.types.*
import org.jetbrains.kotlin.ir.util.defaultType
import org.jetbrains.kotlin.ir.util.findDeclaration
import org.jetbrains.kotlin.ir.util.isPrimitiveArray
import org.jetbrains.kotlin.ir.util.render
internal val annotationImplementationPhase = makeIrFilePhase<JvmBackendContext>(
{ ctxt -> AnnotationImplementationLowering { JvmAnnotationImplementationTransformer(ctxt, it) } },
name = "AnnotationImplementation",
description = "Create synthetic annotations implementations and use them in annotations constructor calls"
)
class JvmAnnotationImplementationTransformer(val jvmContext: JvmBackendContext, file: IrFile) :
AnnotationImplementationTransformer(jvmContext, file) {
override fun IrType.kClassToJClassIfNeeded(): IrType = when {
this.isKClass() -> jvmContext.ir.symbols.javaLangClass.starProjectedType
this.isKClassArray() -> jvmContext.irBuiltIns.arrayClass.typeWith(
jvmContext.ir.symbols.javaLangClass.starProjectedType
)
else -> this
}
private fun IrType.isKClassArray() =
this is IrSimpleType && isArray() && arguments.single().typeOrNull?.isKClass() == true
override fun IrBuilderWithScope.kClassExprToJClassIfNeeded(irExpression: IrExpression): IrExpression {
with(this) {
return irGet(
jvmContext.ir.symbols.javaLangClass.starProjectedType,
null,
jvmContext.ir.symbols.kClassJava.owner.getter!!.symbol
).apply {
extensionReceiver = irExpression
}
}
}
override fun generatedEquals(irBuilder: IrBlockBodyBuilder, type: IrType, arg1: IrExpression, arg2: IrExpression): IrExpression {
return if (type.isArray() || type.isPrimitiveArray()) {
val targetType = if (type.isPrimitiveArray()) type else jvmContext.ir.symbols.arrayOfAnyNType
val requiredSymbol = jvmContext.ir.symbols.arraysClass.owner.findDeclaration<IrFunction> {
it.name.asString() == "equals" && it.valueParameters.size == 2 && it.valueParameters.first().type == targetType
}
requireNotNull(requiredSymbol) { "Can't find Arrays.equals method for type ${targetType.render()}" }
irBuilder.irCall(
requiredSymbol.symbol
).apply {
putValueArgument(0, arg1)
putValueArgument(1, arg2)
}
} else super.generatedEquals(irBuilder, type, arg1, arg2)
}
override fun implementPlatformSpecificParts(annotationClass: IrClass, implClass: IrClass) {
implClass.addFunction(
name = "annotationType",
returnType = jvmContext.ir.symbols.javaLangClass.starProjectedType,
origin = ANNOTATION_IMPLEMENTATION,
isStatic = false
).apply {
body = jvmContext.createJvmIrBuilder(symbol).run {
irBlockBody {
+irReturn(javaClassReference(annotationClass.defaultType))
}
}
}
}
}

View File

@@ -424,7 +424,10 @@ private class JvmInlineClassLowering(private val context: JvmBackendContext) : F
override fun visitGetField(expression: IrGetField): IrExpression {
val field = expression.symbol.owner
val parent = field.parent
if (parent is IrClass && parent.isInline && field.name == parent.inlineClassFieldName) {
if (field.origin == IrDeclarationOrigin.PROPERTY_BACKING_FIELD &&
parent is IrClass &&
parent.isInline &&
field.name == parent.inlineClassFieldName) {
val receiver = expression.receiver!!.transform(this, null)
return coerceInlineClasses(receiver, receiver.type, field.type)
}

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2010-2020 JetBrains s.r.o. and Kotlin Programming Language contributors.
* 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.
*/
@@ -16,9 +16,7 @@ import org.jetbrains.kotlin.ir.expressions.IrMemberAccessExpression
import org.jetbrains.kotlin.ir.expressions.impl.IrGetValueImpl
import org.jetbrains.kotlin.ir.expressions.mapTypeParameters
import org.jetbrains.kotlin.ir.expressions.mapValueParameters
import org.jetbrains.kotlin.ir.symbols.IrClassifierSymbol
import org.jetbrains.kotlin.ir.symbols.IrConstructorSymbol
import org.jetbrains.kotlin.ir.symbols.IrSimpleFunctionSymbol
import org.jetbrains.kotlin.ir.symbols.*
import org.jetbrains.kotlin.ir.symbols.impl.IrVariableSymbolImpl
import org.jetbrains.kotlin.ir.types.IrType
import org.jetbrains.kotlin.ir.types.classifierOrNull
@@ -34,7 +32,7 @@ import org.jetbrains.kotlin.name.Name
@OptIn(ObsoleteDescriptorBasedAPI::class)
abstract class DataClassMembersGenerator(
val context: IrGeneratorContext,
val symbolTable: SymbolTable,
val symbolTable: ReferenceSymbolTable,
val irClass: IrClass,
val origin: IrDeclarationOrigin
) {
@@ -43,7 +41,7 @@ abstract class DataClassMembersGenerator(
inline fun <T : IrDeclaration> T.buildWithScope(builder: (T) -> Unit): T =
also { irDeclaration ->
symbolTable.withScope(irDeclaration) {
symbolTable.withReferenceScope(irDeclaration) {
builder(irDeclaration)
}
}
@@ -206,7 +204,7 @@ abstract class DataClassMembersGenerator(
fun generateToStringMethodBody(properties: List<IrProperty>) {
val irConcat = irConcat()
irConcat.addArgument(irString(irClass.name.asString() + "("))
irConcat.addArgument(irString(irClass.classNameForToString() + "("))
var first = true
for (property in properties) {
if (!first) irConcat.addArgument(irString(", "))
@@ -362,4 +360,6 @@ abstract class DataClassMembersGenerator(
generateToStringMethodBody(properties)
}
}
open fun IrClass.classNameForToString(): String = irClass.name.asString()
}

View File

@@ -8,7 +8,6 @@ package org.jetbrains.kotlin.backend.common.serialization
import org.jetbrains.kotlin.backend.common.serialization.encodings.BinarySymbolData
import org.jetbrains.kotlin.descriptors.ModuleDescriptor
import org.jetbrains.kotlin.ir.IrBuiltIns
import org.jetbrains.kotlin.ir.ObsoleteDescriptorBasedAPI
import org.jetbrains.kotlin.ir.declarations.*
import org.jetbrains.kotlin.ir.symbols.*
import org.jetbrains.kotlin.ir.util.IdSignature
@@ -94,7 +93,6 @@ abstract class IrModuleDeserializer(val moduleDescriptor: ModuleDescriptor, val
}
// Used to resolve built in symbols like `kotlin.ir.internal.*` or `kotlin.FunctionN`
@OptIn(ObsoleteDescriptorBasedAPI::class)
class IrModuleDeserializerWithBuiltIns(
private val builtIns: IrBuiltIns,
private val delegate: IrModuleDeserializer

View File

@@ -308,7 +308,6 @@ abstract class KotlinIrLinker(
return deserializerForModule.moduleFragment
}
@OptIn(ObsoleteDescriptorBasedAPI::class)
private fun maybeWrapWithBuiltInAndInit(
moduleDescriptor: ModuleDescriptor,
moduleDeserializer: IrModuleDeserializer

View File

@@ -15,11 +15,3 @@ dependencies {
sourceSets {
"main" { projectDefault() }
}
tasks {
val compileKotlin by existing(org.jetbrains.kotlin.gradle.tasks.KotlinCompile::class) {
kotlinOptions {
freeCompilerArgs += "-Xopt-in=org.jetbrains.kotlin.ir.ObsoleteDescriptorBasedAPI"
}
}
}

View File

@@ -0,0 +1,53 @@
// IGNORE_BACKEND_FIR: JVM_IR
// TARGET_BACKEND: JVM_IR
// WITH_RUNTIME
// !LANGUAGE: +InstantiationOfAnnotationClasses
// FILE: a.kt
package test
annotation class A1
annotation class A2
fun interface I {
fun run(): A1
}
// FILE: test.kt
package test
class E {
fun insideClass(): A1 = A1()
fun insideLammbda(): A1 = run { A1() }
fun insideSAM(): I = I { A1() }
}
class G {
// test that we can reuse instance in different classes from same file
fun insideClassAgain(): A1 = A1()
}
fun outsideClass(): A2 = A2()
fun test(instance: Any, parent: String, fqa: String) {
val clz = instance.javaClass
assert(clz.getName().startsWith(parent))
assert(clz.getName().contains(fqa))
assert(clz.getEnclosingMethod() == null)
assert(clz.getEnclosingClass().getName() == parent)
// SAM treated as anonymous because of Origin or something else, see ClassCodegen#IrClass.isAnonymousInnerClass
// assert(clz.getDeclaringClass() == null)
}
fun box(): String {
test(E().insideClass(), "test.E", "test_A1")
test(E().insideLammbda(), "test.E", "test_A1")
test(E().insideSAM().run(), "test.E", "test_A1")
test(G().insideClassAgain(), "test.E", "test_A1")
test(outsideClass(), "test.TestKt", "test_A2")
return "OK"
}

View File

@@ -0,0 +1,30 @@
// IGNORE_BACKEND_FIR: JVM_IR
// TARGET_BACKEND: JVM_IR
// WITH_RUNTIME
// !LANGUAGE: +InstantiationOfAnnotationClasses
import kotlin.reflect.KClass
annotation class Bar(val i:Int, val s: String, val f: Float)
annotation class Foo(
val int: Int,
val s: String,
val arr: Array<String>,
val arr2: IntArray,
val kClass: KClass<*>,
val bar: Bar
)
data class BarLike(val i:Int, val s: String, val f: Float)
fun box(): String {
val foo1 = Foo(42, "foo", arrayOf("a", "b"), intArrayOf(1,2), Bar::class, Bar(10, "bar", Float.NaN))
val foo2 = Foo(42, "foo", arrayOf("a", "b"), intArrayOf(1,2), Bar::class, Bar(10, "bar", Float.NaN))
if (foo1 != foo2) return "Failed equals"
val barlike = BarLike(10, "bar", Float.NaN)
if (barlike.hashCode() != foo1.bar.hashCode()) return "Failed HC1"
if (barlike.hashCode() != foo2.bar.hashCode()) return "Failed HC2"
return "OK"
}

View File

@@ -0,0 +1,70 @@
// IGNORE_BACKEND_FIR: JVM_IR
// TARGET_BACKEND: JVM_IR
// WITH_RUNTIME
// !LANGUAGE: +InstantiationOfAnnotationClasses
// note: taken from ../parameters.kt and ../parametersWithPrimitiveValues.kt
import kotlin.reflect.KClass
import kotlin.test.assertEquals
enum class E { E0 }
annotation class Empty
annotation class A(
val b: Byte,
val s: Short,
val i: Int,
val f: Float,
val d: Double,
val l: Long,
val c: Char,
val bool: Boolean
)
@Retention(AnnotationRetention.RUNTIME)
annotation class Anno(
val s: String,
val i: Int,
val f: Double,
val u: UInt,
val e: E,
val a: A,
val k: KClass<*>,
val arr: Array<String>,
val intArr: IntArray,
val arrOfE: Array<E>,
val arrOfA: Array<Empty>,
val arrOfK: Array<KClass<*>>
)
fun box(): String {
val anno = Anno(
"OK", 42, 2.718281828, 43u, E.E0,
A(1, 1, 1, 1.0.toFloat(), 1.0, 1, 'c', true),
A::class, emptyArray(), intArrayOf(1, 2), arrayOf(E.E0), arrayOf(Empty()), arrayOf(E::class, Empty::class)
)
assertEquals(anno.s, "OK")
assertEquals(anno.i, 42)
assert(anno.f > 2.0 && anno.f < 3.0)
assertEquals(anno.u, 43u)
assertEquals(anno.e, E.E0)
assert(anno.a is A)
assert(anno.k == A::class)
assert(anno.arr.isEmpty())
assert(anno.intArr.contentEquals(intArrayOf(1, 2)))
assert(anno.arrOfE.contentEquals(arrayOf(E.E0)))
assert(anno.arrOfA.size == 1)
// assert(anno.arrOfK.size == 2) TODO(KT-47703): Array<KClass> to Array<j.l.Class> conversion
val ann = anno.a
assertEquals(ann.b, 1.toByte())
assertEquals(ann.s, 1.toShort())
assertEquals(ann.i, 1)
assertEquals(ann.f, 1.toFloat())
assertEquals(ann.d, 1.0)
assertEquals(ann.l, 1.toLong())
assertEquals(ann.c, 'c')
assert(ann.bool)
return "OK"
}

View File

@@ -0,0 +1,38 @@
// IGNORE_BACKEND_FIR: JVM_IR
// TARGET_BACKEND: JVM_IR
// WITH_RUNTIME
// !LANGUAGE: +InstantiationOfAnnotationClasses
package test
import kotlin.reflect.KClass
enum class E { A, B }
annotation class A()
annotation class B(val a: A = A())
annotation class C(
val i: Int = 42,
val b: B = B(),
val kClass: KClass<*> = B::class,
val e: E = E.B,
val aS: Array<String> = arrayOf("a", "b"),
val aI: IntArray = intArrayOf(1, 2)
)
annotation class Partial(
val i: Int = 42,
val s: String = "foo",
val e: E = E.A
)
fun box(): String {
val c = C()
assert(c.toString() == "@test.C(i=42, b=@test.B(a=@test.A()), kClass=interface test.B (Kotlin reflection is not available), e=B, aS=[a, b], aI=[1, 2])")
val p = Partial(e = E.B, s = "bar")
assert(p.toString() == "@test.Partial(i=42, s=bar, e=B)")
return "OK"
}

View File

@@ -0,0 +1,50 @@
// IGNORE_BACKEND_FIR: JVM_IR
// TARGET_BACKEND: JVM_IR
// WITH_RUNTIME
// !LANGUAGE: +InstantiationOfAnnotationClasses
package test
import kotlin.reflect.KClass
enum class E { E0 }
annotation class Empty
annotation class A(
val b: Byte,
val s: Short,
val i: Int,
val f: Float,
val d: Double,
val l: Long,
val c: Char,
val bool: Boolean
)
@Retention(AnnotationRetention.RUNTIME)
annotation class Anno(
val s: String,
val i: Int,
val f: Double,
val u: UInt,
val e: E,
val a: A,
val k: KClass<*>,
val arr: Array<String>,
val intArr: IntArray,
val arrOfE: Array<E>,
val arrOfA: Array<Empty>,
)
fun box(): String {
val anno = Anno(
"OK", 42, 2.718281828, 43u, E.E0,
A(1, 1, 1, 1.0.toFloat(), 1.0, 1, 'c', true),
A::class, emptyArray(), intArrayOf(1, 2), arrayOf(E.E0), arrayOf(Empty())
)
val s = anno.toString()
val target = "@test.Anno(s=OK, i=42, f=2.718281828, u=43, e=E0, a=@test.A(b=1, s=1, i=1, f=1.0, d=1.0, l=1, c=c, bool=true), " +
"k=interface test.A (Kotlin reflection is not available), arr=[], intArr=[1, 2], arrOfE=[E0], arrOfA=[@test.Empty()])"
return if (s == target) "OK" else "FAILED, got string $s"
}

View File

@@ -0,0 +1,18 @@
// IGNORE_BACKEND_FIR: JVM_IR
// TARGET_BACKEND: JVM_IR
// WITH_RUNTIME
// !LANGUAGE: +InstantiationOfAnnotationClasses
annotation class Foo(
val int: Int,
)
fun box(): String {
val foo = Foo(42)
val jClass = (foo as java.lang.annotation.Annotation).annotationType()
val kClass = foo.annotationClass
if (kClass != Foo::class) return "FAIL $kClass"
if (jClass != Foo::class.java) return "FAIL $jClass"
return "OK"
}

View File

@@ -0,0 +1,44 @@
// IGNORE_BACKEND_FIR: JVM_IR
// TARGET_BACKEND: JVM_IR
// WITH_RUNTIME
// !LANGUAGE: +InstantiationOfAnnotationClasses
// FILE: A.java
public @interface A {}
// FILE: B.java
public @interface B {
String value();
}
// FILE: C.java
public @interface C {
int[] v1();
String v2();
}
// FILE: D.java
public @interface D {
String value() default "hello";
}
// FILE: b.kt
fun box(): String {
val a = A()
val b = B("OK")
assert(b.value == "OK")
val c = C(v2 = "v2", v1 = intArrayOf(1))
assert(c.v2 == "v2")
// TODO(KT-47702): Looks like we have to force users either to pass default java parameters explicitly
// or hack LazyJavaClassDescriptor/JavaPropertyDescriptor to load annotation param default value,
// because it is not stored currently anywhere.
// val d = D()
val d = D("OK").value
return d
}

View File

@@ -0,0 +1,26 @@
// IGNORE_BACKEND_FIR: JVM_IR
// TARGET_BACKEND: JVM_IR
// WITH_RUNTIME
// !LANGUAGE: +InstantiationOfAnnotationClasses
// FILE: a.kt
package a
annotation class A(val i: Int)
fun createInOtherFile(): A = A(10)
// FILE: b.kt
import a.*
fun here(): A = A(10)
fun box(): String {
if (here() != createInOtherFile()) return "Fail equals"
if (here().hashCode() != createInOtherFile().hashCode()) return "Fail hashCode"
if (here().toString() != createInOtherFile().toString()) return "Fail toString"
return "OK"
}

View File

@@ -0,0 +1,42 @@
// IGNORE_BACKEND_FIR: JVM_IR
// TARGET_BACKEND: JVM_IR
// IGNORE_DEXING
// WITH_RUNTIME
// !LANGUAGE: +InstantiationOfAnnotationClasses
// MODULE: lib
// FILE: lib.kt
package a
annotation class A(val i: Int)
inline fun foo(i: Int): A = A(i)
inline fun bar(f: () -> Int): A = A(f())
// MODULE: app(lib)
// FILE: app.kt
package test
import a.*
class C {
fun one(): A = foo(1)
fun two(): A = bar { 2 }
}
fun box(): String {
val one = C().one()
val two = C().two()
assert(one.i == 1)
assert(two.i == 2)
// Just like SAM wrappers, annotation implementation classes should be copied from inline functions
// into current module to avoid compatibility problems when inline fun implementation in origin module
// has changed (e.g. do not instantiate annotation anymore)
assert(one.javaClass.getEnclosingClass().getName() == "test.C")
assert(two.javaClass.getEnclosingClass().getName() == "test.C")
return "OK"
}

View File

@@ -0,0 +1,30 @@
// IGNORE_BACKEND_FIR: JVM_IR
// TARGET_BACKEND: JVM_IR
// WITH_RUNTIME
// !LANGUAGE: +InstantiationOfAnnotationClasses +MultiPlatformProjects
// MODULE: lib
// FILE: common.kt
expect annotation class A(val value: String)
fun createCommon(): A = A("OK")
// FILE: platform.kt
actual annotation class A(actual val value: String)
fun createPlatform(): A = A("OK")
// MODULE: main(lib)
// FILE: main.kt
fun createApp(): A = A("OK")
fun box(): String {
if (createApp().value != "OK") return "FAIL app"
if (createCommon().value != "OK") return "FAIL common"
if (createPlatform().value != "OK") return "FAIL platform"
return "OK"
}

View File

@@ -1,4 +1,3 @@
// IGNORE_BACKEND: JVM
// WITH_RUNTIME
// WITH_COROUTINES
// KT-27830

View File

@@ -1,5 +1,3 @@
// IGNORE_BACKEND: WASM
data class DC(
val d0: String = "", val d1: String = "", val d2: String = "", val d3: String = "", val d4: String = "", val d5: String = "",
val d6: String = "", val d7: String = "", val d8: String = "", val d9: String = "", val d10: String = "", val d11: String = "",

View File

@@ -0,0 +1,11 @@
inline class A(val a: Int = 1) {
companion object {
val a: Int = 2
}
}
fun box(): String {
if (A.a != 2) return "FAIL1"
val instance = A()
return if (instance.a != 1) "FAIL2" else "OK"
}

View File

@@ -0,0 +1,12 @@
// IGNORE_BACKEND: WASM
// WITH_RUNTIME
fun box(): String {
val r =
try {
ULong
} finally {
UInt.MAX_VALUE
}.MAX_VALUE
return if (r == ULong.MAX_VALUE) "OK" else "FAIL"
}

View File

@@ -0,0 +1,41 @@
// IGNORE_BACKEND_FIR: JVM_IR
// TARGET_BACKEND: JVM_IR
// IGNORE_BACKEND_MULTI_MODULE: JVM_MULTI_MODULE_OLD_AGAINST_IR, JVM_MULTI_MODULE_IR_AGAINST_OLD
// WITH_RUNTIME
// !LANGUAGE: +InstantiationOfAnnotationClasses
// IGNORE_DEXING
// TODO: D8 fails with AssertionError and does not print reason, need further investigation
// FILE: 1.kt
package a
annotation class A(val i: Int)
inline fun foo(i: Int): A = A(i)
inline fun bar(f: () -> Int): A = A(f())
// FILE: 2.kt
import a.*
class C {
fun one(): A {
return foo(1)
}
}
fun two(): A {
return bar { 2 }
}
fun box(): String {
val one = C().one()
assert(one.i == 1)
val two = two()
assert(two.i == 2)
// During cross-module inlining, anonymous classes are copied
// println(one.javaClass.getName().startsWith("a._1Kt"))
return "OK"
}

View File

@@ -0,0 +1,35 @@
// IGNORE_BACKEND_FIR: JVM_IR
// TARGET_BACKEND: JVM_IR
// IGNORE_BACKEND_MULTI_MODULE: JVM_MULTI_MODULE_OLD_AGAINST_IR, JVM_MULTI_MODULE_IR_AGAINST_OLD
// WITH_RUNTIME
// !LANGUAGE: +InstantiationOfAnnotationClasses
// IGNORE_DEXING
// TODO: D8 fails with AssertionError and does not print reason, need further investigation
// FILE: 1.kt
package a
annotation class A(val i: String)
interface I {
fun g(): A
}
inline fun foo(i: String): I = object : I {
override fun g(): A {
return A(i)
}
}
// FILE: 2.kt
import a.*
class C() {
fun one(): A = foo("OK").g()
}
fun box(): String {
return C().one().i
}

View File

@@ -0,0 +1,11 @@
// WITH_RUNTIME
// IGNORE_BACKEND: JVM
// !LANGUAGE: +InstantiationOfAnnotationClasses
annotation class Foo(val int: Int)
annotation class Bar
fun box() {
val foo = Foo(42)
}

View File

@@ -0,0 +1,32 @@
@kotlin.Metadata
public synthetic final class AnnotationCtorCallGenerateSyntheticKt$annotationImpl$Foo$0 {
// source: 'annotationCtorCallGenerateSynthetic.kt'
private synthetic final field int: int
public method <init>(p0: int): void
public synthetic final method annotationType(): java.lang.Class
public final method equals(@org.jetbrains.annotations.Nullable p0: java.lang.Object): boolean
public final method hashCode(): int
public synthetic final method int(): int
public final @org.jetbrains.annotations.NotNull method toString(): java.lang.String
public synthetic inner class AnnotationCtorCallGenerateSyntheticKt$annotationImpl$Foo$0
}
@kotlin.Metadata
public final class AnnotationCtorCallGenerateSyntheticKt {
// source: 'annotationCtorCallGenerateSynthetic.kt'
public final static method box(): void
public synthetic inner class AnnotationCtorCallGenerateSyntheticKt$annotationImpl$Foo$0
}
@java.lang.annotation.Retention
@kotlin.Metadata
public annotation class Bar {
// source: 'annotationCtorCallGenerateSynthetic.kt'
}
@java.lang.annotation.Retention
@kotlin.Metadata
public annotation class Foo {
// source: 'annotationCtorCallGenerateSynthetic.kt'
public abstract method int(): int
}

View File

@@ -0,0 +1,10 @@
// WITH_RUNTIME
// !LANGUAGE: +InstantiationOfAnnotationClasses
annotation class Foo(val bar: Bar)
annotation class Bar
@Foo(Bar())
fun box() {
}

View File

@@ -0,0 +1,18 @@
@kotlin.Metadata
public final class AnnotationCtorCallNoSyntheticKt {
// source: 'annotationCtorCallNoSynthetic.kt'
public final static @Foo method box(): void
}
@java.lang.annotation.Retention
@kotlin.Metadata
public annotation class Bar {
// source: 'annotationCtorCallNoSynthetic.kt'
}
@java.lang.annotation.Retention
@kotlin.Metadata
public annotation class Foo {
// source: 'annotationCtorCallNoSynthetic.kt'
public abstract method bar(): Bar
}

View File

@@ -0,0 +1,21 @@
// !DIAGNOSTICS: -UNUSED_VARIABLE
// WITH_RUNTIME
// SKIP_TXT
// !LANGUAGE: +InstantiationOfAnnotationClasses
// FILE: test.kt
import kotlin.reflect.KClass
annotation class A
annotation class B(val int: Int)
annotation class C(val int: Int = 42)
annotation class G<T: Any>(val int: KClass<T>)
fun box() {
val a = <!ANNOTATION_CLASS_CONSTRUCTOR_CALL!>A()<!>
val b = <!ANNOTATION_CLASS_CONSTRUCTOR_CALL!>B(4)<!>
val c = <!ANNOTATION_CLASS_CONSTRUCTOR_CALL!>C()<!>
val foo = <!ANNOTATION_CLASS_CONSTRUCTOR_CALL!>G(Int::class)<!>
}

View File

@@ -0,0 +1,18 @@
// WITH_RUNTIME
// SKIP_TXT
// !LANGUAGE: +InstantiationOfAnnotationClasses
import kotlin.reflect.KClass
annotation class A
annotation class B(val int: Int)
annotation class C(val int: Int = 42)
annotation class G<T: Any>(val int: KClass<T>)
fun box() {
val a = <!ANNOTATION_CLASS_CONSTRUCTOR_CALL!>A()<!>
val b = <!ANNOTATION_CLASS_CONSTRUCTOR_CALL!>B(4)<!>
val c = <!ANNOTATION_CLASS_CONSTRUCTOR_CALL!>C()<!>
val foo = <!ANNOTATION_CLASS_CONSTRUCTOR_CALL!>G(Int::class)<!>
}

View File

@@ -0,0 +1,18 @@
// WITH_RUNTIME
// SKIP_TXT
// !LANGUAGE: +InstantiationOfAnnotationClasses
import kotlin.reflect.KClass
annotation class A
annotation class B(val int: Int)
annotation class C(val int: Int = 42)
annotation class G<T: Any>(val int: KClass<T>)
fun box() {
val a = A()
val b = B(4)
val c = C()
val foo = <!ANNOTATION_CLASS_CONSTRUCTOR_CALL!>G(Int::class)<!>
}

View File

@@ -1,5 +1,6 @@
// FIR_IDENTICAL
//FILE: foo.kt
// LANGUAGE: +WarnAboutNonExhaustiveWhenOnAlgebraicTypes
// FILE: foo.kt
fun main() {
val c: Type
<!NON_EXHAUSTIVE_WHEN_STATEMENT!>when<!> (<!UNINITIALIZED_VARIABLE!>c<!>) {

View File

@@ -1,4 +1,5 @@
// FIR_IDENTICAL
// LANGUAGE: +WarnAboutNonExhaustiveWhenOnAlgebraicTypes
// !DIAGNOSTICS: -UNUSED_VALUE
fun foo(f: Boolean): Int {

View File

@@ -1,3 +1,4 @@
// LANGUAGE: +WarnAboutNonExhaustiveWhenOnAlgebraicTypes
// See also: KT-11998
data class My(val x: Boolean?)

View File

@@ -1,3 +1,4 @@
// LANGUAGE: +WarnAboutNonExhaustiveWhenOnAlgebraicTypes
// See also: KT-11998
data class My(val x: Boolean?)

View File

@@ -1,3 +1,4 @@
// LANGUAGE: +WarnAboutNonExhaustiveWhenOnAlgebraicTypes
/*
* KOTLIN DIAGNOSTICS SPEC TEST (NEGATIVE)
*

View File

@@ -1,3 +1,4 @@
// LANGUAGE: +WarnAboutNonExhaustiveWhenOnAlgebraicTypes
/*
* KOTLIN DIAGNOSTICS SPEC TEST (NEGATIVE)
*

View File

@@ -1,3 +1,4 @@
// LANGUAGE: +WarnAboutNonExhaustiveWhenOnAlgebraicTypes
/*
* KOTLIN DIAGNOSTICS SPEC TEST (NEGATIVE)
*

View File

@@ -1,3 +1,4 @@
// LANGUAGE: +WarnAboutNonExhaustiveWhenOnAlgebraicTypes
/*
* KOTLIN DIAGNOSTICS SPEC TEST (NEGATIVE)
*

View File

@@ -1,4 +1,5 @@
// FIR_IDENTICAL
// LANGUAGE: +WarnAboutNonExhaustiveWhenOnAlgebraicTypes
/*
* KOTLIN DIAGNOSTICS SPEC TEST (NEGATIVE)
*

View File

@@ -1,3 +1,4 @@
// LANGUAGE: +WarnAboutNonExhaustiveWhenOnAlgebraicTypes
/*
* KOTLIN DIAGNOSTICS SPEC TEST (NEGATIVE)
*

View File

@@ -1,3 +1,4 @@
// LANGUAGE: +WarnAboutNonExhaustiveWhenOnAlgebraicTypes
/*
* KOTLIN DIAGNOSTICS SPEC TEST (NEGATIVE)
*

View File

@@ -1,4 +1,5 @@
// FIR_IDENTICAL
// LANGUAGE: +WarnAboutNonExhaustiveWhenOnAlgebraicTypes
/*
* KOTLIN DIAGNOSTICS SPEC TEST (NEGATIVE)
*

View File

@@ -0,0 +1,154 @@
// !LANGUAGE: -WarnAboutNonExhaustiveWhenOnAlgebraicTypes -ProhibitNonExhaustiveWhenOnAlgebraicTypes
enum class SomeEnum {
A, B
}
sealed class Base {
class A : Base()
class B : Base()
}
sealed interface IBase {
interface A : IBase
interface B : IBase
}
// ------------------ not null ------------------
fun test_1(x: SomeEnum) {
<!NON_EXHAUSTIVE_WHEN_STATEMENT!>when<!> (x) {
SomeEnum.A -> ""
}
}
fun test_2(x: Base) {
<!NON_EXHAUSTIVE_WHEN_STATEMENT!>when<!> (x) {
is Base.A -> ""
}
}
fun test_3(x: IBase) {
<!NON_EXHAUSTIVE_WHEN_STATEMENT!>when<!> (x) {
is IBase.A -> ""
}
}
fun test_4(x: Boolean) {
<!NON_EXHAUSTIVE_WHEN_STATEMENT!>when<!> (x) {
true -> ""
}
}
// ------------------ nullable ------------------
fun test_5(x: SomeEnum?) {
<!NON_EXHAUSTIVE_WHEN_STATEMENT!>when<!> (x) {
SomeEnum.A -> ""
SomeEnum.B -> ""
}
<!NON_EXHAUSTIVE_WHEN_STATEMENT!>when<!> (x) {
SomeEnum.A -> ""
null -> ""
}
}
fun test_6(x: Base?) {
<!NON_EXHAUSTIVE_WHEN_STATEMENT!>when<!> (x) {
is Base.A -> ""
is Base.B -> ""
}
<!NON_EXHAUSTIVE_WHEN_STATEMENT!>when<!> (x) {
is Base.A -> ""
null -> ""
}
}
fun test_7(x: IBase?) {
<!NON_EXHAUSTIVE_WHEN_STATEMENT!>when<!> (x) {
is IBase.A -> ""
is IBase.B -> ""
}
<!NON_EXHAUSTIVE_WHEN_STATEMENT!>when<!> (x) {
is IBase.A -> ""
null -> ""
}
}
fun test_8(x: Boolean?) {
<!NON_EXHAUSTIVE_WHEN_STATEMENT!>when<!> (x) {
true -> ""
false -> ""
}
<!NON_EXHAUSTIVE_WHEN_STATEMENT!>when<!> (x) {
true -> ""
null -> ""
}
}
// ------------------ with else ------------------
fun test_9(x: SomeEnum?) {
when (x) {
SomeEnum.A -> ""
else -> ""
}
}
fun test_10(x: Base?) {
when (x) {
is Base.A -> ""
else -> ""
}
}
fun test_11(x: IBase?) {
when (x) {
is IBase.A -> ""
else -> ""
}
}
fun test_12(x: Boolean?) {
when (x) {
true -> ""
else -> ""
}
}
// ------------------ exhaustive ------------------
fun test_13(x: SomeEnum?) {
when (x) {
SomeEnum.A -> ""
SomeEnum.B -> ""
null -> ""
}
}
fun test_14(x: Base?) {
when (x) {
is Base.A -> ""
is Base.B -> ""
null -> ""
}
}
fun test_15(x: IBase?) {
when (x) {
is IBase.A -> ""
is IBase.B -> ""
null -> ""
}
}
fun test_16(x: Boolean?) {
when (x) {
true -> ""
false -> ""
null -> ""
}
}

View File

@@ -0,0 +1,154 @@
// !LANGUAGE: -WarnAboutNonExhaustiveWhenOnAlgebraicTypes -ProhibitNonExhaustiveWhenOnAlgebraicTypes
enum class SomeEnum {
A, B
}
sealed class Base {
class A : Base()
class B : Base()
}
sealed interface IBase {
interface A : IBase
interface B : IBase
}
// ------------------ not null ------------------
fun test_1(x: SomeEnum) {
<!NON_EXHAUSTIVE_WHEN!>when<!> (x) {
SomeEnum.A -> ""
}
}
fun test_2(x: Base) {
<!NON_EXHAUSTIVE_WHEN_ON_SEALED_CLASS!>when<!> (x) {
is Base.A -> ""
}
}
fun test_3(x: IBase) {
<!NON_EXHAUSTIVE_WHEN_ON_SEALED_CLASS!>when<!> (x) {
is IBase.A -> ""
}
}
fun test_4(x: Boolean) {
when (x) {
true -> ""
}
}
// ------------------ nullable ------------------
fun test_5(x: SomeEnum?) {
when (x) {
SomeEnum.A -> ""
SomeEnum.B -> ""
}
<!NON_EXHAUSTIVE_WHEN!>when<!> (x) {
SomeEnum.A -> ""
null -> ""
}
}
fun test_6(x: Base?) {
when (x) {
is Base.A -> ""
is Base.B -> ""
}
<!NON_EXHAUSTIVE_WHEN_ON_SEALED_CLASS!>when<!> (x) {
is Base.A -> ""
null -> ""
}
}
fun test_7(x: IBase?) {
when (x) {
is IBase.A -> ""
is IBase.B -> ""
}
<!NON_EXHAUSTIVE_WHEN_ON_SEALED_CLASS!>when<!> (x) {
is IBase.A -> ""
null -> ""
}
}
fun test_8(x: Boolean?) {
when (x) {
true -> ""
false -> ""
}
when (x) {
true -> ""
null -> ""
}
}
// ------------------ with else ------------------
fun test_9(x: SomeEnum?) {
when (x) {
SomeEnum.A -> ""
else -> ""
}
}
fun test_10(x: Base?) {
when (x) {
is Base.A -> ""
else -> ""
}
}
fun test_11(x: IBase?) {
when (x) {
is IBase.A -> ""
else -> ""
}
}
fun test_12(x: Boolean?) {
when (x) {
true -> ""
else -> ""
}
}
// ------------------ exhaustive ------------------
fun test_13(x: SomeEnum?) {
when (x) {
SomeEnum.A -> ""
SomeEnum.B -> ""
null -> ""
}
}
fun test_14(x: Base?) {
when (x) {
is Base.A -> ""
is Base.B -> ""
null -> ""
}
}
fun test_15(x: IBase?) {
when (x) {
is IBase.A -> ""
is IBase.B -> ""
null -> ""
}
}
fun test_16(x: Boolean?) {
when (x) {
true -> ""
false -> ""
null -> ""
}
}

View File

@@ -0,0 +1,78 @@
package
public fun test_1(/*0*/ x: SomeEnum): kotlin.Unit
public fun test_10(/*0*/ x: Base?): kotlin.Unit
public fun test_11(/*0*/ x: IBase?): kotlin.Unit
public fun test_12(/*0*/ x: kotlin.Boolean?): kotlin.Unit
public fun test_13(/*0*/ x: SomeEnum?): kotlin.Unit
public fun test_14(/*0*/ x: Base?): kotlin.Unit
public fun test_15(/*0*/ x: IBase?): kotlin.Unit
public fun test_16(/*0*/ x: kotlin.Boolean?): kotlin.Unit
public fun test_2(/*0*/ x: Base): kotlin.Unit
public fun test_3(/*0*/ x: IBase): kotlin.Unit
public fun test_4(/*0*/ x: kotlin.Boolean): kotlin.Unit
public fun test_5(/*0*/ x: SomeEnum?): kotlin.Unit
public fun test_6(/*0*/ x: Base?): kotlin.Unit
public fun test_7(/*0*/ x: IBase?): kotlin.Unit
public fun test_8(/*0*/ x: kotlin.Boolean?): kotlin.Unit
public fun test_9(/*0*/ x: SomeEnum?): kotlin.Unit
public sealed class Base {
protected constructor Base()
public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean
public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int
public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String
public final class A : Base {
public constructor A()
public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean
public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int
public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String
}
public final class B : Base {
public constructor B()
public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean
public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int
public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String
}
}
public sealed interface IBase {
public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean
public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int
public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String
public interface A : IBase {
public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean
public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int
public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String
}
public interface B : IBase {
public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean
public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int
public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String
}
}
public final enum class SomeEnum : kotlin.Enum<SomeEnum> {
enum entry A
enum entry B
private constructor SomeEnum()
public final override /*1*/ /*fake_override*/ val name: kotlin.String
public final override /*1*/ /*fake_override*/ val ordinal: kotlin.Int
protected final override /*1*/ /*fake_override*/ fun clone(): kotlin.Any
public final override /*1*/ /*fake_override*/ fun compareTo(/*0*/ other: SomeEnum): kotlin.Int
public final override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean
protected/*protected and package*/ final override /*1*/ /*fake_override*/ /*isHiddenForResolutionEverywhereBesideSupercalls*/ fun finalize(): kotlin.Unit
public final override /*1*/ /*fake_override*/ /*isHiddenForResolutionEverywhereBesideSupercalls*/ fun getDeclaringClass(): java.lang.Class<SomeEnum!>!
public final override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int
public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String
// Static members
public final /*synthesized*/ fun valueOf(/*0*/ value: kotlin.String): SomeEnum
public final /*synthesized*/ fun values(): kotlin.Array<SomeEnum>
}

View File

@@ -1,5 +1,5 @@
// FIR_IDENTICAL
// !LANGUAGE: -ProhibitNonExhaustiveWhenOnAlgebraicTypes
// !LANGUAGE: +WarnAboutNonExhaustiveWhenOnAlgebraicTypes -ProhibitNonExhaustiveWhenOnAlgebraicTypes
enum class SomeEnum {
A, B

View File

@@ -1,5 +1,5 @@
// FIR_IDENTICAL
// !LANGUAGE: +ProhibitNonExhaustiveWhenOnAlgebraicTypes
// !LANGUAGE: +WarnAboutNonExhaustiveWhenOnAlgebraicTypes +ProhibitNonExhaustiveWhenOnAlgebraicTypes
enum class SomeEnum {
A, B

View File

@@ -0,0 +1,19 @@
// !DIAGNOSTICS: -UNUSED_VARIABLE
// WITH_RUNTIME
// SKIP_TXT
// !LANGUAGE: +InstantiationOfAnnotationClasses
import kotlin.reflect.KClass
annotation class A
annotation class B(val int: Int)
annotation class C(val int: Int = 42)
annotation class G<T: Any>(val int: KClass<T>)
fun box() {
val a = <!ANNOTATION_CLASS_CONSTRUCTOR_CALL!>A()<!>
val b = <!ANNOTATION_CLASS_CONSTRUCTOR_CALL!>B(4)<!>
val c = <!ANNOTATION_CLASS_CONSTRUCTOR_CALL!>C()<!>
val foo = <!ANNOTATION_CLASS_CONSTRUCTOR_CALL!>G(Int::class)<!>
}

View File

@@ -1,4 +1,5 @@
// FIR_IDENTICAL
// LANGUAGE: +WarnAboutNonExhaustiveWhenOnAlgebraicTypes
fun test1() {
if (true) {
<!NON_EXHAUSTIVE_WHEN_STATEMENT!>when<!> (true) {

View File

@@ -1103,6 +1103,12 @@ public class DiagnosticTestGenerated extends AbstractDiagnosticTest {
runTest("compiler/testData/diagnostics/tests/annotations/ConstructorCall.kt");
}
@Test
@TestMetadata("ConstructorCallAllowed.kt")
public void testConstructorCallAllowed() throws Exception {
runTest("compiler/testData/diagnostics/tests/annotations/ConstructorCallAllowed.kt");
}
@Test
@TestMetadata("DanglingInScript.kts")
public void testDanglingInScript() throws Exception {
@@ -31777,6 +31783,12 @@ public class DiagnosticTestGenerated extends AbstractDiagnosticTest {
runTest("compiler/testData/diagnostics/tests/when/NonExhaustiveWarningNull.kt");
}
@Test
@TestMetadata("nonExhaustiveWhenStatement_1_5.kt")
public void testNonExhaustiveWhenStatement_1_5() throws Exception {
runTest("compiler/testData/diagnostics/tests/when/nonExhaustiveWhenStatement_1_5.kt");
}
@Test
@TestMetadata("nonExhaustiveWhenStatement_1_6.kt")
public void testNonExhaustiveWhenStatement_1_6() throws Exception {

View File

@@ -24,6 +24,12 @@ public class DiagnosticsNativeTestGenerated extends AbstractDiagnosticsNativeTes
KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("compiler/testData/diagnostics/nativeTests"), Pattern.compile("^(.+)\\.kt$"), null, true);
}
@Test
@TestMetadata("annotationConstructorCallNative.kt")
public void testAnnotationConstructorCallNative() throws Exception {
runTest("compiler/testData/diagnostics/nativeTests/annotationConstructorCallNative.kt");
}
@Test
@TestMetadata("sharedImmutable.kt")
public void testSharedImmutable() throws Exception {

View File

@@ -24,6 +24,12 @@ public class DiagnosticsTestWithJsStdLibGenerated extends AbstractDiagnosticsTes
KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("compiler/testData/diagnostics/testsWithJsStdLib"), Pattern.compile("^(.+)\\.kt$"), null, true);
}
@Test
@TestMetadata("annotationConstructorCallJs.kt")
public void testAnnotationConstructorCallJs() throws Exception {
runTest("compiler/testData/diagnostics/testsWithJsStdLib/annotationConstructorCallJs.kt");
}
@Test
@TestMetadata("funConstructorCallJS.kt")
public void testFunConstructorCallJS() throws Exception {

View File

@@ -380,6 +380,16 @@ public class BlackBoxCodegenTestGenerated extends AbstractBlackBoxCodegenTest {
}
}
@Nested
@TestMetadata("compiler/testData/codegen/box/annotations/instances")
@TestDataPath("$PROJECT_ROOT")
public class Instances {
@Test
public void testAllFilesPresentInInstances() throws Exception {
KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("compiler/testData/codegen/box/annotations/instances"), Pattern.compile("^(.+)\\.kt$"), null, TargetBackend.JVM, true);
}
}
@Nested
@TestMetadata("compiler/testData/codegen/box/annotations/kClassMapping")
@TestDataPath("$PROJECT_ROOT")
@@ -18868,6 +18878,12 @@ public class BlackBoxCodegenTestGenerated extends AbstractBlackBoxCodegenTest {
runTest("compiler/testData/codegen/box/inlineClasses/kt47609.kt");
}
@Test
@TestMetadata("kt47762.kt")
public void testKt47762() throws Exception {
runTest("compiler/testData/codegen/box/inlineClasses/kt47762.kt");
}
@Test
@TestMetadata("mangledDefaultParameterFunction.kt")
public void testMangledDefaultParameterFunction() throws Exception {
@@ -42412,6 +42428,12 @@ public class BlackBoxCodegenTestGenerated extends AbstractBlackBoxCodegenTest {
runTest("compiler/testData/codegen/box/unsignedTypes/kt43286a.kt");
}
@Test
@TestMetadata("kt47716.kt")
public void testKt47716() throws Exception {
runTest("compiler/testData/codegen/box/unsignedTypes/kt47716.kt");
}
@Test
@TestMetadata("literalEqualsNullableUnsigned.kt")
public void testLiteralEqualsNullableUnsigned() throws Exception {

View File

@@ -25,6 +25,16 @@ public class BlackBoxInlineCodegenTestGenerated extends AbstractBlackBoxInlineCo
KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("compiler/testData/codegen/boxInline"), Pattern.compile("^(.+)\\.kt$"), null, TargetBackend.JVM, true);
}
@Nested
@TestMetadata("compiler/testData/codegen/boxInline/annotations")
@TestDataPath("$PROJECT_ROOT")
public class Annotations {
@Test
public void testAllFilesPresentInAnnotations() throws Exception {
KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("compiler/testData/codegen/boxInline/annotations"), Pattern.compile("^(.+)\\.kt$"), null, TargetBackend.JVM, true);
}
}
@Nested
@TestMetadata("compiler/testData/codegen/boxInline/anonymousObject")
@TestDataPath("$PROJECT_ROOT")

View File

@@ -316,6 +316,18 @@ public class BytecodeListingTestGenerated extends AbstractBytecodeListingTest {
KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("compiler/testData/codegen/bytecodeListing/annotations"), Pattern.compile("^(.+)\\.kt$"), null, TargetBackend.JVM, true);
}
@Test
@TestMetadata("annotationCtorCallGenerateSynthetic.kt")
public void testAnnotationCtorCallGenerateSynthetic() throws Exception {
runTest("compiler/testData/codegen/bytecodeListing/annotations/annotationCtorCallGenerateSynthetic.kt");
}
@Test
@TestMetadata("annotationCtorCallNoSynthetic.kt")
public void testAnnotationCtorCallNoSynthetic() throws Exception {
runTest("compiler/testData/codegen/bytecodeListing/annotations/annotationCtorCallNoSynthetic.kt");
}
@Test
@TestMetadata("annotationsOnDelegatedMembers.kt")
public void testAnnotationsOnDelegatedMembers() throws Exception {

View File

@@ -25,6 +25,16 @@ public class CompileKotlinAgainstInlineKotlinTestGenerated extends AbstractCompi
KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("compiler/testData/codegen/boxInline"), Pattern.compile("^(.+)\\.kt$"), null, TargetBackend.JVM, true);
}
@Nested
@TestMetadata("compiler/testData/codegen/boxInline/annotations")
@TestDataPath("$PROJECT_ROOT")
public class Annotations {
@Test
public void testAllFilesPresentInAnnotations() throws Exception {
KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("compiler/testData/codegen/boxInline/annotations"), Pattern.compile("^(.+)\\.kt$"), null, TargetBackend.JVM, true);
}
}
@Nested
@TestMetadata("compiler/testData/codegen/boxInline/anonymousObject")
@TestDataPath("$PROJECT_ROOT")

View File

@@ -380,6 +380,76 @@ public class IrBlackBoxCodegenTestGenerated extends AbstractIrBlackBoxCodegenTes
}
}
@Nested
@TestMetadata("compiler/testData/codegen/box/annotations/instances")
@TestDataPath("$PROJECT_ROOT")
public class Instances {
@Test
public void testAllFilesPresentInInstances() throws Exception {
KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("compiler/testData/codegen/box/annotations/instances"), Pattern.compile("^(.+)\\.kt$"), null, TargetBackend.JVM_IR, true);
}
@Test
@TestMetadata("annotationEnclosingName.kt")
public void testAnnotationEnclosingName() throws Exception {
runTest("compiler/testData/codegen/box/annotations/instances/annotationEnclosingName.kt");
}
@Test
@TestMetadata("annotationEqHc.kt")
public void testAnnotationEqHc() throws Exception {
runTest("compiler/testData/codegen/box/annotations/instances/annotationEqHc.kt");
}
@Test
@TestMetadata("annotationInstances.kt")
public void testAnnotationInstances() throws Exception {
runTest("compiler/testData/codegen/box/annotations/instances/annotationInstances.kt");
}
@Test
@TestMetadata("annotationInstancesEmptyDefault.kt")
public void testAnnotationInstancesEmptyDefault() throws Exception {
runTest("compiler/testData/codegen/box/annotations/instances/annotationInstancesEmptyDefault.kt");
}
@Test
@TestMetadata("annotationToString.kt")
public void testAnnotationToString() throws Exception {
runTest("compiler/testData/codegen/box/annotations/instances/annotationToString.kt");
}
@Test
@TestMetadata("annotationType.kt")
public void testAnnotationType() throws Exception {
runTest("compiler/testData/codegen/box/annotations/instances/annotationType.kt");
}
@Test
@TestMetadata("javaAnnotation.kt")
public void testJavaAnnotation() throws Exception {
runTest("compiler/testData/codegen/box/annotations/instances/javaAnnotation.kt");
}
@Test
@TestMetadata("multifileEqHc.kt")
public void testMultifileEqHc() throws Exception {
runTest("compiler/testData/codegen/box/annotations/instances/multifileEqHc.kt");
}
@Test
@TestMetadata("multimoduleInlining.kt")
public void testMultimoduleInlining() throws Exception {
runTest("compiler/testData/codegen/box/annotations/instances/multimoduleInlining.kt");
}
@Test
@TestMetadata("multiplatformInstantiation.kt")
public void testMultiplatformInstantiation() throws Exception {
runTest("compiler/testData/codegen/box/annotations/instances/multiplatformInstantiation.kt");
}
}
@Nested
@TestMetadata("compiler/testData/codegen/box/annotations/kClassMapping")
@TestDataPath("$PROJECT_ROOT")
@@ -18910,6 +18980,12 @@ public class IrBlackBoxCodegenTestGenerated extends AbstractIrBlackBoxCodegenTes
runTest("compiler/testData/codegen/box/inlineClasses/kt47609.kt");
}
@Test
@TestMetadata("kt47762.kt")
public void testKt47762() throws Exception {
runTest("compiler/testData/codegen/box/inlineClasses/kt47762.kt");
}
@Test
@TestMetadata("mangledDefaultParameterFunction.kt")
public void testMangledDefaultParameterFunction() throws Exception {
@@ -42454,6 +42530,12 @@ public class IrBlackBoxCodegenTestGenerated extends AbstractIrBlackBoxCodegenTes
runTest("compiler/testData/codegen/box/unsignedTypes/kt43286a.kt");
}
@Test
@TestMetadata("kt47716.kt")
public void testKt47716() throws Exception {
runTest("compiler/testData/codegen/box/unsignedTypes/kt47716.kt");
}
@Test
@TestMetadata("literalEqualsNullableUnsigned.kt")
public void testLiteralEqualsNullableUnsigned() throws Exception {

View File

@@ -25,6 +25,28 @@ public class IrBlackBoxInlineCodegenTestGenerated extends AbstractIrBlackBoxInli
KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("compiler/testData/codegen/boxInline"), Pattern.compile("^(.+)\\.kt$"), null, TargetBackend.JVM_IR, true);
}
@Nested
@TestMetadata("compiler/testData/codegen/boxInline/annotations")
@TestDataPath("$PROJECT_ROOT")
public class Annotations {
@Test
public void testAllFilesPresentInAnnotations() throws Exception {
KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("compiler/testData/codegen/boxInline/annotations"), Pattern.compile("^(.+)\\.kt$"), null, TargetBackend.JVM_IR, true);
}
@Test
@TestMetadata("annotationInstanceInlining.kt")
public void testAnnotationInstanceInlining() throws Exception {
runTest("compiler/testData/codegen/boxInline/annotations/annotationInstanceInlining.kt");
}
@Test
@TestMetadata("instanceInAnonymousClass.kt")
public void testInstanceInAnonymousClass() throws Exception {
runTest("compiler/testData/codegen/boxInline/annotations/instanceInAnonymousClass.kt");
}
}
@Nested
@TestMetadata("compiler/testData/codegen/boxInline/anonymousObject")
@TestDataPath("$PROJECT_ROOT")

View File

@@ -316,6 +316,18 @@ public class IrBytecodeListingTestGenerated extends AbstractIrBytecodeListingTes
KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("compiler/testData/codegen/bytecodeListing/annotations"), Pattern.compile("^(.+)\\.kt$"), null, TargetBackend.JVM_IR, true);
}
@Test
@TestMetadata("annotationCtorCallGenerateSynthetic.kt")
public void testAnnotationCtorCallGenerateSynthetic() throws Exception {
runTest("compiler/testData/codegen/bytecodeListing/annotations/annotationCtorCallGenerateSynthetic.kt");
}
@Test
@TestMetadata("annotationCtorCallNoSynthetic.kt")
public void testAnnotationCtorCallNoSynthetic() throws Exception {
runTest("compiler/testData/codegen/bytecodeListing/annotations/annotationCtorCallNoSynthetic.kt");
}
@Test
@TestMetadata("annotationsOnDelegatedMembers.kt")
public void testAnnotationsOnDelegatedMembers() throws Exception {

View File

@@ -25,6 +25,28 @@ public class IrCompileKotlinAgainstInlineKotlinTestGenerated extends AbstractIrC
KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("compiler/testData/codegen/boxInline"), Pattern.compile("^(.+)\\.kt$"), null, TargetBackend.JVM_IR, true);
}
@Nested
@TestMetadata("compiler/testData/codegen/boxInline/annotations")
@TestDataPath("$PROJECT_ROOT")
public class Annotations {
@Test
public void testAllFilesPresentInAnnotations() throws Exception {
KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("compiler/testData/codegen/boxInline/annotations"), Pattern.compile("^(.+)\\.kt$"), null, TargetBackend.JVM_IR, true);
}
@Test
@TestMetadata("annotationInstanceInlining.kt")
public void testAnnotationInstanceInlining() throws Exception {
runTest("compiler/testData/codegen/boxInline/annotations/annotationInstanceInlining.kt");
}
@Test
@TestMetadata("instanceInAnonymousClass.kt")
public void testInstanceInAnonymousClass() throws Exception {
runTest("compiler/testData/codegen/boxInline/annotations/instanceInAnonymousClass.kt");
}
}
@Nested
@TestMetadata("compiler/testData/codegen/boxInline/anonymousObject")
@TestDataPath("$PROJECT_ROOT")

View File

@@ -25,6 +25,28 @@ public class IrSerializeCompileKotlinAgainstInlineKotlinTestGenerated extends Ab
KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("compiler/testData/codegen/boxInline"), Pattern.compile("^(.+)\\.kt$"), null, TargetBackend.JVM_IR, true);
}
@Nested
@TestMetadata("compiler/testData/codegen/boxInline/annotations")
@TestDataPath("$PROJECT_ROOT")
public class Annotations {
@Test
public void testAllFilesPresentInAnnotations() throws Exception {
KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("compiler/testData/codegen/boxInline/annotations"), Pattern.compile("^(.+)\\.kt$"), null, TargetBackend.JVM_IR, true);
}
@Test
@TestMetadata("annotationInstanceInlining.kt")
public void testAnnotationInstanceInlining() throws Exception {
runTest("compiler/testData/codegen/boxInline/annotations/annotationInstanceInlining.kt");
}
@Test
@TestMetadata("instanceInAnonymousClass.kt")
public void testInstanceInAnonymousClass() throws Exception {
runTest("compiler/testData/codegen/boxInline/annotations/instanceInAnonymousClass.kt");
}
}
@Nested
@TestMetadata("compiler/testData/codegen/boxInline/anonymousObject")
@TestDataPath("$PROJECT_ROOT")

View File

@@ -25,6 +25,28 @@ public class JvmIrAgainstOldBoxInlineTestGenerated extends AbstractJvmIrAgainstO
KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("compiler/testData/codegen/boxInline"), Pattern.compile("^(.+)\\.kt$"), null, TargetBackend.JVM_MULTI_MODULE_IR_AGAINST_OLD, true);
}
@Nested
@TestMetadata("compiler/testData/codegen/boxInline/annotations")
@TestDataPath("$PROJECT_ROOT")
public class Annotations {
@Test
public void testAllFilesPresentInAnnotations() throws Exception {
KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("compiler/testData/codegen/boxInline/annotations"), Pattern.compile("^(.+)\\.kt$"), null, TargetBackend.JVM_MULTI_MODULE_IR_AGAINST_OLD, true);
}
@Test
@TestMetadata("annotationInstanceInlining.kt")
public void testAnnotationInstanceInlining() throws Exception {
runTest("compiler/testData/codegen/boxInline/annotations/annotationInstanceInlining.kt");
}
@Test
@TestMetadata("instanceInAnonymousClass.kt")
public void testInstanceInAnonymousClass() throws Exception {
runTest("compiler/testData/codegen/boxInline/annotations/instanceInAnonymousClass.kt");
}
}
@Nested
@TestMetadata("compiler/testData/codegen/boxInline/anonymousObject")
@TestDataPath("$PROJECT_ROOT")

View File

@@ -25,6 +25,16 @@ public class JvmOldAgainstIrBoxInlineTestGenerated extends AbstractJvmOldAgainst
KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("compiler/testData/codegen/boxInline"), Pattern.compile("^(.+)\\.kt$"), null, TargetBackend.JVM_MULTI_MODULE_OLD_AGAINST_IR, true);
}
@Nested
@TestMetadata("compiler/testData/codegen/boxInline/annotations")
@TestDataPath("$PROJECT_ROOT")
public class Annotations {
@Test
public void testAllFilesPresentInAnnotations() throws Exception {
KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("compiler/testData/codegen/boxInline/annotations"), Pattern.compile("^(.+)\\.kt$"), null, TargetBackend.JVM_MULTI_MODULE_OLD_AGAINST_IR, true);
}
}
@Nested
@TestMetadata("compiler/testData/codegen/boxInline/anonymousObject")
@TestDataPath("$PROJECT_ROOT")

View File

@@ -335,6 +335,19 @@ public class LightAnalysisModeTestGenerated extends AbstractLightAnalysisModeTes
}
}
@TestMetadata("compiler/testData/codegen/box/annotations/instances")
@TestDataPath("$PROJECT_ROOT")
@RunWith(JUnit3RunnerWithInners.class)
public static class Instances extends AbstractLightAnalysisModeTest {
private void runTest(String testDataFilePath) throws Exception {
KotlinTestUtils.runTest(this::doTest, TargetBackend.JVM, testDataFilePath);
}
public void testAllFilesPresentInInstances() throws Exception {
KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("compiler/testData/codegen/box/annotations/instances"), Pattern.compile("^(.+)\\.kt$"), null, TargetBackend.JVM, true);
}
}
@TestMetadata("compiler/testData/codegen/box/annotations/kClassMapping")
@TestDataPath("$PROJECT_ROOT")
@RunWith(JUnit3RunnerWithInners.class)
@@ -7651,11 +7664,6 @@ public class LightAnalysisModeTestGenerated extends AbstractLightAnalysisModeTes
@TestDataPath("$PROJECT_ROOT")
@RunWith(JUnit3RunnerWithInners.class)
public static class ControlFlow extends AbstractLightAnalysisModeTest {
@TestMetadata("doWhileWithInline.kt")
public void ignoreDoWhileWithInline() throws Exception {
runTest("compiler/testData/codegen/box/coroutines/controlFlow/doWhileWithInline.kt");
}
private void runTest(String testDataFilePath) throws Exception {
KotlinTestUtils.runTest(this::doTest, TargetBackend.JVM, testDataFilePath);
}
@@ -7684,6 +7692,11 @@ public class LightAnalysisModeTestGenerated extends AbstractLightAnalysisModeTes
runTest("compiler/testData/codegen/box/coroutines/controlFlow/doWhileStatement.kt");
}
@TestMetadata("doWhileWithInline.kt")
public void testDoWhileWithInline() throws Exception {
runTest("compiler/testData/codegen/box/coroutines/controlFlow/doWhileWithInline.kt");
}
@TestMetadata("doubleBreak.kt")
public void testDoubleBreak() throws Exception {
runTest("compiler/testData/codegen/box/coroutines/controlFlow/doubleBreak.kt");
@@ -15648,6 +15661,11 @@ public class LightAnalysisModeTestGenerated extends AbstractLightAnalysisModeTes
runTest("compiler/testData/codegen/box/inlineClasses/kt47609.kt");
}
@TestMetadata("kt47762.kt")
public void testKt47762() throws Exception {
runTest("compiler/testData/codegen/box/inlineClasses/kt47762.kt");
}
@TestMetadata("mangledDefaultParameterFunction.kt")
public void testMangledDefaultParameterFunction() throws Exception {
runTest("compiler/testData/codegen/box/inlineClasses/mangledDefaultParameterFunction.kt");
@@ -34175,6 +34193,11 @@ public class LightAnalysisModeTestGenerated extends AbstractLightAnalysisModeTes
runTest("compiler/testData/codegen/box/unsignedTypes/kt43286a.kt");
}
@TestMetadata("kt47716.kt")
public void testKt47716() throws Exception {
runTest("compiler/testData/codegen/box/unsignedTypes/kt47716.kt");
}
@TestMetadata("literalEqualsNullableUnsigned.kt")
public void testLiteralEqualsNullableUnsigned() throws Exception {
runTest("compiler/testData/codegen/box/unsignedTypes/literalEqualsNullableUnsigned.kt");

View File

@@ -1,3 +1,4 @@
// LANGUAGE: +WarnAboutNonExhaustiveWhenOnAlgebraicTypes
// !DIAGNOSTICS: -UNUSED_EXPRESSION -DEBUG_INFO_SMARTCAST
// SKIP_TXT

View File

@@ -1,3 +1,4 @@
// LANGUAGE: +WarnAboutNonExhaustiveWhenOnAlgebraicTypes
// !DIAGNOSTICS: -UNUSED_EXPRESSION
// SKIP_TXT

View File

@@ -1,3 +1,4 @@
// LANGUAGE: +WarnAboutNonExhaustiveWhenOnAlgebraicTypes
// SKIP_TXT
/*

Some files were not shown because too many files have changed in this diff Show More