[FIR] Fix incorrect smartcasts from || expressions

#KT-36057 Fixed
This commit is contained in:
Dmitriy Novozhilov
2020-02-18 12:11:03 +03:00
parent 89e377763a
commit 41d2f41141
6 changed files with 77 additions and 3 deletions
@@ -137,8 +137,10 @@ abstract class LogicSystem<FLOW : Flow>(protected val context: ConeInferenceCont
val allTypes = types.flatMapTo(mutableSetOf()) { it }
val commonTypes = allTypes.toMutableSet()
types.forEach { commonTypes.retainAll(it) }
val differentTypes = allTypes - commonTypes
context.commonSuperTypeOrNull(differentTypes.toList())?.let { commonTypes += it }
val differentTypes = types.mapNotNull { (it - commonTypes).takeIf { it.isNotEmpty() } }
if (differentTypes.size == types.size) {
context.commonSuperTypeOrNull(differentTypes.flatten())?.let { commonTypes += it }
}
return commonTypes
}
}
@@ -0,0 +1,27 @@
// ISSUE: KT-36057
fun String.foo() {}
fun test_1(a: Any?) {
when (a) {
is String, is Any -> a.<!INAPPLICABLE_CANDIDATE!>foo<!>() // Should be Bad
}
}
fun test_2(a: Any?) {
if (a is String || a is Any) {
a.<!INAPPLICABLE_CANDIDATE!>foo<!>() // Should be Bad
}
}
fun test_3(a: Any?, b: Boolean) {
when (a) {
is String, b -> a.<!INAPPLICABLE_CANDIDATE!>foo<!>() // Should be Bad
}
}
fun test_4(a: Any?, b: Boolean) {
if (a is String || b) {
a.<!INAPPLICABLE_CANDIDATE!>foo<!>() // Should be Bad
}
}
@@ -0,0 +1,35 @@
FILE: orInWhenBranch.kt
public final fun R|kotlin/String|.foo(): R|kotlin/Unit| {
}
public final fun test_1(a: R|kotlin/Any?|): R|kotlin/Unit| {
when (R|<local>/a|) {
($subj$ is R|kotlin/String|) || ($subj$ is R|kotlin/Any|) -> {
R|<local>/a|.<Inapplicable(WRONG_RECEIVER): [/foo]>#()
}
}
}
public final fun test_2(a: R|kotlin/Any?|): R|kotlin/Unit| {
when () {
(R|<local>/a| is R|kotlin/String|) || (R|<local>/a| is R|kotlin/Any|) -> {
R|<local>/a|.<Inapplicable(WRONG_RECEIVER): [/foo]>#()
}
}
}
public final fun test_3(a: R|kotlin/Any?|, b: R|kotlin/Boolean|): R|kotlin/Unit| {
when (R|<local>/a|) {
($subj$ is R|kotlin/String|) || ==($subj$, R|<local>/b|) -> {
R|<local>/a|.<Inapplicable(WRONG_RECEIVER): [/foo]>#()
}
}
}
public final fun test_4(a: R|kotlin/Any?|, b: R|kotlin/Boolean|): R|kotlin/Unit| {
when () {
(R|<local>/a| is R|kotlin/String|) || R|<local>/b| -> {
R|<local>/a|.<Inapplicable(WRONG_RECEIVER): [/foo]>#()
}
}
}
@@ -1461,6 +1461,11 @@ public class FirDiagnosticsTestGenerated extends AbstractFirDiagnosticsTest {
runTest("compiler/fir/resolve/testData/resolve/smartcasts/nullability.kt");
}
@TestMetadata("orInWhenBranch.kt")
public void testOrInWhenBranch() throws Exception {
runTest("compiler/fir/resolve/testData/resolve/smartcasts/orInWhenBranch.kt");
}
@TestMetadata("smartCastInInit.kt")
public void testSmartCastInInit() throws Exception {
runTest("compiler/fir/resolve/testData/resolve/smartcasts/smartCastInInit.kt");
@@ -1461,6 +1461,11 @@ public class FirDiagnosticsWithLightTreeTestGenerated extends AbstractFirDiagnos
runTest("compiler/fir/resolve/testData/resolve/smartcasts/nullability.kt");
}
@TestMetadata("orInWhenBranch.kt")
public void testOrInWhenBranch() throws Exception {
runTest("compiler/fir/resolve/testData/resolve/smartcasts/orInWhenBranch.kt");
}
@TestMetadata("smartCastInInit.kt")
public void testSmartCastInInit() throws Exception {
runTest("compiler/fir/resolve/testData/resolve/smartcasts/smartCastInInit.kt");
@@ -196,7 +196,7 @@ fun mergeSmartCasts(a: Any?) {
a.<!INAPPLICABLE_CANDIDATE!>compareTo<!>("")
}
when (a) {
is String, is Any -> a.compareTo("")
is String, is Any -> a.<!UNRESOLVED_REFERENCE!>compareTo<!>("")
}
if (a is String && a is Any) {
val i: Int = a.compareTo("")