FIR DFA: remove RealVariableAndType

This commit is contained in:
pyos
2022-11-03 15:05:28 +01:00
committed by teamcity
parent 33363ba1fc
commit 7c8e9ac316
13 changed files with 133 additions and 187 deletions
@@ -1286,32 +1286,35 @@ digraph boundSmartcastsInBranches_kt {
506 [label="Exit when branch result"];
507 [label="Exit when"];
}
508 [label="Access variable R|<local>/b|"];
509 [label="Access variable <Inapplicable(UNSAFE_CALL): kotlin/String.length>#"];
subgraph cluster_97 {
color=blue
508 [label="Enter when"];
510 [label="Enter when"];
subgraph cluster_98 {
color=blue
509 [label="Enter when branch condition "];
510 [label="Access variable R|<local>/a|"];
511 [label="Const: Null(null)"];
512 [label="Equality operator !="];
513 [label="Exit when branch condition"];
511 [label="Enter when branch condition "];
512 [label="Access variable R|<local>/a|"];
513 [label="Const: Null(null)"];
514 [label="Equality operator !="];
515 [label="Exit when branch condition"];
}
514 [label="Synthetic else branch"];
515 [label="Enter when branch result"];
516 [label="Synthetic else branch"];
517 [label="Enter when branch result"];
subgraph cluster_99 {
color=blue
516 [label="Enter block"];
517 [label="Access variable R|<local>/b|"];
518 [label="Access variable <Inapplicable(UNSAFE_CALL): kotlin/String.length>#"];
519 [label="Exit block"];
518 [label="Enter block"];
519 [label="Access variable R|<local>/b|"];
520 [label="Smart cast: R|<local>/b|"];
521 [label="Access variable R|kotlin/String.length|"];
522 [label="Exit block"];
}
520 [label="Exit when branch result"];
521 [label="Exit when"];
523 [label="Exit when branch result"];
524 [label="Exit when"];
}
522 [label="Exit block"];
525 [label="Exit block"];
}
523 [label="Exit function test_9" style="filled" fillcolor=red];
526 [label="Exit function test_9" style="filled" fillcolor=red];
}
480 -> {481};
481 -> {482};
@@ -1346,15 +1349,18 @@ digraph boundSmartcastsInBranches_kt {
510 -> {511};
511 -> {512};
512 -> {513};
513 -> {515 514};
514 -> {521};
515 -> {516};
516 -> {517};
513 -> {514};
514 -> {515};
515 -> {517 516};
516 -> {524};
517 -> {518};
518 -> {519};
519 -> {520};
520 -> {521};
521 -> {522};
522 -> {523};
523 -> {524};
524 -> {525};
525 -> {526};
}
@@ -223,9 +223,10 @@ FILE: boundSmartcastsInBranches.kt
}
}
R|<local>/b|.<Inapplicable(UNSAFE_CALL): kotlin/String.length>#
when () {
!=(R|<local>/a|, Null(null)) -> {
R|<local>/b|.<Inapplicable(UNSAFE_CALL): kotlin/String.length>#
R|<local>/b|.R|kotlin/String.length|
}
}
@@ -170,7 +170,8 @@ fun test_9() {
} else {
b = a
}
b<!UNSAFE_CALL!>.<!>length // bad
if (a != null) {
b<!UNSAFE_CALL!>.<!>length // ok
b.length // ok
}
}
@@ -39,7 +39,6 @@ import org.jetbrains.kotlin.fir.visitors.transformSingle
import org.jetbrains.kotlin.name.StandardClassIds
import org.jetbrains.kotlin.types.ConstantValueKind
import org.jetbrains.kotlin.util.OperatorNameConventions
import org.jetbrains.kotlin.utils.addIfNotNull
import org.jetbrains.kotlin.utils.addToStdlib.firstIsInstanceOrNull
class DataFlowAnalyzerContext<FLOW : Flow>(
@@ -104,15 +103,13 @@ abstract class FirDataFlowAnalyzer<FLOW : Flow>(
val symbol = variable.identifier.symbol
val index = receiverStack.getReceiverIndex(symbol) ?: return
val info = flow.getTypeStatement(variable)
val type = if (info == null) {
receiverStack.getOriginalType(index)
} else {
val types = info.exactType.toMutableList().also {
it += receiverStack.getOriginalType(index)
}
val info = flow.getType(variable)
val type = if (info.isNotEmpty()) {
val types = info.toMutableList()
types += receiverStack.getOriginalType(index)
context.intersectTypesOrNull(types)!!
} else {
receiverStack.getOriginalType(index)
}
receiverStack.replaceReceiverType(index, type)
}
@@ -200,15 +197,8 @@ abstract class FirDataFlowAnalyzer<FLOW : Flow>(
expression: FirExpression
): Pair<PropertyStability, MutableList<ConeKotlinType>>? {
val flow = graphBuilder.lastNode.flow
var variable = variableStorage.getRealVariableWithoutUnwrappingAlias(flow, symbol, expression) ?: return null
val stability = variable.stability
val result = mutableListOf<ConeKotlinType>()
flow.directAliasMap[variable]?.let {
result.addIfNotNull(it.originalType)
variable = it.variable
}
flow.getTypeStatement(variable)?.exactType?.let { result += it }
return result.takeIf { it.isNotEmpty() }?.let { stability to it }
val variable = variableStorage.getRealVariableWithoutUnwrappingAlias(flow, symbol, expression) ?: return null
return flow.getType(variable)?.takeIf { it.isNotEmpty() }?.let { variable.stability to it.toMutableList() }
}
fun returnExpressionsOfAnonymousFunction(function: FirAnonymousFunction): Collection<FirStatement> {
@@ -1251,11 +1241,7 @@ abstract class FirDataFlowAnalyzer<FLOW : Flow>(
initializerVariable.isStable || (initializerVariable.hasLocalStability && initializer.isAccessToStableVariable())
if (!hasExplicitType && isInitializerStable && (propertyVariable.hasLocalStability || propertyVariable.isStable)) {
logicSystem.addLocalVariableAlias(
flow, propertyVariable,
RealVariableAndType(initializerVariable, initializer.coneType)
)
// node.flow.addImplication((propertyVariable notEq null) implies (initializerVariable notEq null))
logicSystem.addLocalVariableAlias(flow, propertyVariable, initializerVariable)
} else {
logicSystem.replaceVariableFromConditionInStatements(flow, initializerVariable, propertyVariable)
}
@@ -76,26 +76,6 @@ class RealVariable(
}
}
class RealVariableAndType(val variable: RealVariable, val originalType: ConeKotlinType?) {
override fun equals(other: Any?): Boolean {
if (this === other) return true
if (javaClass != other?.javaClass) return false
other as RealVariableAndType
if (variable != other.variable) return false
if (originalType != other.originalType) return false
return true
}
override fun hashCode(): Int {
var result = variable.hashCode()
result = 31 * result + originalType.hashCode()
return result
}
}
class SyntheticVariable(val fir: FirElement, variableIndexForDebug: Int) : DataFlowVariable(variableIndexForDebug) {
override fun equals(other: Any?): Boolean {
if (this === other) return true
@@ -5,17 +5,9 @@
package org.jetbrains.kotlin.fir.resolve.dfa
import org.jetbrains.kotlin.fir.types.ConeKotlinType
abstract class Flow {
abstract fun getTypeStatement(variable: RealVariable): TypeStatement?
abstract fun getImplications(variable: DataFlowVariable): Collection<Implication>
abstract fun getVariablesInTypeStatements(): Collection<RealVariable>
abstract fun removeOperations(variable: DataFlowVariable): Collection<Implication>
abstract val directAliasMap: Map<RealVariable, RealVariableAndType>
abstract val backwardsAliasMap: Map<RealVariable, List<RealVariable>>
abstract val assignmentIndex: Map<RealVariable, Int>
}
fun Flow.unwrapVariable(variable: RealVariable): RealVariable {
return directAliasMap[variable]?.variable ?: variable
abstract fun unwrapVariable(variable: RealVariable): RealVariable
abstract fun getType(variable: RealVariable): Set<ConeKotlinType>?
}
@@ -48,7 +48,7 @@ abstract class LogicSystem<FLOW : Flow>(protected val context: ConeInferenceCont
shouldRemoveSynthetics: Boolean,
): FLOW
abstract fun addLocalVariableAlias(flow: FLOW, alias: RealVariable, underlyingVariable: RealVariableAndType)
abstract fun addLocalVariableAlias(flow: FLOW, alias: RealVariable, underlyingVariable: RealVariable)
abstract fun removeLocalVariableAlias(flow: FLOW, alias: RealVariable)
abstract fun recordNewAssignment(flow: FLOW, variable: RealVariable, index: Int)
@@ -126,7 +126,7 @@ abstract class LogicSystem<FLOW : Flow>(protected val context: ConeInferenceCont
op: (Collection<Set<ConeKotlinType>>) -> MutableSet<ConeKotlinType>
): MutableTypeStatement {
require(statements.isNotEmpty())
statements.singleOrNull()?.let { return it as MutableTypeStatement }
statements.singleOrNull()?.let { return it.asMutableStatement() }
val variable = statements.first().variable
assert(statements.all { it.variable == variable })
val exactType = op.invoke(statements.map { it.exactType })
@@ -9,7 +9,6 @@ import com.google.common.collect.ArrayListMultimap
import kotlinx.collections.immutable.*
import org.jetbrains.kotlin.fir.types.ConeInferenceContext
import org.jetbrains.kotlin.fir.types.ConeKotlinType
import org.jetbrains.kotlin.utils.addIfNotNull
import java.util.*
import kotlin.math.max
@@ -51,10 +50,10 @@ class PersistentFlow : Flow {
* directAliasMap: { x -> a, y -> a}
* backwardsAliasMap: { a -> [x, y] }
*/
override var directAliasMap: PersistentMap<RealVariable, RealVariableAndType>
override var backwardsAliasMap: PersistentMap<RealVariable, PersistentList<RealVariable>>
var directAliasMap: PersistentMap<RealVariable, RealVariable>
var backwardsAliasMap: PersistentMap<RealVariable, PersistentList<RealVariable>>
override var assignmentIndex: PersistentMap<RealVariable, Int>
var assignmentIndex: PersistentMap<RealVariable, Int>
constructor(previousFlow: PersistentFlow) {
this.previousFlow = previousFlow
@@ -78,24 +77,22 @@ class PersistentFlow : Flow {
assignmentIndex = persistentMapOf()
}
override fun getTypeStatement(variable: RealVariable): TypeStatement? {
return approvedTypeStatements[variable]
override fun unwrapVariable(variable: RealVariable): RealVariable {
return directAliasMap[variable] ?: variable
}
override fun getImplications(variable: DataFlowVariable): Collection<Implication> {
return logicStatements[variable] ?: emptyList()
}
override fun getVariablesInTypeStatements(): Collection<RealVariable> {
return approvedTypeStatements.keys
}
override fun removeOperations(variable: DataFlowVariable): Collection<Implication> {
return getImplications(variable).also {
if (it.isNotEmpty()) {
logicStatements -= variable
}
fun getTypeStatement(variable: RealVariable): TypeStatement {
val result = MutableTypeStatement(variable)
approvedTypeStatements[variable]?.let { result += it }
val variableUnderAlias = directAliasMap[variable]
if (variableUnderAlias != null) {
approvedTypeStatements[variableUnderAlias]?.let { result += it }
}
return result
}
override fun getType(variable: RealVariable): Set<ConeKotlinType> {
return getTypeStatement(variable).exactType
}
}
@@ -110,7 +107,7 @@ abstract class PersistentLogicSystem(context: ConeInferenceContext) : LogicSyste
override fun joinFlow(flows: Collection<PersistentFlow>): PersistentFlow {
// One input flow executes - one set of statements is true, others might be false.
return foldFlow(flows) { variable -> or(flows.map { it.getApprovedTypeStatements(variable) }).takeIf { it.isNotEmpty } }
return foldFlow(flows) { variable -> or(flows.map { it.getTypeStatement(variable) }).takeIf { it.isNotEmpty } }
}
override fun unionFlow(flows: Collection<PersistentFlow>): PersistentFlow {
@@ -120,7 +117,7 @@ abstract class PersistentLogicSystem(context: ConeInferenceContext) : LogicSyste
// happened last (and the flows that don't reassign may or may not have executed after that).
return foldFlow(flows) { variable ->
or(flows.groupBy { it.assignmentIndex[variable] ?: -1 }.values.map { flowSubset ->
and(flowSubset.map { it.getApprovedTypeStatements(variable) })
and(flowSubset.map { it.getTypeStatement(variable) })
})
}
}
@@ -166,16 +163,16 @@ abstract class PersistentLogicSystem(context: ConeInferenceContext) : LogicSyste
return commonFlow
}
private fun computeCommonAliases(flows: Collection<PersistentFlow>): Map<RealVariable, RealVariableAndType> =
private fun computeCommonAliases(flows: Collection<PersistentFlow>): Map<RealVariable, RealVariable> =
flows.first().directAliasMap.filterTo(mutableMapOf()) { (variable, alias) ->
flows.all { it.directAliasMap[variable] == alias }
}
override fun addLocalVariableAlias(flow: PersistentFlow, alias: RealVariable, underlyingVariable: RealVariableAndType) {
override fun addLocalVariableAlias(flow: PersistentFlow, alias: RealVariable, underlyingVariable: RealVariable) {
removeLocalVariableAlias(flow, alias)
flow.directAliasMap = flow.directAliasMap.put(alias, underlyingVariable)
flow.backwardsAliasMap = flow.backwardsAliasMap.put(
underlyingVariable.variable,
underlyingVariable,
{ persistentListOf(alias) },
{ variables -> variables + alias }
)
@@ -221,7 +218,7 @@ abstract class PersistentLogicSystem(context: ConeInferenceContext) : LogicSyste
processApprovedStatements(isDiff = true)
}
val original = flow.directAliasMap[alias]?.variable
val original = flow.directAliasMap[alias]
if (original != null) {
flow.directAliasMap = flow.directAliasMap.remove(alias)
val updatedBackwardsAliasList = flow.backwardsAliasMap.getValue(original).remove(alias)
@@ -252,23 +249,6 @@ abstract class PersistentLogicSystem(context: ConeInferenceContext) : LogicSyste
return statement as T
}
@OptIn(DfaInternals::class)
private fun PersistentFlow.getApprovedTypeStatements(variable: RealVariable): MutableTypeStatement {
var flow = this
val result = MutableTypeStatement(variable)
val variableUnderAlias = directAliasMap[variable]
if (variableUnderAlias == null) {
flow.approvedTypeStatements[variable]?.let {
result += it
}
} else {
result.exactType.addIfNotNull(variableUnderAlias.originalType)
flow.approvedTypeStatements[variableUnderAlias.variable]?.let { result += it }
}
return result
}
override fun addTypeStatement(flow: PersistentFlow, statement: TypeStatement) {
if (statement.isEmpty) return
with(flow) {
@@ -56,8 +56,7 @@ class VariableStorageImpl(private val session: FirSession) : VariableStorage() {
fir: FirElement,
stability: PropertyStability
): RealVariable {
val variable = getOrCreateRealVariableWithoutUnwrappingAlias(flow, symbol, fir, stability)
return flow.directAliasMap[variable]?.variable ?: variable
return flow.unwrapVariable(getOrCreateRealVariableWithoutUnwrappingAlias(flow, symbol, fir, stability))
}
private fun FirElement.unwrapElement(): FirElement = when (this) {
@@ -265,7 +265,8 @@ FILE fqName:<root> fileName:/suspendConversionOnArbitraryExpression.kt
TYPE_OP type=kotlin.coroutines.SuspendFunction0<kotlin.Unit> origin=CAST typeOperand=kotlin.coroutines.SuspendFunction0<kotlin.Unit>
GET_VAR 'var b: kotlin.Function0<kotlin.Unit> [var] declared in <root>.testSmartCastOnVarVsSuspendConversion' type=kotlin.Function0<kotlin.Unit> origin=null
CALL 'public final fun useSuspend (sfn: kotlin.coroutines.SuspendFunction0<kotlin.Unit>): kotlin.Unit declared in <root>' type=kotlin.Unit origin=null
sfn: GET_VAR 'var b: kotlin.Function0<kotlin.Unit> [var] declared in <root>.testSmartCastOnVarVsSuspendConversion' type=kotlin.Function0<kotlin.Unit> origin=null
sfn: TYPE_OP type=kotlin.coroutines.SuspendFunction0<kotlin.Unit> origin=IMPLICIT_CAST typeOperand=kotlin.coroutines.SuspendFunction0<kotlin.Unit>
GET_VAR 'var b: kotlin.Function0<kotlin.Unit> [var] declared in <root>.testSmartCastOnVarVsSuspendConversion' type=kotlin.Function0<kotlin.Unit> origin=null
FUN name:testIntersectionVsSuspendConversion visibility:public modality:FINAL <T> (x:T of <root>.testIntersectionVsSuspendConversion) returnType:kotlin.Unit
TYPE_PARAMETER name:T index:0 variance: superTypes:[kotlin.Function0<kotlin.Unit>; kotlin.coroutines.SuspendFunction0<kotlin.Unit>] reified:false
VALUE_PARAMETER name:x index:0 type:T of <root>.testIntersectionVsSuspendConversion
@@ -181,7 +181,7 @@ fun testSmartCastVsSuspendConversion(a: Function0<Unit>) {
fun testSmartCastOnVarVsSuspendConversion(a: Function0<Unit>) {
var b: Function0<Unit> = a
b as SuspendFunction0<Unit> /*~> Unit */
useSuspend(sfn = b)
useSuspend(sfn = b /*as SuspendFunction0<Unit> */)
}
fun <T> testIntersectionVsSuspendConversion(x: T) where T : Function0<Unit>, T : SuspendFunction0<Unit> {
@@ -206,20 +206,20 @@ fun <T> T.case_7() {
val x = this
if (x is Interface1?) {
if (x != null) {
<!DEBUG_INFO_EXPRESSION_TYPE("T & T!! & Interface1")!>x<!>
<!DEBUG_INFO_EXPRESSION_TYPE("T & T!! & Interface1")!>x<!>.equals(null)
<!DEBUG_INFO_EXPRESSION_TYPE("T & Interface1 & T!!")!>x<!>
<!DEBUG_INFO_EXPRESSION_TYPE("T & Interface1 & T!!")!>x<!>.equals(null)
x.propT
<!DEBUG_INFO_EXPRESSION_TYPE("T & T!! & Interface1")!>x<!>.propAny
<!DEBUG_INFO_EXPRESSION_TYPE("T & T!! & Interface1")!>x<!>.propNullableT
<!DEBUG_INFO_EXPRESSION_TYPE("T & T!! & Interface1")!>x<!>.propNullableAny
<!DEBUG_INFO_EXPRESSION_TYPE("T & Interface1 & T!!")!>x<!>.propAny
<!DEBUG_INFO_EXPRESSION_TYPE("T & Interface1 & T!!")!>x<!>.propNullableT
<!DEBUG_INFO_EXPRESSION_TYPE("T & Interface1 & T!!")!>x<!>.propNullableAny
x.funT()
<!DEBUG_INFO_EXPRESSION_TYPE("T & T!! & Interface1")!>x<!>.funAny()
<!DEBUG_INFO_EXPRESSION_TYPE("T & T!! & Interface1")!>x<!>.funNullableT()
<!DEBUG_INFO_EXPRESSION_TYPE("T & T!! & Interface1")!>x<!>.funNullableAny()
<!DEBUG_INFO_EXPRESSION_TYPE("T & T!! & Interface1")!>x<!>.itest1()
<!DEBUG_INFO_EXPRESSION_TYPE("T & Interface1 & T!!")!>x<!>.funAny()
<!DEBUG_INFO_EXPRESSION_TYPE("T & Interface1 & T!!")!>x<!>.funNullableT()
<!DEBUG_INFO_EXPRESSION_TYPE("T & Interface1 & T!!")!>x<!>.funNullableAny()
<!DEBUG_INFO_EXPRESSION_TYPE("T & Interface1 & T!!")!>x<!>.itest1()
x.apply {
<!DEBUG_INFO_EXPRESSION_TYPE("T!! & Interface1")!>this<!>
<!DEBUG_INFO_EXPRESSION_TYPE("Interface1 & T!!")!>this<!>
equals(null)
propT
propAny
@@ -230,29 +230,29 @@ fun <T> T.case_7() {
funNullableT()
funNullableAny()
itest1()
<!DEBUG_INFO_EXPRESSION_TYPE("T!! & Interface1")!>this<!>.equals(null)
<!DEBUG_INFO_EXPRESSION_TYPE("T!! & Interface1")!>this<!>.propT
<!DEBUG_INFO_EXPRESSION_TYPE("T!! & Interface1")!>this<!>.propAny
<!DEBUG_INFO_EXPRESSION_TYPE("T!! & Interface1")!>this<!>.propNullableT
<!DEBUG_INFO_EXPRESSION_TYPE("T!! & Interface1")!>this<!>.propNullableAny
<!DEBUG_INFO_EXPRESSION_TYPE("T!! & Interface1")!>this<!>.funT()
<!DEBUG_INFO_EXPRESSION_TYPE("T!! & Interface1")!>this<!>.funAny()
<!DEBUG_INFO_EXPRESSION_TYPE("T!! & Interface1")!>this<!>.funNullableT()
<!DEBUG_INFO_EXPRESSION_TYPE("T!! & Interface1")!>this<!>.funNullableAny()
<!DEBUG_INFO_EXPRESSION_TYPE("T!! & Interface1")!>this<!>.itest1()
<!DEBUG_INFO_EXPRESSION_TYPE("Interface1 & T!!")!>this<!>.equals(null)
<!DEBUG_INFO_EXPRESSION_TYPE("Interface1 & T!!")!>this<!>.propT
<!DEBUG_INFO_EXPRESSION_TYPE("Interface1 & T!!")!>this<!>.propAny
<!DEBUG_INFO_EXPRESSION_TYPE("Interface1 & T!!")!>this<!>.propNullableT
<!DEBUG_INFO_EXPRESSION_TYPE("Interface1 & T!!")!>this<!>.propNullableAny
<!DEBUG_INFO_EXPRESSION_TYPE("Interface1 & T!!")!>this<!>.funT()
<!DEBUG_INFO_EXPRESSION_TYPE("Interface1 & T!!")!>this<!>.funAny()
<!DEBUG_INFO_EXPRESSION_TYPE("Interface1 & T!!")!>this<!>.funNullableT()
<!DEBUG_INFO_EXPRESSION_TYPE("Interface1 & T!!")!>this<!>.funNullableAny()
<!DEBUG_INFO_EXPRESSION_TYPE("Interface1 & T!!")!>this<!>.itest1()
}
x.also {
<!DEBUG_INFO_EXPRESSION_TYPE("T!! & Interface1")!>it<!>
<!DEBUG_INFO_EXPRESSION_TYPE("T!! & Interface1")!>it<!>.itest1()
<!DEBUG_INFO_EXPRESSION_TYPE("T!! & Interface1")!>it<!>.equals(null)
<!DEBUG_INFO_EXPRESSION_TYPE("T!! & Interface1")!>it<!>.propT
<!DEBUG_INFO_EXPRESSION_TYPE("T!! & Interface1")!>it<!>.propAny
<!DEBUG_INFO_EXPRESSION_TYPE("T!! & Interface1")!>it<!>.propNullableT
<!DEBUG_INFO_EXPRESSION_TYPE("T!! & Interface1")!>it<!>.propNullableAny
<!DEBUG_INFO_EXPRESSION_TYPE("T!! & Interface1")!>it<!>.funT()
<!DEBUG_INFO_EXPRESSION_TYPE("T!! & Interface1")!>it<!>.funAny()
<!DEBUG_INFO_EXPRESSION_TYPE("T!! & Interface1")!>it<!>.funNullableT()
<!DEBUG_INFO_EXPRESSION_TYPE("T!! & Interface1")!>it<!>.funNullableAny()
<!DEBUG_INFO_EXPRESSION_TYPE("Interface1 & T!!")!>it<!>
<!DEBUG_INFO_EXPRESSION_TYPE("Interface1 & T!!")!>it<!>.itest1()
<!DEBUG_INFO_EXPRESSION_TYPE("Interface1 & T!!")!>it<!>.equals(null)
<!DEBUG_INFO_EXPRESSION_TYPE("Interface1 & T!!")!>it<!>.propT
<!DEBUG_INFO_EXPRESSION_TYPE("Interface1 & T!!")!>it<!>.propAny
<!DEBUG_INFO_EXPRESSION_TYPE("Interface1 & T!!")!>it<!>.propNullableT
<!DEBUG_INFO_EXPRESSION_TYPE("Interface1 & T!!")!>it<!>.propNullableAny
<!DEBUG_INFO_EXPRESSION_TYPE("Interface1 & T!!")!>it<!>.funT()
<!DEBUG_INFO_EXPRESSION_TYPE("Interface1 & T!!")!>it<!>.funAny()
<!DEBUG_INFO_EXPRESSION_TYPE("Interface1 & T!!")!>it<!>.funNullableT()
<!DEBUG_INFO_EXPRESSION_TYPE("Interface1 & T!!")!>it<!>.funNullableAny()
}
}
}
@@ -258,20 +258,20 @@ fun <T> case_7(y: T) {
val x = y
if (x is Interface1?) {
if (x != null) {
<!DEBUG_INFO_EXPRESSION_TYPE("T & T!! & Interface1")!>x<!>
<!DEBUG_INFO_EXPRESSION_TYPE("T & T!! & Interface1")!>x<!>.equals(null)
<!DEBUG_INFO_EXPRESSION_TYPE("T & Interface1 & T!!")!>x<!>
<!DEBUG_INFO_EXPRESSION_TYPE("T & Interface1 & T!!")!>x<!>.equals(null)
x.propT
<!DEBUG_INFO_EXPRESSION_TYPE("T & T!! & Interface1")!>x<!>.propAny
<!DEBUG_INFO_EXPRESSION_TYPE("T & T!! & Interface1")!>x<!>.propNullableT
<!DEBUG_INFO_EXPRESSION_TYPE("T & T!! & Interface1")!>x<!>.propNullableAny
<!DEBUG_INFO_EXPRESSION_TYPE("T & Interface1 & T!!")!>x<!>.propAny
<!DEBUG_INFO_EXPRESSION_TYPE("T & Interface1 & T!!")!>x<!>.propNullableT
<!DEBUG_INFO_EXPRESSION_TYPE("T & Interface1 & T!!")!>x<!>.propNullableAny
x.funT()
<!DEBUG_INFO_EXPRESSION_TYPE("T & T!! & Interface1")!>x<!>.funAny()
<!DEBUG_INFO_EXPRESSION_TYPE("T & T!! & Interface1")!>x<!>.funNullableT()
<!DEBUG_INFO_EXPRESSION_TYPE("T & T!! & Interface1")!>x<!>.funNullableAny()
<!DEBUG_INFO_EXPRESSION_TYPE("T & T!! & Interface1")!>x<!>.itest()
<!DEBUG_INFO_EXPRESSION_TYPE("T & Interface1 & T!!")!>x<!>.funAny()
<!DEBUG_INFO_EXPRESSION_TYPE("T & Interface1 & T!!")!>x<!>.funNullableT()
<!DEBUG_INFO_EXPRESSION_TYPE("T & Interface1 & T!!")!>x<!>.funNullableAny()
<!DEBUG_INFO_EXPRESSION_TYPE("T & Interface1 & T!!")!>x<!>.itest()
x.apply {
<!DEBUG_INFO_EXPRESSION_TYPE("T!! & Interface1")!>this<!>
<!DEBUG_INFO_EXPRESSION_TYPE("Interface1 & T!!")!>this<!>
equals(null)
propT
propAny
@@ -282,29 +282,29 @@ fun <T> case_7(y: T) {
funNullableT()
funNullableAny()
itest()
<!DEBUG_INFO_EXPRESSION_TYPE("T!! & Interface1")!>this<!>.equals(null)
<!DEBUG_INFO_EXPRESSION_TYPE("T!! & Interface1")!>this<!>.propT
<!DEBUG_INFO_EXPRESSION_TYPE("T!! & Interface1")!>this<!>.propAny
<!DEBUG_INFO_EXPRESSION_TYPE("T!! & Interface1")!>this<!>.propNullableT
<!DEBUG_INFO_EXPRESSION_TYPE("T!! & Interface1")!>this<!>.propNullableAny
<!DEBUG_INFO_EXPRESSION_TYPE("T!! & Interface1")!>this<!>.funT()
<!DEBUG_INFO_EXPRESSION_TYPE("T!! & Interface1")!>this<!>.funAny()
<!DEBUG_INFO_EXPRESSION_TYPE("T!! & Interface1")!>this<!>.funNullableT()
<!DEBUG_INFO_EXPRESSION_TYPE("T!! & Interface1")!>this<!>.funNullableAny()
<!DEBUG_INFO_EXPRESSION_TYPE("T!! & Interface1")!>this<!>.itest()
<!DEBUG_INFO_EXPRESSION_TYPE("Interface1 & T!!")!>this<!>.equals(null)
<!DEBUG_INFO_EXPRESSION_TYPE("Interface1 & T!!")!>this<!>.propT
<!DEBUG_INFO_EXPRESSION_TYPE("Interface1 & T!!")!>this<!>.propAny
<!DEBUG_INFO_EXPRESSION_TYPE("Interface1 & T!!")!>this<!>.propNullableT
<!DEBUG_INFO_EXPRESSION_TYPE("Interface1 & T!!")!>this<!>.propNullableAny
<!DEBUG_INFO_EXPRESSION_TYPE("Interface1 & T!!")!>this<!>.funT()
<!DEBUG_INFO_EXPRESSION_TYPE("Interface1 & T!!")!>this<!>.funAny()
<!DEBUG_INFO_EXPRESSION_TYPE("Interface1 & T!!")!>this<!>.funNullableT()
<!DEBUG_INFO_EXPRESSION_TYPE("Interface1 & T!!")!>this<!>.funNullableAny()
<!DEBUG_INFO_EXPRESSION_TYPE("Interface1 & T!!")!>this<!>.itest()
}
x.also {
<!DEBUG_INFO_EXPRESSION_TYPE("T!! & Interface1")!>it<!>
<!DEBUG_INFO_EXPRESSION_TYPE("T!! & Interface1")!>it<!>.itest()
<!DEBUG_INFO_EXPRESSION_TYPE("T!! & Interface1")!>it<!>.equals(null)
<!DEBUG_INFO_EXPRESSION_TYPE("T!! & Interface1")!>it<!>.propT
<!DEBUG_INFO_EXPRESSION_TYPE("T!! & Interface1")!>it<!>.propAny
<!DEBUG_INFO_EXPRESSION_TYPE("T!! & Interface1")!>it<!>.propNullableT
<!DEBUG_INFO_EXPRESSION_TYPE("T!! & Interface1")!>it<!>.propNullableAny
<!DEBUG_INFO_EXPRESSION_TYPE("T!! & Interface1")!>it<!>.funT()
<!DEBUG_INFO_EXPRESSION_TYPE("T!! & Interface1")!>it<!>.funAny()
<!DEBUG_INFO_EXPRESSION_TYPE("T!! & Interface1")!>it<!>.funNullableT()
<!DEBUG_INFO_EXPRESSION_TYPE("T!! & Interface1")!>it<!>.funNullableAny()
<!DEBUG_INFO_EXPRESSION_TYPE("Interface1 & T!!")!>it<!>
<!DEBUG_INFO_EXPRESSION_TYPE("Interface1 & T!!")!>it<!>.itest()
<!DEBUG_INFO_EXPRESSION_TYPE("Interface1 & T!!")!>it<!>.equals(null)
<!DEBUG_INFO_EXPRESSION_TYPE("Interface1 & T!!")!>it<!>.propT
<!DEBUG_INFO_EXPRESSION_TYPE("Interface1 & T!!")!>it<!>.propAny
<!DEBUG_INFO_EXPRESSION_TYPE("Interface1 & T!!")!>it<!>.propNullableT
<!DEBUG_INFO_EXPRESSION_TYPE("Interface1 & T!!")!>it<!>.propNullableAny
<!DEBUG_INFO_EXPRESSION_TYPE("Interface1 & T!!")!>it<!>.funT()
<!DEBUG_INFO_EXPRESSION_TYPE("Interface1 & T!!")!>it<!>.funAny()
<!DEBUG_INFO_EXPRESSION_TYPE("Interface1 & T!!")!>it<!>.funNullableT()
<!DEBUG_INFO_EXPRESSION_TYPE("Interface1 & T!!")!>it<!>.funNullableAny()
}
}
}