diff --git a/plugins/kotlin/code-insight/inspections-k2/src/org/jetbrains/kotlin/idea/k2/codeinsight/inspections/dfa/KotlinFunctionCallInstruction.kt b/plugins/kotlin/code-insight/inspections-k2/src/org/jetbrains/kotlin/idea/k2/codeinsight/inspections/dfa/KotlinFunctionCallInstruction.kt index ded35d3711db..cb3cf08a0e54 100644 --- a/plugins/kotlin/code-insight/inspections-k2/src/org/jetbrains/kotlin/idea/k2/codeinsight/inspections/dfa/KotlinFunctionCallInstruction.kt +++ b/plugins/kotlin/code-insight/inspections-k2/src/org/jetbrains/kotlin/idea/k2/codeinsight/inspections/dfa/KotlinFunctionCallInstruction.kt @@ -131,7 +131,7 @@ class KotlinFunctionCallInstruction( ?.cond(RelationType.equivalence(!isNegated), factory.fromDfType(DfTypes.NULL)) is KaContractIsInstancePredicateExpression -> argument.findDfaValue(callDescriptor, arguments) - ?.cond(if (isNegated) RelationType.IS_NOT else RelationType.IS, factory.fromDfType(type.toDfType())) + ?.cond(if (isNegated) RelationType.IS_NOT else RelationType.IS, factory.fromDfType(type.toDfReferenceType())) else -> null } diff --git a/plugins/kotlin/code-insight/inspections-k2/src/org/jetbrains/kotlin/idea/k2/codeinsight/inspections/dfa/KtControlFlowBuilder.kt b/plugins/kotlin/code-insight/inspections-k2/src/org/jetbrains/kotlin/idea/k2/codeinsight/inspections/dfa/KtControlFlowBuilder.kt index 17399fc6656b..c824e4b907a6 100644 --- a/plugins/kotlin/code-insight/inspections-k2/src/org/jetbrains/kotlin/idea/k2/codeinsight/inspections/dfa/KtControlFlowBuilder.kt +++ b/plugins/kotlin/code-insight/inspections-k2/src/org/jetbrains/kotlin/idea/k2/codeinsight/inspections/dfa/KtControlFlowBuilder.kt @@ -364,8 +364,7 @@ class KtControlFlowBuilder(val factory: DfaValueFactory, val context: KtExpressi if (kotlinType is KaErrorType || kotlinType is KaTypeParameterType) return DfType.TOP val result = if (kotlinType.isMarkedNullable) kotlinType.toDfType() else { - // makeNullable to convert primitive to boxed - val dfType = kotlinType.withNullability(true).toDfType().meet(DfTypes.NOT_NULL_OBJECT) + val dfType = kotlinType.toDfReferenceType() if (dfType is DfReferenceType) dfType.dropSpecialField() else dfType } return if (result is DfReferenceType) diff --git a/plugins/kotlin/code-insight/inspections-k2/src/org/jetbrains/kotlin/idea/k2/codeinsight/inspections/dfa/KtDfaHelpers.kt b/plugins/kotlin/code-insight/inspections-k2/src/org/jetbrains/kotlin/idea/k2/codeinsight/inspections/dfa/KtDfaHelpers.kt index 2fa595ac57ad..8144797f6df7 100644 --- a/plugins/kotlin/code-insight/inspections-k2/src/org/jetbrains/kotlin/idea/k2/codeinsight/inspections/dfa/KtDfaHelpers.kt +++ b/plugins/kotlin/code-insight/inspections-k2/src/org/jetbrains/kotlin/idea/k2/codeinsight/inspections/dfa/KtDfaHelpers.kt @@ -51,6 +51,14 @@ internal fun KaType?.toDfType(): DfType { return toDfTypeNotNullable() } +/** + * Convert KaType to DfReferenceType (primitive types are boxed) + */ +context(_: KaSession) +internal fun KaType?.toDfReferenceType(): DfType { + return this?.withNullability(true).toDfType().meet(DfTypes.NOT_NULL_OBJECT) +} + context(_: KaSession) private fun KaType.toDfTypeNotNullable(): DfType { return when (this) { diff --git a/plugins/kotlin/code-insight/inspections-k2/tests/test/org/jetbrains/kotlin/idea/k2/inspections/tests/K2DataFlowInspectionTest.kt b/plugins/kotlin/code-insight/inspections-k2/tests/test/org/jetbrains/kotlin/idea/k2/inspections/tests/K2DataFlowInspectionTest.kt index fb1761c5268f..d336e6f176eb 100644 --- a/plugins/kotlin/code-insight/inspections-k2/tests/test/org/jetbrains/kotlin/idea/k2/inspections/tests/K2DataFlowInspectionTest.kt +++ b/plugins/kotlin/code-insight/inspections-k2/tests/test/org/jetbrains/kotlin/idea/k2/inspections/tests/K2DataFlowInspectionTest.kt @@ -46,6 +46,7 @@ class K2DataFlowInspectionTest : AbstractK2InspectionTest() { fun testConstantDivisionByZero() = doTest() fun testConstantWithDifferentType() = doTest() fun testContextParameter() = doTest() + fun testContractForNumber() = doTest() fun testCustomObjectComparisonK2() = doTest() fun testDestructuringInLoop() = doTest() fun testDoubleComparison() = doTest() diff --git a/plugins/kotlin/idea/tests/testData/inspections/dfa/ContractForNumber.kt b/plugins/kotlin/idea/tests/testData/inspections/dfa/ContractForNumber.kt new file mode 100644 index 000000000000..cae5bdcb48cc --- /dev/null +++ b/plugins/kotlin/idea/tests/testData/inspections/dfa/ContractForNumber.kt @@ -0,0 +1,14 @@ +// WITH_STDLIB +import kotlin.contracts.ExperimentalContracts +import kotlin.contracts.contract + +fun foo(number: Number) { + if (myPredicate(number)) + println(number) +} + +@OptIn(ExperimentalContracts::class) +fun myPredicate(n: Number): Boolean { + contract { returns(true) implies (n is Int) } + return n is Int +} \ No newline at end of file