[FIR] Support PreliminaryLoopVisitor in FIR DFA
This commit is contained in:
+6
@@ -37516,6 +37516,12 @@ public class FirBlackBoxCodegenTestGenerated extends AbstractFirBlackBoxCodegenT
|
|||||||
runTest("compiler/testData/codegen/box/smartCasts/kt42517.kt");
|
runTest("compiler/testData/codegen/box/smartCasts/kt42517.kt");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@TestMetadata("kt44804.kt")
|
||||||
|
public void testKt44804() throws Exception {
|
||||||
|
runTest("compiler/testData/codegen/box/smartCasts/kt44804.kt");
|
||||||
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
@TestMetadata("lambdaArgumentWithoutType.kt")
|
@TestMetadata("lambdaArgumentWithoutType.kt")
|
||||||
public void testLambdaArgumentWithoutType() throws Exception {
|
public void testLambdaArgumentWithoutType() throws Exception {
|
||||||
|
|||||||
+32
-4
@@ -29,19 +29,20 @@ import org.jetbrains.kotlin.fir.resolve.transformers.body.resolve.resultType
|
|||||||
import org.jetbrains.kotlin.fir.symbols.AbstractFirBasedSymbol
|
import org.jetbrains.kotlin.fir.symbols.AbstractFirBasedSymbol
|
||||||
import org.jetbrains.kotlin.fir.symbols.CallableId
|
import org.jetbrains.kotlin.fir.symbols.CallableId
|
||||||
import org.jetbrains.kotlin.fir.symbols.StandardClassIds
|
import org.jetbrains.kotlin.fir.symbols.StandardClassIds
|
||||||
|
import org.jetbrains.kotlin.fir.symbols.impl.FirVariableSymbol
|
||||||
import org.jetbrains.kotlin.fir.types.*
|
import org.jetbrains.kotlin.fir.types.*
|
||||||
import org.jetbrains.kotlin.fir.visitors.transformSingle
|
import org.jetbrains.kotlin.fir.visitors.transformSingle
|
||||||
import org.jetbrains.kotlin.name.FqName
|
import org.jetbrains.kotlin.name.FqName
|
||||||
import org.jetbrains.kotlin.name.Name
|
import org.jetbrains.kotlin.name.Name
|
||||||
import org.jetbrains.kotlin.types.ConstantValueKind
|
import org.jetbrains.kotlin.types.ConstantValueKind
|
||||||
import org.jetbrains.kotlin.utils.addIfNotNull
|
import org.jetbrains.kotlin.utils.addIfNotNull
|
||||||
import org.jetbrains.kotlin.utils.addToStdlib.runIf
|
|
||||||
|
|
||||||
class DataFlowAnalyzerContext<FLOW : Flow>(
|
class DataFlowAnalyzerContext<FLOW : Flow>(
|
||||||
val graphBuilder: ControlFlowGraphBuilder,
|
val graphBuilder: ControlFlowGraphBuilder,
|
||||||
variableStorage: VariableStorage,
|
variableStorage: VariableStorage,
|
||||||
flowOnNodes: MutableMap<CFGNode<*>, FLOW>,
|
flowOnNodes: MutableMap<CFGNode<*>, FLOW>,
|
||||||
val variablesForWhenConditions: MutableMap<WhenBranchConditionExitNode, DataFlowVariable>
|
val variablesForWhenConditions: MutableMap<WhenBranchConditionExitNode, DataFlowVariable>,
|
||||||
|
val preliminaryLoopVisitor: PreliminaryLoopVisitor
|
||||||
) {
|
) {
|
||||||
var flowOnNodes = flowOnNodes
|
var flowOnNodes = flowOnNodes
|
||||||
private set
|
private set
|
||||||
@@ -54,13 +55,15 @@ class DataFlowAnalyzerContext<FLOW : Flow>(
|
|||||||
|
|
||||||
variableStorage = variableStorage.clear()
|
variableStorage = variableStorage.clear()
|
||||||
flowOnNodes = mutableMapOf()
|
flowOnNodes = mutableMapOf()
|
||||||
|
|
||||||
|
preliminaryLoopVisitor.resetState()
|
||||||
}
|
}
|
||||||
|
|
||||||
companion object {
|
companion object {
|
||||||
fun <FLOW : Flow> empty(session: FirSession) =
|
fun <FLOW : Flow> empty(session: FirSession): DataFlowAnalyzerContext<FLOW> =
|
||||||
DataFlowAnalyzerContext<FLOW>(
|
DataFlowAnalyzerContext<FLOW>(
|
||||||
ControlFlowGraphBuilder(), VariableStorage(session),
|
ControlFlowGraphBuilder(), VariableStorage(session),
|
||||||
mutableMapOf(), mutableMapOf()
|
mutableMapOf(), mutableMapOf(), PreliminaryLoopVisitor()
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -210,12 +213,14 @@ abstract class FirDataFlowAnalyzer<FLOW : Flow>(
|
|||||||
// TODO: questionable
|
// TODO: questionable
|
||||||
postponedLambdaExitNode?.mergeIncomingFlow()
|
postponedLambdaExitNode?.mergeIncomingFlow()
|
||||||
functionExitNode.mergeIncomingFlow()
|
functionExitNode.mergeIncomingFlow()
|
||||||
|
exitCapturingStatement(anonymousFunction)
|
||||||
return FirControlFlowGraphReferenceImpl(graph)
|
return FirControlFlowGraphReferenceImpl(graph)
|
||||||
}
|
}
|
||||||
|
|
||||||
fun visitPostponedAnonymousFunction(anonymousFunction: FirAnonymousFunction) {
|
fun visitPostponedAnonymousFunction(anonymousFunction: FirAnonymousFunction) {
|
||||||
val (enterNode, exitNode) = graphBuilder.visitPostponedAnonymousFunction(anonymousFunction)
|
val (enterNode, exitNode) = graphBuilder.visitPostponedAnonymousFunction(anonymousFunction)
|
||||||
enterNode.mergeIncomingFlow()
|
enterNode.mergeIncomingFlow()
|
||||||
|
enterCapturingStatement(enterNode, anonymousFunction)
|
||||||
exitNode.mergeIncomingFlow()
|
exitNode.mergeIncomingFlow()
|
||||||
enterNode.flow = enterNode.flow.fork()
|
enterNode.flow = enterNode.flow.fork()
|
||||||
}
|
}
|
||||||
@@ -236,12 +241,14 @@ abstract class FirDataFlowAnalyzer<FLOW : Flow>(
|
|||||||
}
|
}
|
||||||
|
|
||||||
private fun exitLocalClass(klass: FirRegularClass): ControlFlowGraph {
|
private fun exitLocalClass(klass: FirRegularClass): ControlFlowGraph {
|
||||||
|
// TODO: support capturing of mutable properties, KT-44877
|
||||||
val (node, controlFlowGraph) = graphBuilder.exitLocalClass(klass)
|
val (node, controlFlowGraph) = graphBuilder.exitLocalClass(klass)
|
||||||
node.mergeIncomingFlow()
|
node.mergeIncomingFlow()
|
||||||
return controlFlowGraph
|
return controlFlowGraph
|
||||||
}
|
}
|
||||||
|
|
||||||
fun exitAnonymousObject(anonymousObject: FirAnonymousObject): ControlFlowGraph {
|
fun exitAnonymousObject(anonymousObject: FirAnonymousObject): ControlFlowGraph {
|
||||||
|
// TODO: support capturing of mutable properties, KT-44877
|
||||||
val (node, controlFlowGraph) = graphBuilder.exitAnonymousObject(anonymousObject)
|
val (node, controlFlowGraph) = graphBuilder.exitAnonymousObject(anonymousObject)
|
||||||
node.mergeIncomingFlow()
|
node.mergeIncomingFlow()
|
||||||
return controlFlowGraph
|
return controlFlowGraph
|
||||||
@@ -601,11 +608,13 @@ abstract class FirDataFlowAnalyzer<FLOW : Flow>(
|
|||||||
shouldRemoveSynthetics = true
|
shouldRemoveSynthetics = true
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
exitCapturingStatement(exitNode.fir)
|
||||||
}
|
}
|
||||||
|
|
||||||
fun enterWhileLoop(loop: FirLoop) {
|
fun enterWhileLoop(loop: FirLoop) {
|
||||||
val (loopEnterNode, loopConditionEnterNode) = graphBuilder.enterWhileLoop(loop)
|
val (loopEnterNode, loopConditionEnterNode) = graphBuilder.enterWhileLoop(loop)
|
||||||
loopEnterNode.mergeIncomingFlow()
|
loopEnterNode.mergeIncomingFlow()
|
||||||
|
enterCapturingStatement(loopEnterNode, loop)
|
||||||
loopConditionEnterNode.mergeIncomingFlow()
|
loopConditionEnterNode.mergeIncomingFlow()
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -630,11 +639,30 @@ abstract class FirDataFlowAnalyzer<FLOW : Flow>(
|
|||||||
exitCommonLoop(exitNode)
|
exitCommonLoop(exitNode)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private fun enterCapturingStatement(node: CFGNode<*>, statement: FirStatement) {
|
||||||
|
val reassignedNames = context.preliminaryLoopVisitor.enterCapturingStatement(statement)
|
||||||
|
if (reassignedNames.isEmpty()) return
|
||||||
|
val possiblyChangedVariables = variableStorage.realVariables.filterKeys {
|
||||||
|
val fir = (it.symbol as? FirVariableSymbol<*>)?.fir ?: return@filterKeys false
|
||||||
|
fir.isVar && fir.name in reassignedNames
|
||||||
|
}.values
|
||||||
|
if (possiblyChangedVariables.isEmpty()) return
|
||||||
|
val flow = node.flow
|
||||||
|
for (variable in possiblyChangedVariables) {
|
||||||
|
logicSystem.removeAllAboutVariableIncludingAliasInformation(flow, variable)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun exitCapturingStatement(statement: FirStatement) {
|
||||||
|
context.preliminaryLoopVisitor.exitCapturingStatement(statement)
|
||||||
|
}
|
||||||
|
|
||||||
// ----------------------------------- Do while Loop -----------------------------------
|
// ----------------------------------- Do while Loop -----------------------------------
|
||||||
|
|
||||||
fun enterDoWhileLoop(loop: FirLoop) {
|
fun enterDoWhileLoop(loop: FirLoop) {
|
||||||
val (loopEnterNode, loopBlockEnterNode) = graphBuilder.enterDoWhileLoop(loop)
|
val (loopEnterNode, loopBlockEnterNode) = graphBuilder.enterDoWhileLoop(loop)
|
||||||
loopEnterNode.mergeIncomingFlow()
|
loopEnterNode.mergeIncomingFlow()
|
||||||
|
enterCapturingStatement(loopEnterNode, loop)
|
||||||
loopBlockEnterNode.mergeIncomingFlow()
|
loopBlockEnterNode.mergeIncomingFlow()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -36,6 +36,7 @@ abstract class LogicSystem<FLOW : Flow>(protected val context: ConeInferenceCont
|
|||||||
abstract fun addImplication(flow: FLOW, implication: Implication)
|
abstract fun addImplication(flow: FLOW, implication: Implication)
|
||||||
|
|
||||||
abstract fun removeAllAboutVariable(flow: FLOW, variable: RealVariable)
|
abstract fun removeAllAboutVariable(flow: FLOW, variable: RealVariable)
|
||||||
|
abstract fun removeAllAboutVariableIncludingAliasInformation(flow: FLOW, variable: RealVariable)
|
||||||
|
|
||||||
abstract fun translateVariableFromConditionInStatements(
|
abstract fun translateVariableFromConditionInStatements(
|
||||||
flow: FLOW,
|
flow: FLOW,
|
||||||
|
|||||||
+15
@@ -254,6 +254,21 @@ abstract class PersistentLogicSystem(context: ConeInferenceContext) : LogicSyste
|
|||||||
// TODO: should we search variable in all logic statements?
|
// TODO: should we search variable in all logic statements?
|
||||||
}
|
}
|
||||||
|
|
||||||
|
override fun removeAllAboutVariableIncludingAliasInformation(flow: PersistentFlow, variable: RealVariable) {
|
||||||
|
removeAllAboutVariable(flow, variable)
|
||||||
|
val existedAlias = flow.directAliasMap[variable]?.variable
|
||||||
|
if (existedAlias != null) {
|
||||||
|
flow.directAliasMap = flow.directAliasMap.remove(variable)
|
||||||
|
val updatedBackwardsAliasList = flow.backwardsAliasMap.getValue(existedAlias).remove(variable)
|
||||||
|
flow.backwardsAliasMap = if (updatedBackwardsAliasList.isEmpty()) {
|
||||||
|
flow.backwardsAliasMap.remove(existedAlias)
|
||||||
|
} else {
|
||||||
|
flow.backwardsAliasMap.put(existedAlias, updatedBackwardsAliasList)
|
||||||
|
}
|
||||||
|
flow.updatedAliasDiff = flow.updatedAliasDiff.add(variable)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
override fun translateVariableFromConditionInStatements(
|
override fun translateVariableFromConditionInStatements(
|
||||||
flow: PersistentFlow,
|
flow: PersistentFlow,
|
||||||
originalVariable: DataFlowVariable,
|
originalVariable: DataFlowVariable,
|
||||||
|
|||||||
+87
@@ -0,0 +1,87 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2010-2021 JetBrains s.r.o. and Kotlin Programming Language contributors.
|
||||||
|
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package org.jetbrains.kotlin.fir.resolve.dfa
|
||||||
|
|
||||||
|
import org.jetbrains.kotlin.fir.FirElement
|
||||||
|
import org.jetbrains.kotlin.fir.declarations.*
|
||||||
|
import org.jetbrains.kotlin.fir.expressions.*
|
||||||
|
import org.jetbrains.kotlin.fir.references.FirNamedReference
|
||||||
|
import org.jetbrains.kotlin.fir.util.SetMultimap
|
||||||
|
import org.jetbrains.kotlin.fir.util.setMultimapOf
|
||||||
|
import org.jetbrains.kotlin.fir.visitors.FirVisitor
|
||||||
|
import org.jetbrains.kotlin.name.Name
|
||||||
|
|
||||||
|
class PreliminaryLoopVisitor {
|
||||||
|
private val reassignedVariablesPerElement: SetMultimap<FirStatement, Name> = setMultimapOf()
|
||||||
|
|
||||||
|
fun enterCapturingStatement(statement: FirStatement): Set<Name> {
|
||||||
|
assert(statement is FirLoop || statement is FirClass<*> || statement is FirFunction<*>)
|
||||||
|
if (statement !in reassignedVariablesPerElement) {
|
||||||
|
statement.accept(visitor, null)
|
||||||
|
}
|
||||||
|
return reassignedVariablesPerElement[statement]
|
||||||
|
}
|
||||||
|
|
||||||
|
fun exitCapturingStatement(statement: FirStatement) {
|
||||||
|
assert(statement is FirLoop || statement is FirClass<*> || statement is FirFunction<*>)
|
||||||
|
reassignedVariablesPerElement.removeKey(statement)
|
||||||
|
}
|
||||||
|
|
||||||
|
fun resetState() {
|
||||||
|
reassignedVariablesPerElement.clear()
|
||||||
|
}
|
||||||
|
|
||||||
|
// FirStatement -- closest statement (loop/lambda/local declaration) which may contain reassignments
|
||||||
|
private val visitor = object : FirVisitor<Unit, FirStatement?>() {
|
||||||
|
override fun visitElement(element: FirElement, data: FirStatement?) {
|
||||||
|
element.acceptChildren(this, data)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun visitVariableAssignment(variableAssignment: FirVariableAssignment, data: FirStatement?) {
|
||||||
|
val reference = variableAssignment.lValue as? FirNamedReference
|
||||||
|
if (reference != null) {
|
||||||
|
requireNotNull(data)
|
||||||
|
reassignedVariablesPerElement.put(data, reference.name)
|
||||||
|
}
|
||||||
|
visitElement(variableAssignment, data)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun visitWhileLoop(whileLoop: FirWhileLoop, data: FirStatement?) {
|
||||||
|
visitCapturingStatement(whileLoop, data)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun visitDoWhileLoop(doWhileLoop: FirDoWhileLoop, data: FirStatement?) {
|
||||||
|
visitCapturingStatement(doWhileLoop, data)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun visitAnonymousFunction(anonymousFunction: FirAnonymousFunction, data: FirStatement?) {
|
||||||
|
visitCapturingStatement(anonymousFunction, data)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun visitSimpleFunction(simpleFunction: FirSimpleFunction, data: FirStatement?) {
|
||||||
|
visitCapturingStatement(simpleFunction, data)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun <F : FirFunction<F>> visitFunction(function: FirFunction<F>, data: FirStatement?) {
|
||||||
|
visitCapturingStatement(function, data)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun visitRegularClass(regularClass: FirRegularClass, data: FirStatement?) {
|
||||||
|
visitCapturingStatement(regularClass, data)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun visitAnonymousObject(anonymousObject: FirAnonymousObject, data: FirStatement?) {
|
||||||
|
visitCapturingStatement(anonymousObject, data)
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun visitCapturingStatement(statement: FirStatement, parent: FirStatement?) {
|
||||||
|
visitElement(statement, statement)
|
||||||
|
if (parent != null) {
|
||||||
|
reassignedVariablesPerElement.putAll(parent, reassignedVariablesPerElement[statement])
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -26,7 +26,10 @@ import kotlin.contracts.contract
|
|||||||
@OptIn(DfaInternals::class)
|
@OptIn(DfaInternals::class)
|
||||||
class VariableStorage(private val session: FirSession) {
|
class VariableStorage(private val session: FirSession) {
|
||||||
private var counter = 1
|
private var counter = 1
|
||||||
private val realVariables: MutableMap<Identifier, RealVariable> = HashMap()
|
private val _realVariables: MutableMap<Identifier, RealVariable> = HashMap()
|
||||||
|
val realVariables: Map<Identifier, RealVariable>
|
||||||
|
get() = _realVariables
|
||||||
|
|
||||||
private val syntheticVariables: MutableMap<FirElement, SyntheticVariable> = HashMap()
|
private val syntheticVariables: MutableMap<FirElement, SyntheticVariable> = HashMap()
|
||||||
|
|
||||||
fun clear(): VariableStorage = VariableStorage(session)
|
fun clear(): VariableStorage = VariableStorage(session)
|
||||||
@@ -34,7 +37,7 @@ class VariableStorage(private val session: FirSession) {
|
|||||||
fun getOrCreateRealVariableWithoutUnwrappingAlias(flow: Flow, symbol: AbstractFirBasedSymbol<*>, fir: FirElement): RealVariable {
|
fun getOrCreateRealVariableWithoutUnwrappingAlias(flow: Flow, symbol: AbstractFirBasedSymbol<*>, fir: FirElement): RealVariable {
|
||||||
val realFir = fir.unwrapElement()
|
val realFir = fir.unwrapElement()
|
||||||
val identifier = getIdentifierBySymbol(flow, symbol, realFir)
|
val identifier = getIdentifierBySymbol(flow, symbol, realFir)
|
||||||
return realVariables.getOrPut(identifier) { createRealVariableInternal(flow, identifier, realFir) }
|
return _realVariables.getOrPut(identifier) { createRealVariableInternal(flow, identifier, realFir) }
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun getOrCreateRealVariable(flow: Flow, symbol: AbstractFirBasedSymbol<*>, fir: FirElement): RealVariable {
|
private fun getOrCreateRealVariable(flow: Flow, symbol: AbstractFirBasedSymbol<*>, fir: FirElement): RealVariable {
|
||||||
@@ -108,7 +111,7 @@ class VariableStorage(private val session: FirSession) {
|
|||||||
fun getRealVariableWithoutUnwrappingAlias(symbol: AbstractFirBasedSymbol<*>?, fir: FirElement, flow: Flow): RealVariable? {
|
fun getRealVariableWithoutUnwrappingAlias(symbol: AbstractFirBasedSymbol<*>?, fir: FirElement, flow: Flow): RealVariable? {
|
||||||
val realFir = fir.unwrapElement()
|
val realFir = fir.unwrapElement()
|
||||||
return symbol.takeIf { it.isStable(realFir) }?.let {
|
return symbol.takeIf { it.isStable(realFir) }?.let {
|
||||||
realVariables[getIdentifierBySymbol(flow, it, realFir.unwrapElement())]
|
_realVariables[getIdentifierBySymbol(flow, it, realFir.unwrapElement())]
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -131,7 +134,7 @@ class VariableStorage(private val session: FirSession) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fun removeRealVariable(symbol: AbstractFirBasedSymbol<*>) {
|
fun removeRealVariable(symbol: AbstractFirBasedSymbol<*>) {
|
||||||
realVariables.remove(Identifier(symbol, null, null))
|
_realVariables.remove(Identifier(symbol, null, null))
|
||||||
}
|
}
|
||||||
|
|
||||||
fun removeSyntheticVariable(variable: DataFlowVariable) {
|
fun removeSyntheticVariable(variable: DataFlowVariable) {
|
||||||
|
|||||||
+1
-2
@@ -1,6 +1,5 @@
|
|||||||
// TARGET_BACKEND: JVM
|
// TARGET_BACKEND: JVM
|
||||||
// WITH_RUNTIME
|
// WITH_RUNTIME
|
||||||
// IGNORE_BACKEND_FIR: JVM_IR
|
|
||||||
|
|
||||||
open class A {
|
open class A {
|
||||||
fun Foo() {
|
fun Foo() {
|
||||||
@@ -23,4 +22,4 @@ fun box(): String {
|
|||||||
test.Foo()
|
test.Foo()
|
||||||
|
|
||||||
return "OK"
|
return "OK"
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,43 @@
|
|||||||
|
// ISSUE: KT-44804
|
||||||
|
// WITH_STDLIB
|
||||||
|
|
||||||
|
abstract class AbstractInsnNode(val next: AbstractInsnNode? = null)
|
||||||
|
|
||||||
|
class LineNumberNode(next: AbstractInsnNode? = null) : AbstractInsnNode(next) {
|
||||||
|
val line: Int = 1
|
||||||
|
}
|
||||||
|
|
||||||
|
class LabelNode() : AbstractInsnNode(null)
|
||||||
|
|
||||||
|
fun isDeadLineNumber(insn: LineNumberNode, index: Int, frames: Array<out Any?>): Boolean {
|
||||||
|
// Line number node is "dead" if the corresponding line number interval
|
||||||
|
// contains at least one "dead" meaningful instruction and no "live" meaningful instructions.
|
||||||
|
var finger: AbstractInsnNode = insn
|
||||||
|
var fingerIndex = index
|
||||||
|
var hasDeadInsn = false
|
||||||
|
loop@ while (true) {
|
||||||
|
finger = finger.next ?: break
|
||||||
|
fingerIndex++
|
||||||
|
when (finger) {
|
||||||
|
is LabelNode ->
|
||||||
|
continue@loop
|
||||||
|
is LineNumberNode ->
|
||||||
|
if (finger.line != insn.line) return hasDeadInsn
|
||||||
|
else -> {
|
||||||
|
if (frames[fingerIndex] != null) return false
|
||||||
|
hasDeadInsn = true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
fun box(): String {
|
||||||
|
val node = LineNumberNode(
|
||||||
|
LineNumberNode(
|
||||||
|
LabelNode()
|
||||||
|
)
|
||||||
|
)
|
||||||
|
val result = isDeadLineNumber(node, 0, arrayOf(null, null, "aaa", "bbb"))
|
||||||
|
return if (result) "OK" else "fail"
|
||||||
|
}
|
||||||
@@ -10,5 +10,5 @@ fun use() {
|
|||||||
// Write to x is AFTER
|
// Write to x is AFTER
|
||||||
x.hashCode()
|
x.hashCode()
|
||||||
// No smart cast should be here!
|
// No smart cast should be here!
|
||||||
foo(bar { x = null }, x.hashCode())
|
foo(bar { x = null }, x<!UNSAFE_CALL!>.<!>hashCode())
|
||||||
}
|
}
|
||||||
|
|||||||
+2
-2
@@ -4,10 +4,10 @@ fun foo(arg: Int?) {
|
|||||||
if (x == null) return
|
if (x == null) return
|
||||||
run {
|
run {
|
||||||
// Unsafe because of owner modification
|
// Unsafe because of owner modification
|
||||||
x.hashCode()
|
x<!UNSAFE_CALL!>.<!>hashCode()
|
||||||
x = null
|
x = null
|
||||||
}
|
}
|
||||||
if (x != null) x = 42
|
if (x != null) x = 42
|
||||||
// Unsafe because of lambda
|
// Unsafe because of lambda
|
||||||
x<!UNSAFE_CALL!>.<!>hashCode()
|
x<!UNSAFE_CALL!>.<!>hashCode()
|
||||||
}
|
}
|
||||||
|
|||||||
+1
-1
@@ -6,5 +6,5 @@ fun foo(x: Int, f: () -> Unit, y: Int) {}
|
|||||||
fun bar() {
|
fun bar() {
|
||||||
var x: Int?
|
var x: Int?
|
||||||
x = 4
|
x = 4
|
||||||
foo(x, { x = null; x<!UNSAFE_CALL!>.<!>hashCode() }, x)
|
<!INAPPLICABLE_CANDIDATE!>foo<!>(x, { x = null; x<!UNSAFE_CALL!>.<!>hashCode() }, x)
|
||||||
}
|
}
|
||||||
|
|||||||
+2
-2
@@ -2,8 +2,8 @@ public fun foo() {
|
|||||||
var i: Any = 1
|
var i: Any = 1
|
||||||
if (i is Int) {
|
if (i is Int) {
|
||||||
while (i != 10) {
|
while (i != 10) {
|
||||||
i++ // Here smart cast should not be performed due to a successor
|
i<!UNRESOLVED_REFERENCE!>++<!> // Here smart cast should not be performed due to a successor
|
||||||
i = ""
|
i = ""
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+2
-2
@@ -2,7 +2,7 @@ public fun foo() {
|
|||||||
var i: Any = 1
|
var i: Any = 1
|
||||||
if (i is Int) {
|
if (i is Int) {
|
||||||
while (i != 10) {
|
while (i != 10) {
|
||||||
i++
|
i<!UNRESOLVED_REFERENCE!>++<!>
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+2
-2
@@ -13,5 +13,5 @@ fun list(start: String) {
|
|||||||
e = e.next()
|
e = e.next()
|
||||||
}
|
}
|
||||||
// e can never be null but we do not know it
|
// e can never be null but we do not know it
|
||||||
e.hashCode()
|
e<!UNSAFE_CALL!>.<!>hashCode()
|
||||||
}
|
}
|
||||||
|
|||||||
+2
-2
@@ -13,7 +13,7 @@ fun foo(): Bar {
|
|||||||
y = Bar()
|
y = Bar()
|
||||||
while (x != null) {
|
while (x != null) {
|
||||||
// Here call is unsafe because of inner loop
|
// Here call is unsafe because of inner loop
|
||||||
y.next()
|
y<!UNSAFE_CALL!>.<!>next()
|
||||||
while (y != null) {
|
while (y != null) {
|
||||||
if (x == y)
|
if (x == y)
|
||||||
// x is not null because of outer while
|
// x is not null because of outer while
|
||||||
@@ -25,4 +25,4 @@ fun foo(): Bar {
|
|||||||
x = x.next()
|
x = x.next()
|
||||||
}
|
}
|
||||||
return Bar()
|
return Bar()
|
||||||
}
|
}
|
||||||
|
|||||||
Vendored
+4
-4
@@ -30,7 +30,7 @@ fun baz(s: String?) {
|
|||||||
x.hashCode()
|
x.hashCode()
|
||||||
}
|
}
|
||||||
run {
|
run {
|
||||||
x.hashCode()
|
x<!UNSAFE_CALL!>.<!>hashCode()
|
||||||
x = null
|
x = null
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -40,11 +40,11 @@ fun gaz(s: String?) {
|
|||||||
var x = s
|
var x = s
|
||||||
if (x != null) {
|
if (x != null) {
|
||||||
run {
|
run {
|
||||||
x.hashCode()
|
x<!UNSAFE_CALL!>.<!>hashCode()
|
||||||
x = null
|
x = null
|
||||||
}
|
}
|
||||||
run {
|
run {
|
||||||
x.hashCode()
|
x<!UNSAFE_CALL!>.<!>hashCode()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -57,4 +57,4 @@ fun gav(s: String?) {
|
|||||||
}
|
}
|
||||||
x = null
|
x = null
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
-21
@@ -1,21 +0,0 @@
|
|||||||
data class SomeObject(val n: SomeObject?) {
|
|
||||||
fun doSomething(): Boolean = true
|
|
||||||
fun next(): SomeObject? = n
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
fun list(start: SomeObject) {
|
|
||||||
var e: SomeObject?
|
|
||||||
e = start
|
|
||||||
do {
|
|
||||||
// In theory smart cast is possible here
|
|
||||||
// But in practice we have a loop with changing e
|
|
||||||
// ?: should we "or" entrance type info with condition type info?
|
|
||||||
if (!e.doSomething())
|
|
||||||
break
|
|
||||||
// Smart cast here is still not possible
|
|
||||||
e = e.next()
|
|
||||||
} while (e != null)
|
|
||||||
// e can be null because of next()
|
|
||||||
e.doSomething()
|
|
||||||
}
|
|
||||||
@@ -1,3 +1,4 @@
|
|||||||
|
// FIR_IDENTICAL
|
||||||
data class SomeObject(val n: SomeObject?) {
|
data class SomeObject(val n: SomeObject?) {
|
||||||
fun doSomething(): Boolean = true
|
fun doSomething(): Boolean = true
|
||||||
fun next(): SomeObject? = n
|
fun next(): SomeObject? = n
|
||||||
|
|||||||
-12
@@ -1,12 +0,0 @@
|
|||||||
fun x(): Boolean { return true }
|
|
||||||
|
|
||||||
public fun foo(pp: String?): Int {
|
|
||||||
var p = pp
|
|
||||||
do {
|
|
||||||
p!!.length
|
|
||||||
if (p == "abc") break
|
|
||||||
p = null
|
|
||||||
} while (!x())
|
|
||||||
// Smart cast is NOT possible here
|
|
||||||
return p.length
|
|
||||||
}
|
|
||||||
+1
@@ -1,3 +1,4 @@
|
|||||||
|
// FIR_IDENTICAL
|
||||||
fun x(): Boolean { return true }
|
fun x(): Boolean { return true }
|
||||||
|
|
||||||
public fun foo(pp: String?): Int {
|
public fun foo(pp: String?): Int {
|
||||||
|
|||||||
@@ -9,9 +9,9 @@ fun list(start: SomeObject): SomeObject {
|
|||||||
var e: SomeObject? = start
|
var e: SomeObject? = start
|
||||||
for (i in 0..42) {
|
for (i in 0..42) {
|
||||||
// Unsafe calls because of nullable e at the beginning
|
// Unsafe calls because of nullable e at the beginning
|
||||||
e.doSomething()
|
e<!UNSAFE_CALL!>.<!>doSomething()
|
||||||
e = e.next()
|
e = e<!UNSAFE_CALL!>.<!>next()
|
||||||
}
|
}
|
||||||
// Smart cast is not possible here due to next()
|
// Smart cast is not possible here due to next()
|
||||||
return e
|
return e
|
||||||
}
|
}
|
||||||
|
|||||||
+2
-2
@@ -16,5 +16,5 @@ fun list(start: SomeObject) {
|
|||||||
e = e.next()
|
e = e.next()
|
||||||
}
|
}
|
||||||
// e can be null because of next()
|
// e can be null because of next()
|
||||||
e.doSomething()
|
e<!UNSAFE_CALL!>.<!>doSomething()
|
||||||
}
|
}
|
||||||
|
|||||||
+2
-2
@@ -2,8 +2,8 @@ public fun foo() {
|
|||||||
var i: Int? = 1
|
var i: Int? = 1
|
||||||
if (i != null) {
|
if (i != null) {
|
||||||
while (i != 10) {
|
while (i != 10) {
|
||||||
i++ // Here smart cast should not be performed due to a successor
|
i<!UNSAFE_CALL!>++<!> // Here smart cast should not be performed due to a successor
|
||||||
i = null
|
i = null
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+2
-2
@@ -2,7 +2,7 @@ public fun foo() {
|
|||||||
var i: Int? = 1
|
var i: Int? = 1
|
||||||
if (i != null) {
|
if (i != null) {
|
||||||
while (i != 10) {
|
while (i != 10) {
|
||||||
i++
|
i<!UNSAFE_CALL!>++<!>
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+2
-2
@@ -13,5 +13,5 @@ fun list(start: SomeObject) {
|
|||||||
e = e.next()
|
e = e.next()
|
||||||
}
|
}
|
||||||
// e can be null because of next()
|
// e can be null because of next()
|
||||||
e.doSomething()
|
e<!UNSAFE_CALL!>.<!>doSomething()
|
||||||
}
|
}
|
||||||
|
|||||||
+6
@@ -37516,6 +37516,12 @@ public class BlackBoxCodegenTestGenerated extends AbstractBlackBoxCodegenTest {
|
|||||||
runTest("compiler/testData/codegen/box/smartCasts/kt42517.kt");
|
runTest("compiler/testData/codegen/box/smartCasts/kt42517.kt");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@TestMetadata("kt44804.kt")
|
||||||
|
public void testKt44804() throws Exception {
|
||||||
|
runTest("compiler/testData/codegen/box/smartCasts/kt44804.kt");
|
||||||
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
@TestMetadata("lambdaArgumentWithoutType.kt")
|
@TestMetadata("lambdaArgumentWithoutType.kt")
|
||||||
public void testLambdaArgumentWithoutType() throws Exception {
|
public void testLambdaArgumentWithoutType() throws Exception {
|
||||||
|
|||||||
+6
@@ -37516,6 +37516,12 @@ public class IrBlackBoxCodegenTestGenerated extends AbstractIrBlackBoxCodegenTes
|
|||||||
runTest("compiler/testData/codegen/box/smartCasts/kt42517.kt");
|
runTest("compiler/testData/codegen/box/smartCasts/kt42517.kt");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@TestMetadata("kt44804.kt")
|
||||||
|
public void testKt44804() throws Exception {
|
||||||
|
runTest("compiler/testData/codegen/box/smartCasts/kt44804.kt");
|
||||||
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
@TestMetadata("lambdaArgumentWithoutType.kt")
|
@TestMetadata("lambdaArgumentWithoutType.kt")
|
||||||
public void testLambdaArgumentWithoutType() throws Exception {
|
public void testLambdaArgumentWithoutType() throws Exception {
|
||||||
|
|||||||
+5
@@ -29984,6 +29984,11 @@ public class LightAnalysisModeTestGenerated extends AbstractLightAnalysisModeTes
|
|||||||
runTest("compiler/testData/codegen/box/smartCasts/kt42517.kt");
|
runTest("compiler/testData/codegen/box/smartCasts/kt42517.kt");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@TestMetadata("kt44804.kt")
|
||||||
|
public void testKt44804() throws Exception {
|
||||||
|
runTest("compiler/testData/codegen/box/smartCasts/kt44804.kt");
|
||||||
|
}
|
||||||
|
|
||||||
@TestMetadata("lambdaArgumentWithoutType.kt")
|
@TestMetadata("lambdaArgumentWithoutType.kt")
|
||||||
public void testLambdaArgumentWithoutType() throws Exception {
|
public void testLambdaArgumentWithoutType() throws Exception {
|
||||||
runTest("compiler/testData/codegen/box/smartCasts/lambdaArgumentWithoutType.kt");
|
runTest("compiler/testData/codegen/box/smartCasts/lambdaArgumentWithoutType.kt");
|
||||||
|
|||||||
@@ -19,8 +19,8 @@ fun case_1() {
|
|||||||
<!DEBUG_INFO_EXPRESSION_TYPE("kotlin.String & kotlin.String")!>b<!>.length
|
<!DEBUG_INFO_EXPRESSION_TYPE("kotlin.String & kotlin.String")!>b<!>.length
|
||||||
}
|
}
|
||||||
|
|
||||||
<!DEBUG_INFO_EXPRESSION_TYPE("kotlin.String & kotlin.String")!>b<!>
|
<!DEBUG_INFO_EXPRESSION_TYPE("kotlin.String")!>b<!>
|
||||||
<!DEBUG_INFO_EXPRESSION_TYPE("kotlin.String & kotlin.String")!>b<!>.length
|
<!DEBUG_INFO_EXPRESSION_TYPE("kotlin.String")!>b<!>.length
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -41,8 +41,8 @@ fun case_2() {
|
|||||||
<!DEBUG_INFO_EXPRESSION_TYPE("kotlin.String & kotlin.String")!>b<!>.length
|
<!DEBUG_INFO_EXPRESSION_TYPE("kotlin.String & kotlin.String")!>b<!>.length
|
||||||
}
|
}
|
||||||
|
|
||||||
<!DEBUG_INFO_EXPRESSION_TYPE("kotlin.String & kotlin.String")!>b<!>
|
<!DEBUG_INFO_EXPRESSION_TYPE("kotlin.String")!>b<!>
|
||||||
<!DEBUG_INFO_EXPRESSION_TYPE("kotlin.String & kotlin.String")!>b<!>.length
|
<!DEBUG_INFO_EXPRESSION_TYPE("kotlin.String")!>b<!>.length
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -107,8 +107,8 @@ fun case_5() {
|
|||||||
<!DEBUG_INFO_EXPRESSION_TYPE("kotlin.String & kotlin.String")!>b<!>.length
|
<!DEBUG_INFO_EXPRESSION_TYPE("kotlin.String & kotlin.String")!>b<!>.length
|
||||||
}
|
}
|
||||||
|
|
||||||
<!DEBUG_INFO_EXPRESSION_TYPE("kotlin.String & kotlin.String")!>b<!>
|
<!DEBUG_INFO_EXPRESSION_TYPE("kotlin.String")!>b<!>
|
||||||
<!DEBUG_INFO_EXPRESSION_TYPE("kotlin.String & kotlin.String")!>b<!>.length
|
<!DEBUG_INFO_EXPRESSION_TYPE("kotlin.String")!>b<!>.length
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -240,12 +240,12 @@ fun case_12() {
|
|||||||
<!DEBUG_INFO_EXPRESSION_TYPE("kotlin.String & kotlin.String")!>b<!>
|
<!DEBUG_INFO_EXPRESSION_TYPE("kotlin.String & kotlin.String")!>b<!>
|
||||||
<!DEBUG_INFO_EXPRESSION_TYPE("kotlin.String & kotlin.String")!>b<!>.length
|
<!DEBUG_INFO_EXPRESSION_TYPE("kotlin.String & kotlin.String")!>b<!>.length
|
||||||
while (if (true) { b = a; true } else true) {
|
while (if (true) { b = a; true } else true) {
|
||||||
<!DEBUG_INFO_EXPRESSION_TYPE("kotlin.String & kotlin.String")!>b<!>
|
<!DEBUG_INFO_EXPRESSION_TYPE("kotlin.String")!>b<!>
|
||||||
<!DEBUG_INFO_EXPRESSION_TYPE("kotlin.String & kotlin.String")!>b<!>.length
|
<!DEBUG_INFO_EXPRESSION_TYPE("kotlin.String")!>b<!>.length
|
||||||
}
|
}
|
||||||
|
|
||||||
<!DEBUG_INFO_EXPRESSION_TYPE("kotlin.String & kotlin.String")!>b<!>
|
<!DEBUG_INFO_EXPRESSION_TYPE("kotlin.String")!>b<!>
|
||||||
<!DEBUG_INFO_EXPRESSION_TYPE("kotlin.String & kotlin.String")!>b<!>.length
|
<!DEBUG_INFO_EXPRESSION_TYPE("kotlin.String")!>b<!>.length
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -276,8 +276,8 @@ fun case_14() {
|
|||||||
<!DEBUG_INFO_EXPRESSION_TYPE("kotlin.String & kotlin.String")!>b<!>.length
|
<!DEBUG_INFO_EXPRESSION_TYPE("kotlin.String & kotlin.String")!>b<!>.length
|
||||||
while (true) {
|
while (true) {
|
||||||
if (true) { b = a; } else 3
|
if (true) { b = a; } else 3
|
||||||
<!DEBUG_INFO_EXPRESSION_TYPE("kotlin.String & kotlin.String")!>b<!>
|
<!DEBUG_INFO_EXPRESSION_TYPE("kotlin.String")!>b<!>
|
||||||
<!DEBUG_INFO_EXPRESSION_TYPE("kotlin.String & kotlin.String")!>b<!>.length
|
<!DEBUG_INFO_EXPRESSION_TYPE("kotlin.String")!>b<!>.length
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -11,8 +11,8 @@ fun case_1() {
|
|||||||
var x: Any? = null
|
var x: Any? = null
|
||||||
if (x == null) return
|
if (x == null) return
|
||||||
do {
|
do {
|
||||||
<!DEBUG_INFO_EXPRESSION_TYPE("kotlin.Any & kotlin.Any?")!>x<!>
|
<!DEBUG_INFO_EXPRESSION_TYPE("kotlin.Any?")!>x<!>
|
||||||
x = x.equals(10)
|
x = x<!UNSAFE_CALL!>.<!>equals(10)
|
||||||
} while (x != null)
|
} while (x != null)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -25,8 +25,8 @@ fun case_2() {
|
|||||||
var x: Any? = null
|
var x: Any? = null
|
||||||
if (x === null) return
|
if (x === null) return
|
||||||
do {
|
do {
|
||||||
<!DEBUG_INFO_EXPRESSION_TYPE("kotlin.Any & kotlin.Any?")!>x<!>
|
<!DEBUG_INFO_EXPRESSION_TYPE("kotlin.Any?")!>x<!>
|
||||||
x = x.equals(10)
|
x = x<!UNSAFE_CALL!>.<!>equals(10)
|
||||||
} while (x !== null)
|
} while (x !== null)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -57,8 +57,8 @@ fun case_5() {
|
|||||||
var x: Any? = null
|
var x: Any? = null
|
||||||
if (x == null) return
|
if (x == null) return
|
||||||
do {
|
do {
|
||||||
<!DEBUG_INFO_EXPRESSION_TYPE("kotlin.Any & kotlin.Any?")!>x<!>
|
<!DEBUG_INFO_EXPRESSION_TYPE("kotlin.Any?")!>x<!>
|
||||||
x = x.equals(10)
|
x = x<!UNSAFE_CALL!>.<!>equals(10)
|
||||||
} while (x !== null)
|
} while (x !== null)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -71,8 +71,8 @@ fun case_6() {
|
|||||||
var x: Any? = null
|
var x: Any? = null
|
||||||
if (x === null) return
|
if (x === null) return
|
||||||
do {
|
do {
|
||||||
<!DEBUG_INFO_EXPRESSION_TYPE("kotlin.Any & kotlin.Any?")!>x<!>
|
<!DEBUG_INFO_EXPRESSION_TYPE("kotlin.Any?")!>x<!>
|
||||||
x = x.equals(10)
|
x = x<!UNSAFE_CALL!>.<!>equals(10)
|
||||||
} while (x != null)
|
} while (x != null)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -85,8 +85,8 @@ fun case_7() {
|
|||||||
var x: Any? = null
|
var x: Any? = null
|
||||||
x ?: return
|
x ?: return
|
||||||
do {
|
do {
|
||||||
<!DEBUG_INFO_EXPRESSION_TYPE("kotlin.Any & kotlin.Any?")!>x<!>
|
<!DEBUG_INFO_EXPRESSION_TYPE("kotlin.Any?")!>x<!>
|
||||||
x = x.equals(10)
|
x = x<!UNSAFE_CALL!>.<!>equals(10)
|
||||||
} while (x !== null)
|
} while (x !== null)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -99,8 +99,8 @@ fun case_8() {
|
|||||||
var x: Any? = null
|
var x: Any? = null
|
||||||
if (x == null) throw Exception()
|
if (x == null) throw Exception()
|
||||||
do {
|
do {
|
||||||
<!DEBUG_INFO_EXPRESSION_TYPE("kotlin.Any & kotlin.Any?")!>x<!>
|
<!DEBUG_INFO_EXPRESSION_TYPE("kotlin.Any?")!>x<!>
|
||||||
x = x.equals(10)
|
x = x<!UNSAFE_CALL!>.<!>equals(10)
|
||||||
} while (x != null)
|
} while (x != null)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -113,8 +113,8 @@ fun case_9() {
|
|||||||
var x: Any? = null
|
var x: Any? = null
|
||||||
x ?: throw Exception()
|
x ?: throw Exception()
|
||||||
do {
|
do {
|
||||||
<!DEBUG_INFO_EXPRESSION_TYPE("kotlin.Any & kotlin.Any?")!>x<!>
|
<!DEBUG_INFO_EXPRESSION_TYPE("kotlin.Any?")!>x<!>
|
||||||
x = x.equals(10)
|
x = x<!UNSAFE_CALL!>.<!>equals(10)
|
||||||
} while (x !== null)
|
} while (x !== null)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -127,8 +127,8 @@ fun case_10() {
|
|||||||
var x: Any? = null
|
var x: Any? = null
|
||||||
x as Any
|
x as Any
|
||||||
do {
|
do {
|
||||||
<!DEBUG_INFO_EXPRESSION_TYPE("kotlin.Any & kotlin.Any?")!>x<!>
|
<!DEBUG_INFO_EXPRESSION_TYPE("kotlin.Any?")!>x<!>
|
||||||
x = x.equals(10)
|
x = x<!UNSAFE_CALL!>.<!>equals(10)
|
||||||
} while (x != null)
|
} while (x != null)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -155,8 +155,8 @@ fun case_12() {
|
|||||||
var x: Any? = null
|
var x: Any? = null
|
||||||
if (x is Any) {
|
if (x is Any) {
|
||||||
do {
|
do {
|
||||||
<!DEBUG_INFO_EXPRESSION_TYPE("kotlin.Any & kotlin.Any?")!>x<!>
|
<!DEBUG_INFO_EXPRESSION_TYPE("kotlin.Any?")!>x<!>
|
||||||
x = x .equals(10)
|
x = x <!UNSAFE_CALL!>.<!>equals(10)
|
||||||
} while (x != null)
|
} while (x != null)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -170,8 +170,8 @@ fun case_13() {
|
|||||||
var x: Any? = null
|
var x: Any? = null
|
||||||
if (x != null) {
|
if (x != null) {
|
||||||
do {
|
do {
|
||||||
<!DEBUG_INFO_EXPRESSION_TYPE("kotlin.Any & kotlin.Any?")!>x<!>
|
<!DEBUG_INFO_EXPRESSION_TYPE("kotlin.Any?")!>x<!>
|
||||||
x = x .equals(10)
|
x = x <!UNSAFE_CALL!>.<!>equals(10)
|
||||||
} while (x != null)
|
} while (x != null)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -185,8 +185,8 @@ fun case_14() {
|
|||||||
var x: Any? = null
|
var x: Any? = null
|
||||||
if (x == null) return
|
if (x == null) return
|
||||||
do {
|
do {
|
||||||
<!DEBUG_INFO_EXPRESSION_TYPE("kotlin.Any & kotlin.Any?")!>x<!>
|
<!DEBUG_INFO_EXPRESSION_TYPE("kotlin.Any?")!>x<!>
|
||||||
x = x.equals(10)
|
x = x<!UNSAFE_CALL!>.<!>equals(10)
|
||||||
} while (x is Any)
|
} while (x is Any)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -199,8 +199,8 @@ fun case_15() {
|
|||||||
var x: Any? = null
|
var x: Any? = null
|
||||||
if (x is Any) {
|
if (x is Any) {
|
||||||
do {
|
do {
|
||||||
<!DEBUG_INFO_EXPRESSION_TYPE("kotlin.Any & kotlin.Any?")!>x<!>
|
<!DEBUG_INFO_EXPRESSION_TYPE("kotlin.Any?")!>x<!>
|
||||||
x = x .equals(10)
|
x = x <!UNSAFE_CALL!>.<!>equals(10)
|
||||||
} while (x is Any)
|
} while (x is Any)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
js/js.tests/tests-gen/org/jetbrains/kotlin/js/test/es6/semantics/IrJsCodegenBoxES6TestGenerated.java
Generated
+5
@@ -25530,6 +25530,11 @@ public class IrJsCodegenBoxES6TestGenerated extends AbstractIrJsCodegenBoxES6Tes
|
|||||||
runTest("compiler/testData/codegen/box/smartCasts/kt42517.kt");
|
runTest("compiler/testData/codegen/box/smartCasts/kt42517.kt");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@TestMetadata("kt44804.kt")
|
||||||
|
public void testKt44804() throws Exception {
|
||||||
|
runTest("compiler/testData/codegen/box/smartCasts/kt44804.kt");
|
||||||
|
}
|
||||||
|
|
||||||
@TestMetadata("lambdaArgumentWithoutType.kt")
|
@TestMetadata("lambdaArgumentWithoutType.kt")
|
||||||
public void testLambdaArgumentWithoutType() throws Exception {
|
public void testLambdaArgumentWithoutType() throws Exception {
|
||||||
runTest("compiler/testData/codegen/box/smartCasts/lambdaArgumentWithoutType.kt");
|
runTest("compiler/testData/codegen/box/smartCasts/lambdaArgumentWithoutType.kt");
|
||||||
|
|||||||
Generated
+5
@@ -25015,6 +25015,11 @@ public class IrJsCodegenBoxTestGenerated extends AbstractIrJsCodegenBoxTest {
|
|||||||
runTest("compiler/testData/codegen/box/smartCasts/kt42517.kt");
|
runTest("compiler/testData/codegen/box/smartCasts/kt42517.kt");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@TestMetadata("kt44804.kt")
|
||||||
|
public void testKt44804() throws Exception {
|
||||||
|
runTest("compiler/testData/codegen/box/smartCasts/kt44804.kt");
|
||||||
|
}
|
||||||
|
|
||||||
@TestMetadata("lambdaArgumentWithoutType.kt")
|
@TestMetadata("lambdaArgumentWithoutType.kt")
|
||||||
public void testLambdaArgumentWithoutType() throws Exception {
|
public void testLambdaArgumentWithoutType() throws Exception {
|
||||||
runTest("compiler/testData/codegen/box/smartCasts/lambdaArgumentWithoutType.kt");
|
runTest("compiler/testData/codegen/box/smartCasts/lambdaArgumentWithoutType.kt");
|
||||||
|
|||||||
Generated
+5
@@ -24975,6 +24975,11 @@ public class JsCodegenBoxTestGenerated extends AbstractJsCodegenBoxTest {
|
|||||||
runTest("compiler/testData/codegen/box/smartCasts/kt42517.kt");
|
runTest("compiler/testData/codegen/box/smartCasts/kt42517.kt");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@TestMetadata("kt44804.kt")
|
||||||
|
public void testKt44804() throws Exception {
|
||||||
|
runTest("compiler/testData/codegen/box/smartCasts/kt44804.kt");
|
||||||
|
}
|
||||||
|
|
||||||
@TestMetadata("lambdaArgumentWithoutType.kt")
|
@TestMetadata("lambdaArgumentWithoutType.kt")
|
||||||
public void testLambdaArgumentWithoutType() throws Exception {
|
public void testLambdaArgumentWithoutType() throws Exception {
|
||||||
runTest("compiler/testData/codegen/box/smartCasts/lambdaArgumentWithoutType.kt");
|
runTest("compiler/testData/codegen/box/smartCasts/lambdaArgumentWithoutType.kt");
|
||||||
|
|||||||
js/js.tests/tests-gen/org/jetbrains/kotlin/js/test/wasm/semantics/IrCodegenBoxWasmTestGenerated.java
Generated
+5
@@ -13597,6 +13597,11 @@ public class IrCodegenBoxWasmTestGenerated extends AbstractIrCodegenBoxWasmTest
|
|||||||
runTest("compiler/testData/codegen/box/smartCasts/kt19100.kt");
|
runTest("compiler/testData/codegen/box/smartCasts/kt19100.kt");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@TestMetadata("kt44804.kt")
|
||||||
|
public void testKt44804() throws Exception {
|
||||||
|
runTest("compiler/testData/codegen/box/smartCasts/kt44804.kt");
|
||||||
|
}
|
||||||
|
|
||||||
@TestMetadata("multipleSmartCast.kt")
|
@TestMetadata("multipleSmartCast.kt")
|
||||||
public void testMultipleSmartCast() throws Exception {
|
public void testMultipleSmartCast() throws Exception {
|
||||||
runTest("compiler/testData/codegen/box/smartCasts/multipleSmartCast.kt");
|
runTest("compiler/testData/codegen/box/smartCasts/multipleSmartCast.kt");
|
||||||
|
|||||||
Reference in New Issue
Block a user