[FIR] Add smartcasts from == if equals is from Any
^KT-49127 Fixed
This commit is contained in:
committed by
teamcityserver
parent
ac718cd1c4
commit
1f0b62b25f
+12
@@ -3551,6 +3551,18 @@ public class DiagnosisCompilerFirTestdataTestGenerated extends AbstractDiagnosis
|
|||||||
runTest("compiler/fir/analysis-tests/testData/resolve/smartcasts/smartcastToTypeParameter.kt");
|
runTest("compiler/fir/analysis-tests/testData/resolve/smartcasts/smartcastToTypeParameter.kt");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@TestMetadata("smartcastsFromEquals_differentModule.kt")
|
||||||
|
public void testSmartcastsFromEquals_differentModule() throws Exception {
|
||||||
|
runTest("compiler/fir/analysis-tests/testData/resolve/smartcasts/smartcastsFromEquals_differentModule.kt");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@TestMetadata("smartcastsFromEquals_sameModule.kt")
|
||||||
|
public void testSmartcastsFromEquals_sameModule() throws Exception {
|
||||||
|
runTest("compiler/fir/analysis-tests/testData/resolve/smartcasts/smartcastsFromEquals_sameModule.kt");
|
||||||
|
}
|
||||||
|
|
||||||
@Nested
|
@Nested
|
||||||
@TestMetadata("compiler/fir/analysis-tests/testData/resolve/smartcasts/booleans")
|
@TestMetadata("compiler/fir/analysis-tests/testData/resolve/smartcasts/booleans")
|
||||||
@TestDataPath("$PROJECT_ROOT")
|
@TestDataPath("$PROJECT_ROOT")
|
||||||
|
|||||||
+10
@@ -3139,6 +3139,16 @@ public class LazyBodyIsNotTouchedTilContractsPhaseTestGenerated extends Abstract
|
|||||||
runTest("compiler/fir/analysis-tests/testData/resolve/smartcasts/smartcastToTypeParameter.kt");
|
runTest("compiler/fir/analysis-tests/testData/resolve/smartcasts/smartcastToTypeParameter.kt");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@TestMetadata("smartcastsFromEquals_differentModule.kt")
|
||||||
|
public void testSmartcastsFromEquals_differentModule() throws Exception {
|
||||||
|
runTest("compiler/fir/analysis-tests/testData/resolve/smartcasts/smartcastsFromEquals_differentModule.kt");
|
||||||
|
}
|
||||||
|
|
||||||
|
@TestMetadata("smartcastsFromEquals_sameModule.kt")
|
||||||
|
public void testSmartcastsFromEquals_sameModule() throws Exception {
|
||||||
|
runTest("compiler/fir/analysis-tests/testData/resolve/smartcasts/smartcastsFromEquals_sameModule.kt");
|
||||||
|
}
|
||||||
|
|
||||||
@TestMetadata("compiler/fir/analysis-tests/testData/resolve/smartcasts/booleans")
|
@TestMetadata("compiler/fir/analysis-tests/testData/resolve/smartcasts/booleans")
|
||||||
@TestDataPath("$PROJECT_ROOT")
|
@TestDataPath("$PROJECT_ROOT")
|
||||||
@RunWith(JUnit3RunnerWithInners.class)
|
@RunWith(JUnit3RunnerWithInners.class)
|
||||||
|
|||||||
compiler/fir/analysis-tests/testData/resolve/smartcasts/smartcastsFromEquals_differentModule.fir.txt
Vendored
+96
@@ -0,0 +1,96 @@
|
|||||||
|
Module: lib
|
||||||
|
FILE: module_lib_smartcastsFromEquals_differentModule.kt
|
||||||
|
public final class Final<T> : R|kotlin/Any| {
|
||||||
|
public constructor<T>(): R|Final<T>| {
|
||||||
|
super<R|kotlin/Any|>()
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
public open class Base<T> : R|kotlin/Any| {
|
||||||
|
public constructor<T>(): R|Base<T>| {
|
||||||
|
super<R|kotlin/Any|>()
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
public final class Derived<T> : R|Base<T>| {
|
||||||
|
public constructor<T>(): R|Derived<T>| {
|
||||||
|
super<R|Base<T>|>()
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
public final class FinalWithOverride<T> : R|kotlin/Any| {
|
||||||
|
public constructor<T>(): R|FinalWithOverride<T>| {
|
||||||
|
super<R|kotlin/Any|>()
|
||||||
|
}
|
||||||
|
|
||||||
|
public final override operator fun equals(other: R|kotlin/Any?|): R|kotlin/Boolean| {
|
||||||
|
^equals ===(this@R|/FinalWithOverride|, R|<local>/other|)
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
Module: main
|
||||||
|
FILE: module_main_smartcastsFromEquals_differentModule.kt
|
||||||
|
public final fun testFinal(x: R|Final<*>|, y: R|Final<kotlin/Int>|): R|kotlin/Unit| {
|
||||||
|
when () {
|
||||||
|
==(R|<local>/x|, R|<local>/y|) -> {
|
||||||
|
<Inapplicable(INAPPLICABLE): /takeIntFinal>#(R|<local>/x|)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
when () {
|
||||||
|
===(R|<local>/x|, R|<local>/y|) -> {
|
||||||
|
R|/takeIntFinal|(R|<local>/x|)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
public final fun testBase(x: R|Base<*>|, y: R|Base<kotlin/Int>|): R|kotlin/Unit| {
|
||||||
|
when () {
|
||||||
|
==(R|<local>/x|, R|<local>/y|) -> {
|
||||||
|
<Inapplicable(INAPPLICABLE): /takeIntBase>#(R|<local>/x|)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
when () {
|
||||||
|
===(R|<local>/x|, R|<local>/y|) -> {
|
||||||
|
R|/takeIntBase|(R|<local>/x|)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
public final fun testDerived(x: R|Derived<*>|, y: R|Derived<kotlin/Int>|): R|kotlin/Unit| {
|
||||||
|
when () {
|
||||||
|
==(R|<local>/x|, R|<local>/y|) -> {
|
||||||
|
<Inapplicable(INAPPLICABLE): /takeIntDerived>#(R|<local>/x|)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
when () {
|
||||||
|
===(R|<local>/x|, R|<local>/y|) -> {
|
||||||
|
R|/takeIntDerived|(R|<local>/x|)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
public final fun testFinalWithOverride(x: R|FinalWithOverride<*>|, y: R|FinalWithOverride<kotlin/Int>|): R|kotlin/Unit| {
|
||||||
|
when () {
|
||||||
|
==(R|<local>/x|, R|<local>/y|) -> {
|
||||||
|
<Inapplicable(INAPPLICABLE): /takeIntFinalWithOverride>#(R|<local>/x|)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
when () {
|
||||||
|
===(R|<local>/x|, R|<local>/y|) -> {
|
||||||
|
R|/takeIntFinalWithOverride|(R|<local>/x|)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
public final fun takeIntFinal(x: R|Final<kotlin/Int>|): R|kotlin/Unit| {
|
||||||
|
}
|
||||||
|
public final fun takeIntBase(x: R|Base<kotlin/Int>|): R|kotlin/Unit| {
|
||||||
|
}
|
||||||
|
public final fun takeIntDerived(x: R|Derived<kotlin/Int>|): R|kotlin/Unit| {
|
||||||
|
}
|
||||||
|
public final fun takeIntFinalWithOverride(x: R|FinalWithOverride<kotlin/Int>|): R|kotlin/Unit| {
|
||||||
|
}
|
||||||
Vendored
+60
@@ -0,0 +1,60 @@
|
|||||||
|
// SKIP_JAVAC
|
||||||
|
// This directive is needed to skip this test in LazyBodyIsNotTouchedTilContractsPhaseTestGenerated,
|
||||||
|
// because it fails to parse module structure of multimodule test
|
||||||
|
// ISSUE: KT-49127
|
||||||
|
|
||||||
|
// MODULE: lib
|
||||||
|
class Final<T>
|
||||||
|
|
||||||
|
open class Base<T>
|
||||||
|
|
||||||
|
class Derived<T> : Base<T>()
|
||||||
|
|
||||||
|
class FinalWithOverride<T> {
|
||||||
|
override fun equals(other: Any?): Boolean {
|
||||||
|
// some custom implementation
|
||||||
|
return this === other
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// MODULE: main(lib)
|
||||||
|
fun testFinal(x: Final<*>, y: Final<Int>) {
|
||||||
|
if (x == y) {
|
||||||
|
takeIntFinal(<!ARGUMENT_TYPE_MISMATCH!>x<!>) // Error
|
||||||
|
}
|
||||||
|
if (x === y) {
|
||||||
|
takeIntFinal(x) // OK
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fun testBase(x: Base<*>, y: Base<Int>) {
|
||||||
|
if (x == y) {
|
||||||
|
takeIntBase(<!ARGUMENT_TYPE_MISMATCH!>x<!>) // Error
|
||||||
|
}
|
||||||
|
if (x === y) {
|
||||||
|
takeIntBase(x) // OK
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fun testDerived(x: Derived<*>, y: Derived<Int>) {
|
||||||
|
if (x == y) {
|
||||||
|
takeIntDerived(<!ARGUMENT_TYPE_MISMATCH!>x<!>) // Error
|
||||||
|
}
|
||||||
|
if (x === y) {
|
||||||
|
takeIntDerived(x) // OK
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fun testFinalWithOverride(x: FinalWithOverride<*>, y: FinalWithOverride<Int>) {
|
||||||
|
if (x == y) {
|
||||||
|
takeIntFinalWithOverride(<!ARGUMENT_TYPE_MISMATCH!>x<!>) // Error
|
||||||
|
}
|
||||||
|
if (x === y) {
|
||||||
|
takeIntFinalWithOverride(x) // OK
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fun takeIntFinal(x: Final<Int>) {}
|
||||||
|
fun takeIntBase(x: Base<Int>) {}
|
||||||
|
fun takeIntDerived(x: Derived<Int>) {}
|
||||||
|
fun takeIntFinalWithOverride(x: FinalWithOverride<Int>) {}
|
||||||
Vendored
+93
@@ -0,0 +1,93 @@
|
|||||||
|
FILE: smartcastsFromEquals_sameModule.kt
|
||||||
|
public final class Final<T> : R|kotlin/Any| {
|
||||||
|
public constructor<T>(): R|Final<T>| {
|
||||||
|
super<R|kotlin/Any|>()
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
public open class Base<T> : R|kotlin/Any| {
|
||||||
|
public constructor<T>(): R|Base<T>| {
|
||||||
|
super<R|kotlin/Any|>()
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
public final class Derived<T> : R|Base<T>| {
|
||||||
|
public constructor<T>(): R|Derived<T>| {
|
||||||
|
super<R|Base<T>|>()
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
public final class FinalWithOverride<T> : R|kotlin/Any| {
|
||||||
|
public constructor<T>(): R|FinalWithOverride<T>| {
|
||||||
|
super<R|kotlin/Any|>()
|
||||||
|
}
|
||||||
|
|
||||||
|
public final override operator fun equals(other: R|kotlin/Any?|): R|kotlin/Boolean| {
|
||||||
|
^equals ===(this@R|/FinalWithOverride|, R|<local>/other|)
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
public final fun testFinal(x: R|Final<*>|, y: R|Final<kotlin/Int>|): R|kotlin/Unit| {
|
||||||
|
when () {
|
||||||
|
==(R|<local>/x|, R|<local>/y|) -> {
|
||||||
|
R|/takeIntFinal|(R|<local>/x|)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
when () {
|
||||||
|
===(R|<local>/x|, R|<local>/y|) -> {
|
||||||
|
R|/takeIntFinal|(R|<local>/x|)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
public final fun testBase(x: R|Base<*>|, y: R|Base<kotlin/Int>|): R|kotlin/Unit| {
|
||||||
|
when () {
|
||||||
|
==(R|<local>/x|, R|<local>/y|) -> {
|
||||||
|
<Inapplicable(INAPPLICABLE): /takeIntBase>#(R|<local>/x|)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
when () {
|
||||||
|
===(R|<local>/x|, R|<local>/y|) -> {
|
||||||
|
R|/takeIntBase|(R|<local>/x|)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
public final fun testDerived(x: R|Derived<*>|, y: R|Derived<kotlin/Int>|): R|kotlin/Unit| {
|
||||||
|
when () {
|
||||||
|
==(R|<local>/x|, R|<local>/y|) -> {
|
||||||
|
R|/takeIntDerived|(R|<local>/x|)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
when () {
|
||||||
|
===(R|<local>/x|, R|<local>/y|) -> {
|
||||||
|
R|/takeIntDerived|(R|<local>/x|)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
public final fun testFinalWithOverride(x: R|FinalWithOverride<*>|, y: R|FinalWithOverride<kotlin/Int>|): R|kotlin/Unit| {
|
||||||
|
when () {
|
||||||
|
==(R|<local>/x|, R|<local>/y|) -> {
|
||||||
|
<Inapplicable(INAPPLICABLE): /takeIntFinalWithOverride>#(R|<local>/x|)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
when () {
|
||||||
|
===(R|<local>/x|, R|<local>/y|) -> {
|
||||||
|
R|/takeIntFinalWithOverride|(R|<local>/x|)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
public final fun takeIntFinal(x: R|Final<kotlin/Int>|): R|kotlin/Unit| {
|
||||||
|
}
|
||||||
|
public final fun takeIntBase(x: R|Base<kotlin/Int>|): R|kotlin/Unit| {
|
||||||
|
}
|
||||||
|
public final fun takeIntDerived(x: R|Derived<kotlin/Int>|): R|kotlin/Unit| {
|
||||||
|
}
|
||||||
|
public final fun takeIntFinalWithOverride(x: R|FinalWithOverride<kotlin/Int>|): R|kotlin/Unit| {
|
||||||
|
}
|
||||||
+55
@@ -0,0 +1,55 @@
|
|||||||
|
// ISSUE: KT-49127
|
||||||
|
|
||||||
|
class Final<T>
|
||||||
|
|
||||||
|
open class Base<T>
|
||||||
|
|
||||||
|
class Derived<T> : Base<T>()
|
||||||
|
|
||||||
|
class FinalWithOverride<T> {
|
||||||
|
override fun equals(other: Any?): Boolean {
|
||||||
|
// some custom implementation
|
||||||
|
return this === other
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fun testFinal(x: Final<*>, y: Final<Int>) {
|
||||||
|
if (x == y) {
|
||||||
|
takeIntFinal(x) // OK
|
||||||
|
}
|
||||||
|
if (x === y) {
|
||||||
|
takeIntFinal(x) // OK
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fun testBase(x: Base<*>, y: Base<Int>) {
|
||||||
|
if (x == y) {
|
||||||
|
takeIntBase(<!ARGUMENT_TYPE_MISMATCH!>x<!>) // Error
|
||||||
|
}
|
||||||
|
if (x === y) {
|
||||||
|
takeIntBase(x) // OK
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fun testDerived(x: Derived<*>, y: Derived<Int>) {
|
||||||
|
if (x == y) {
|
||||||
|
takeIntDerived(x) // OK
|
||||||
|
}
|
||||||
|
if (x === y) {
|
||||||
|
takeIntDerived(x) // OK
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fun testFinalWithOverride(x: FinalWithOverride<*>, y: FinalWithOverride<Int>) {
|
||||||
|
if (x == y) {
|
||||||
|
takeIntFinalWithOverride(<!ARGUMENT_TYPE_MISMATCH!>x<!>) // Error
|
||||||
|
}
|
||||||
|
if (x === y) {
|
||||||
|
takeIntFinalWithOverride(x) // OK
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fun takeIntFinal(x: Final<Int>) {}
|
||||||
|
fun takeIntBase(x: Base<Int>) {}
|
||||||
|
fun takeIntDerived(x: Derived<Int>) {}
|
||||||
|
fun takeIntFinalWithOverride(x: FinalWithOverride<Int>) {}
|
||||||
+12
@@ -3551,6 +3551,18 @@ public class FirDiagnosticTestGenerated extends AbstractFirDiagnosticTest {
|
|||||||
runTest("compiler/fir/analysis-tests/testData/resolve/smartcasts/smartcastToTypeParameter.kt");
|
runTest("compiler/fir/analysis-tests/testData/resolve/smartcasts/smartcastToTypeParameter.kt");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@TestMetadata("smartcastsFromEquals_differentModule.kt")
|
||||||
|
public void testSmartcastsFromEquals_differentModule() throws Exception {
|
||||||
|
runTest("compiler/fir/analysis-tests/testData/resolve/smartcasts/smartcastsFromEquals_differentModule.kt");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@TestMetadata("smartcastsFromEquals_sameModule.kt")
|
||||||
|
public void testSmartcastsFromEquals_sameModule() throws Exception {
|
||||||
|
runTest("compiler/fir/analysis-tests/testData/resolve/smartcasts/smartcastsFromEquals_sameModule.kt");
|
||||||
|
}
|
||||||
|
|
||||||
@Nested
|
@Nested
|
||||||
@TestMetadata("compiler/fir/analysis-tests/testData/resolve/smartcasts/booleans")
|
@TestMetadata("compiler/fir/analysis-tests/testData/resolve/smartcasts/booleans")
|
||||||
@TestDataPath("$PROJECT_ROOT")
|
@TestDataPath("$PROJECT_ROOT")
|
||||||
|
|||||||
+12
@@ -3551,6 +3551,18 @@ public class FirDiagnosticsWithLightTreeTestGenerated extends AbstractFirDiagnos
|
|||||||
runTest("compiler/fir/analysis-tests/testData/resolve/smartcasts/smartcastToTypeParameter.kt");
|
runTest("compiler/fir/analysis-tests/testData/resolve/smartcasts/smartcastToTypeParameter.kt");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@TestMetadata("smartcastsFromEquals_differentModule.kt")
|
||||||
|
public void testSmartcastsFromEquals_differentModule() throws Exception {
|
||||||
|
runTest("compiler/fir/analysis-tests/testData/resolve/smartcasts/smartcastsFromEquals_differentModule.kt");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@TestMetadata("smartcastsFromEquals_sameModule.kt")
|
||||||
|
public void testSmartcastsFromEquals_sameModule() throws Exception {
|
||||||
|
runTest("compiler/fir/analysis-tests/testData/resolve/smartcasts/smartcastsFromEquals_sameModule.kt");
|
||||||
|
}
|
||||||
|
|
||||||
@Nested
|
@Nested
|
||||||
@TestMetadata("compiler/fir/analysis-tests/testData/resolve/smartcasts/booleans")
|
@TestMetadata("compiler/fir/analysis-tests/testData/resolve/smartcasts/booleans")
|
||||||
@TestDataPath("$PROJECT_ROOT")
|
@TestDataPath("$PROJECT_ROOT")
|
||||||
|
|||||||
+7
-10
@@ -6,19 +6,19 @@
|
|||||||
package org.jetbrains.kotlin.fir.analysis.checkers.declaration
|
package org.jetbrains.kotlin.fir.analysis.checkers.declaration
|
||||||
|
|
||||||
import org.jetbrains.kotlin.builtins.StandardNames.HASHCODE_NAME
|
import org.jetbrains.kotlin.builtins.StandardNames.HASHCODE_NAME
|
||||||
|
import org.jetbrains.kotlin.diagnostics.DiagnosticReporter
|
||||||
|
import org.jetbrains.kotlin.diagnostics.reportOn
|
||||||
import org.jetbrains.kotlin.fir.analysis.checkers.FirDeclarationPresenter
|
import org.jetbrains.kotlin.fir.analysis.checkers.FirDeclarationPresenter
|
||||||
import org.jetbrains.kotlin.fir.analysis.checkers.context.CheckerContext
|
import org.jetbrains.kotlin.fir.analysis.checkers.context.CheckerContext
|
||||||
import org.jetbrains.kotlin.diagnostics.DiagnosticReporter
|
|
||||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors
|
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors
|
||||||
import org.jetbrains.kotlin.diagnostics.reportOn
|
|
||||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.withSuppressedDiagnostics
|
import org.jetbrains.kotlin.fir.analysis.diagnostics.withSuppressedDiagnostics
|
||||||
import org.jetbrains.kotlin.fir.declarations.*
|
import org.jetbrains.kotlin.fir.declarations.FirRegularClass
|
||||||
|
import org.jetbrains.kotlin.fir.declarations.FirSimpleFunction
|
||||||
import org.jetbrains.kotlin.fir.declarations.utils.hasBody
|
import org.jetbrains.kotlin.fir.declarations.utils.hasBody
|
||||||
import org.jetbrains.kotlin.fir.declarations.utils.isInterface
|
import org.jetbrains.kotlin.fir.declarations.utils.isInterface
|
||||||
import org.jetbrains.kotlin.fir.declarations.utils.isOverride
|
import org.jetbrains.kotlin.fir.declarations.utils.isOverride
|
||||||
import org.jetbrains.kotlin.fir.types.isNullableAny
|
import org.jetbrains.kotlin.fir.resolve.isEquals
|
||||||
import org.jetbrains.kotlin.name.CallableId
|
import org.jetbrains.kotlin.name.CallableId
|
||||||
import org.jetbrains.kotlin.util.OperatorNameConventions.EQUALS
|
|
||||||
import org.jetbrains.kotlin.util.OperatorNameConventions.TO_STRING
|
import org.jetbrains.kotlin.util.OperatorNameConventions.TO_STRING
|
||||||
|
|
||||||
object FirMethodOfAnyImplementedInInterfaceChecker : FirRegularClassChecker(), FirDeclarationPresenter {
|
object FirMethodOfAnyImplementedInInterfaceChecker : FirRegularClassChecker(), FirDeclarationPresenter {
|
||||||
@@ -44,11 +44,8 @@ object FirMethodOfAnyImplementedInInterfaceChecker : FirRegularClassChecker(), F
|
|||||||
(function.name == HASHCODE_NAME || function.name == TO_STRING)
|
(function.name == HASHCODE_NAME || function.name == TO_STRING)
|
||||||
) {
|
) {
|
||||||
methodOfAny = true
|
methodOfAny = true
|
||||||
} else {
|
} else if (function.isEquals()) {
|
||||||
val singleParameter = function.valueParameters.singleOrNull() ?: continue
|
methodOfAny = true
|
||||||
if (singleParameter.returnTypeRef.isNullableAny && function.name == EQUALS) {
|
|
||||||
methodOfAny = true
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (methodOfAny) {
|
if (methodOfAny) {
|
||||||
|
|||||||
@@ -17,12 +17,14 @@ import org.jetbrains.kotlin.fir.resolve.substitution.ConeSubstitutor
|
|||||||
import org.jetbrains.kotlin.fir.resolve.substitution.ConeSubstitutorByMap
|
import org.jetbrains.kotlin.fir.resolve.substitution.ConeSubstitutorByMap
|
||||||
import org.jetbrains.kotlin.fir.scopes.FirScope
|
import org.jetbrains.kotlin.fir.scopes.FirScope
|
||||||
import org.jetbrains.kotlin.fir.scopes.FirTypeScope
|
import org.jetbrains.kotlin.fir.scopes.FirTypeScope
|
||||||
|
import org.jetbrains.kotlin.fir.symbols.ConeClassLikeLookupTag
|
||||||
import org.jetbrains.kotlin.fir.symbols.ensureResolved
|
import org.jetbrains.kotlin.fir.symbols.ensureResolved
|
||||||
import org.jetbrains.kotlin.fir.symbols.impl.*
|
import org.jetbrains.kotlin.fir.symbols.impl.*
|
||||||
import org.jetbrains.kotlin.fir.types.*
|
import org.jetbrains.kotlin.fir.types.*
|
||||||
import org.jetbrains.kotlin.types.model.CaptureStatus
|
import org.jetbrains.kotlin.types.model.CaptureStatus
|
||||||
import org.jetbrains.kotlin.utils.SmartList
|
import org.jetbrains.kotlin.utils.SmartList
|
||||||
import org.jetbrains.kotlin.utils.SmartSet
|
import org.jetbrains.kotlin.utils.SmartSet
|
||||||
|
import org.jetbrains.kotlin.utils.addIfNotNull
|
||||||
|
|
||||||
abstract class SupertypeSupplier {
|
abstract class SupertypeSupplier {
|
||||||
abstract fun forClass(firClass: FirClass, useSiteSession: FirSession): List<ConeClassLikeType>
|
abstract fun forClass(firClass: FirClass, useSiteSession: FirSession): List<ConeClassLikeType>
|
||||||
@@ -44,6 +46,48 @@ abstract class SupertypeSupplier {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fun collectSymbolsForType(type: ConeKotlinType, useSiteSession: FirSession): List<FirClassSymbol<*>> {
|
||||||
|
val lookupTags = mutableListOf<ConeClassLikeLookupTag>()
|
||||||
|
|
||||||
|
fun ConeKotlinType.collectClassIds() {
|
||||||
|
when (val unwrappedType = lowerBoundIfFlexible().fullyExpandedType(useSiteSession)) {
|
||||||
|
is ConeClassLikeType -> lookupTags.addIfNotNull(unwrappedType.lookupTag)
|
||||||
|
is ConeIntersectionType -> unwrappedType.intersectedTypes.forEach { it.collectClassIds() }
|
||||||
|
else -> {}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
type.collectClassIds()
|
||||||
|
return lookupTags.mapNotNull { it.toSymbol(useSiteSession) as? FirClassSymbol<*> }
|
||||||
|
}
|
||||||
|
|
||||||
|
fun lookupSuperTypes(
|
||||||
|
type: ConeKotlinType,
|
||||||
|
lookupInterfaces: Boolean,
|
||||||
|
deep: Boolean,
|
||||||
|
useSiteSession: FirSession,
|
||||||
|
substituteTypes: Boolean,
|
||||||
|
supertypeSupplier: SupertypeSupplier = SupertypeSupplier.Default,
|
||||||
|
): List<ConeClassLikeType> {
|
||||||
|
return lookupSuperTypes(collectSymbolsForType(type, useSiteSession), lookupInterfaces, deep, useSiteSession, substituteTypes, supertypeSupplier)
|
||||||
|
}
|
||||||
|
|
||||||
|
fun lookupSuperTypes(
|
||||||
|
symbols: List<FirClassifierSymbol<*>>,
|
||||||
|
lookupInterfaces: Boolean,
|
||||||
|
deep: Boolean,
|
||||||
|
useSiteSession: FirSession,
|
||||||
|
substituteTypes: Boolean,
|
||||||
|
supertypeSupplier: SupertypeSupplier = SupertypeSupplier.Default,
|
||||||
|
): List<ConeClassLikeType> {
|
||||||
|
return SmartList<ConeClassLikeType>().also {
|
||||||
|
val visitedSymbols = SmartSet.create<FirClassifierSymbol<*>>()
|
||||||
|
for (symbol in symbols) {
|
||||||
|
symbol.collectSuperTypes(it, visitedSymbols, deep, lookupInterfaces, substituteTypes, useSiteSession, supertypeSupplier)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
fun lookupSuperTypes(
|
fun lookupSuperTypes(
|
||||||
klass: FirClass,
|
klass: FirClass,
|
||||||
lookupInterfaces: Boolean,
|
lookupInterfaces: Boolean,
|
||||||
|
|||||||
@@ -34,6 +34,7 @@ import org.jetbrains.kotlin.fir.resolve.dfa.FirDataFlowAnalyzer
|
|||||||
import org.jetbrains.kotlin.fir.resolve.dfa.PropertyStability
|
import org.jetbrains.kotlin.fir.resolve.dfa.PropertyStability
|
||||||
import org.jetbrains.kotlin.fir.resolve.diagnostics.ConeUnresolvedNameError
|
import org.jetbrains.kotlin.fir.resolve.diagnostics.ConeUnresolvedNameError
|
||||||
import org.jetbrains.kotlin.fir.resolve.providers.symbolProvider
|
import org.jetbrains.kotlin.fir.resolve.providers.symbolProvider
|
||||||
|
import org.jetbrains.kotlin.fir.resolve.transformers.ReturnTypeCalculator
|
||||||
import org.jetbrains.kotlin.fir.resolve.transformers.body.resolve.resultType
|
import org.jetbrains.kotlin.fir.resolve.transformers.body.resolve.resultType
|
||||||
import org.jetbrains.kotlin.fir.scopes.impl.delegatedWrapperData
|
import org.jetbrains.kotlin.fir.scopes.impl.delegatedWrapperData
|
||||||
import org.jetbrains.kotlin.fir.scopes.impl.importedFromObjectData
|
import org.jetbrains.kotlin.fir.scopes.impl.importedFromObjectData
|
||||||
@@ -49,6 +50,7 @@ import org.jetbrains.kotlin.name.Name
|
|||||||
import org.jetbrains.kotlin.name.StandardClassIds
|
import org.jetbrains.kotlin.name.StandardClassIds
|
||||||
import org.jetbrains.kotlin.resolve.ForbiddenNamedArgumentsTarget
|
import org.jetbrains.kotlin.resolve.ForbiddenNamedArgumentsTarget
|
||||||
import org.jetbrains.kotlin.types.SmartcastStability
|
import org.jetbrains.kotlin.types.SmartcastStability
|
||||||
|
import org.jetbrains.kotlin.util.OperatorNameConventions
|
||||||
import org.jetbrains.kotlin.utils.addToStdlib.safeAs
|
import org.jetbrains.kotlin.utils.addToStdlib.safeAs
|
||||||
|
|
||||||
fun List<FirQualifierPart>.toTypeProjections(): Array<ConeTypeProjection> =
|
fun List<FirQualifierPart>.toTypeProjections(): Array<ConeTypeProjection> =
|
||||||
|
|||||||
+53
-11
@@ -6,6 +6,7 @@
|
|||||||
package org.jetbrains.kotlin.fir.resolve.dfa
|
package org.jetbrains.kotlin.fir.resolve.dfa
|
||||||
|
|
||||||
import org.jetbrains.kotlin.config.LanguageFeature
|
import org.jetbrains.kotlin.config.LanguageFeature
|
||||||
|
import org.jetbrains.kotlin.descriptors.Modality
|
||||||
import org.jetbrains.kotlin.fir.*
|
import org.jetbrains.kotlin.fir.*
|
||||||
import org.jetbrains.kotlin.fir.contracts.FirResolvedContractDescription
|
import org.jetbrains.kotlin.fir.contracts.FirResolvedContractDescription
|
||||||
import org.jetbrains.kotlin.fir.contracts.description.ConeBooleanConstantReference
|
import org.jetbrains.kotlin.fir.contracts.description.ConeBooleanConstantReference
|
||||||
@@ -18,24 +19,23 @@ import org.jetbrains.kotlin.fir.declarations.utils.isLocal
|
|||||||
import org.jetbrains.kotlin.fir.expressions.*
|
import org.jetbrains.kotlin.fir.expressions.*
|
||||||
import org.jetbrains.kotlin.fir.references.FirControlFlowGraphReference
|
import org.jetbrains.kotlin.fir.references.FirControlFlowGraphReference
|
||||||
import org.jetbrains.kotlin.fir.references.FirResolvedNamedReference
|
import org.jetbrains.kotlin.fir.references.FirResolvedNamedReference
|
||||||
import org.jetbrains.kotlin.fir.resolve.PersistentImplicitReceiverStack
|
import org.jetbrains.kotlin.fir.resolve.*
|
||||||
import org.jetbrains.kotlin.fir.resolve.ResolutionMode
|
|
||||||
import org.jetbrains.kotlin.fir.resolve.dfa.cfg.*
|
import org.jetbrains.kotlin.fir.resolve.dfa.cfg.*
|
||||||
import org.jetbrains.kotlin.fir.resolve.dfa.contracts.buildContractFir
|
import org.jetbrains.kotlin.fir.resolve.dfa.contracts.buildContractFir
|
||||||
import org.jetbrains.kotlin.fir.resolve.dfa.contracts.createArgumentsMapping
|
import org.jetbrains.kotlin.fir.resolve.dfa.contracts.createArgumentsMapping
|
||||||
import org.jetbrains.kotlin.fir.resolve.fullyExpandedType
|
|
||||||
import org.jetbrains.kotlin.fir.resolve.substitution.ConeSubstitutor
|
import org.jetbrains.kotlin.fir.resolve.substitution.ConeSubstitutor
|
||||||
import org.jetbrains.kotlin.fir.resolve.substitution.ConeSubstitutorByMap
|
import org.jetbrains.kotlin.fir.resolve.substitution.ConeSubstitutorByMap
|
||||||
import org.jetbrains.kotlin.fir.resolve.toSymbol
|
|
||||||
import org.jetbrains.kotlin.fir.resolve.transformers.body.resolve.FirAbstractBodyResolveTransformer
|
import org.jetbrains.kotlin.fir.resolve.transformers.body.resolve.FirAbstractBodyResolveTransformer
|
||||||
import org.jetbrains.kotlin.fir.resolve.transformers.body.resolve.resultType
|
import org.jetbrains.kotlin.fir.resolve.transformers.body.resolve.resultType
|
||||||
|
import org.jetbrains.kotlin.fir.scopes.getFunctions
|
||||||
|
import org.jetbrains.kotlin.fir.scopes.impl.declaredMemberScope
|
||||||
import org.jetbrains.kotlin.fir.symbols.FirBasedSymbol
|
import org.jetbrains.kotlin.fir.symbols.FirBasedSymbol
|
||||||
import org.jetbrains.kotlin.fir.symbols.impl.FirTypeParameterSymbol
|
import org.jetbrains.kotlin.fir.symbols.impl.*
|
||||||
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.StandardClassIds
|
import org.jetbrains.kotlin.name.StandardClassIds
|
||||||
import org.jetbrains.kotlin.types.ConstantValueKind
|
import org.jetbrains.kotlin.types.ConstantValueKind
|
||||||
|
import org.jetbrains.kotlin.util.OperatorNameConventions
|
||||||
import org.jetbrains.kotlin.utils.addIfNotNull
|
import org.jetbrains.kotlin.utils.addIfNotNull
|
||||||
import org.jetbrains.kotlin.utils.addToStdlib.firstIsInstanceOrNull
|
import org.jetbrains.kotlin.utils.addToStdlib.firstIsInstanceOrNull
|
||||||
|
|
||||||
@@ -570,9 +570,7 @@ abstract class FirDataFlowAnalyzer<FLOW : Flow>(
|
|||||||
rightIsNullable -> processEqNull(node, rightOperand, operation.invert(), ::shouldAddImplicationForStatement)
|
rightIsNullable -> processEqNull(node, rightOperand, operation.invert(), ::shouldAddImplicationForStatement)
|
||||||
}
|
}
|
||||||
|
|
||||||
if (operation == FirOperation.IDENTITY || operation == FirOperation.NOT_IDENTITY) {
|
processPossibleIdentity(node, leftOperand, rightOperand, operation)
|
||||||
processIdentity(node, leftOperand, rightOperand, operation)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@@ -639,8 +637,11 @@ abstract class FirDataFlowAnalyzer<FLOW : Flow>(
|
|||||||
node.flow = flow
|
node.flow = flow
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun processIdentity(
|
private fun processPossibleIdentity(
|
||||||
node: EqualityOperatorCallNode, leftOperand: FirExpression, rightOperand: FirExpression, operation: FirOperation
|
node: EqualityOperatorCallNode,
|
||||||
|
leftOperand: FirExpression,
|
||||||
|
rightOperand: FirExpression,
|
||||||
|
operation: FirOperation,
|
||||||
) {
|
) {
|
||||||
val flow = node.flow
|
val flow = node.flow
|
||||||
val expressionVariable = variableStorage.getOrCreateVariable(node.previousFlow, node.fir)
|
val expressionVariable = variableStorage.getOrCreateVariable(node.previousFlow, node.fir)
|
||||||
@@ -648,6 +649,13 @@ abstract class FirDataFlowAnalyzer<FLOW : Flow>(
|
|||||||
val rightOperandVariable = variableStorage.getOrCreateVariable(node.previousFlow, rightOperand)
|
val rightOperandVariable = variableStorage.getOrCreateVariable(node.previousFlow, rightOperand)
|
||||||
val leftOperandType = leftOperand.coneType
|
val leftOperandType = leftOperand.coneType
|
||||||
val rightOperandType = rightOperand.coneType
|
val rightOperandType = rightOperand.coneType
|
||||||
|
|
||||||
|
if (!leftOperandVariable.isReal() && !rightOperandVariable.isReal()) return
|
||||||
|
|
||||||
|
if (operation == FirOperation.EQ || operation == FirOperation.NOT_EQ) {
|
||||||
|
if (hasOverriddenEquals(leftOperandType)) return
|
||||||
|
}
|
||||||
|
|
||||||
val isEq = operation.isEq()
|
val isEq = operation.isEq()
|
||||||
|
|
||||||
if (leftOperandVariable.isReal()) {
|
if (leftOperandVariable.isReal()) {
|
||||||
@@ -663,6 +671,40 @@ abstract class FirDataFlowAnalyzer<FLOW : Flow>(
|
|||||||
node.flow = flow
|
node.flow = flow
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private fun hasOverriddenEquals(type: ConeKotlinType): Boolean {
|
||||||
|
val session = components.session
|
||||||
|
val symbolsForType = collectSymbolsForType(type, session)
|
||||||
|
if (symbolsForType.any { it.hasEqualsOverride(session, checkModality = true) }) return true
|
||||||
|
|
||||||
|
val superTypes = lookupSuperTypes(
|
||||||
|
symbolsForType,
|
||||||
|
lookupInterfaces = false,
|
||||||
|
deep = true,
|
||||||
|
session,
|
||||||
|
substituteTypes = false
|
||||||
|
)
|
||||||
|
val superClassSymbols = superTypes.mapNotNull {
|
||||||
|
it.fullyExpandedType(session).toSymbol(session) as? FirRegularClassSymbol
|
||||||
|
}
|
||||||
|
|
||||||
|
return superClassSymbols.any { it.hasEqualsOverride(session, checkModality = false) }
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun FirClassSymbol<*>.hasEqualsOverride(session: FirSession, checkModality: Boolean): Boolean {
|
||||||
|
val status = resolvedStatus
|
||||||
|
if (checkModality && status.modality != Modality.FINAL) return true
|
||||||
|
if (status.isExpect) return true
|
||||||
|
when (classId) {
|
||||||
|
StandardClassIds.Any, StandardClassIds.String -> return false
|
||||||
|
}
|
||||||
|
if (moduleData != session.moduleData) {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
return session.declaredMemberScope(this)
|
||||||
|
.getFunctions(OperatorNameConventions.EQUALS)
|
||||||
|
.any { it.fir.isEquals() }
|
||||||
|
}
|
||||||
|
|
||||||
// ----------------------------------- Jump -----------------------------------
|
// ----------------------------------- Jump -----------------------------------
|
||||||
|
|
||||||
fun exitJump(jump: FirJump<*>) {
|
fun exitJump(jump: FirJump<*>) {
|
||||||
|
|||||||
@@ -15,6 +15,7 @@ import org.jetbrains.kotlin.fir.symbols.impl.FirTypeParameterSymbol
|
|||||||
import org.jetbrains.kotlin.fir.symbols.impl.LookupTagInternals
|
import org.jetbrains.kotlin.fir.symbols.impl.LookupTagInternals
|
||||||
import org.jetbrains.kotlin.fir.types.*
|
import org.jetbrains.kotlin.fir.types.*
|
||||||
import org.jetbrains.kotlin.name.ClassId
|
import org.jetbrains.kotlin.name.ClassId
|
||||||
|
import org.jetbrains.kotlin.util.OperatorNameConventions
|
||||||
|
|
||||||
fun FirClassLikeDeclaration.getContainingDeclaration(session: FirSession): FirClassLikeDeclaration? {
|
fun FirClassLikeDeclaration.getContainingDeclaration(session: FirSession): FirClassLikeDeclaration? {
|
||||||
if (isLocal) {
|
if (isLocal) {
|
||||||
@@ -86,3 +87,10 @@ var FirConstructor.originalConstructorIfTypeAlias: FirConstructor? by FirDeclara
|
|||||||
|
|
||||||
val FirConstructorSymbol.isTypeAliasedConstructor: Boolean
|
val FirConstructorSymbol.isTypeAliasedConstructor: Boolean
|
||||||
get() = fir.originalConstructorIfTypeAlias != null
|
get() = fir.originalConstructorIfTypeAlias != null
|
||||||
|
|
||||||
|
fun FirSimpleFunction.isEquals(): Boolean {
|
||||||
|
if (name != OperatorNameConventions.EQUALS) return false
|
||||||
|
if (valueParameters.size != 1) return false
|
||||||
|
val parameter = valueParameters.first()
|
||||||
|
return parameter.returnTypeRef.isNullableAny
|
||||||
|
}
|
||||||
|
|||||||
+2
-2
@@ -34,11 +34,11 @@ fun foo(x: FinalClass?, y: Any) {
|
|||||||
// OK
|
// OK
|
||||||
x.hashCode()
|
x.hashCode()
|
||||||
// OK
|
// OK
|
||||||
y.<!UNRESOLVED_REFERENCE!>use<!>()
|
y.use()
|
||||||
}
|
}
|
||||||
when (x) {
|
when (x) {
|
||||||
// OK (equals from FinalClass)
|
// OK (equals from FinalClass)
|
||||||
y -> y.<!UNRESOLVED_REFERENCE!>use<!>()
|
y -> y.use()
|
||||||
}
|
}
|
||||||
when (y) {
|
when (y) {
|
||||||
// ERROR (equals from Any)
|
// ERROR (equals from Any)
|
||||||
|
|||||||
@@ -181,11 +181,11 @@ fun case_12(x: TypealiasNullableStringIndirect, y: TypealiasNullableStringIndire
|
|||||||
|
|
||||||
// TESTCASE NUMBER: 13
|
// TESTCASE NUMBER: 13
|
||||||
fun case_13(x: <!UNRESOLVED_REFERENCE!>otherpackage.Case13<!>?) =
|
fun case_13(x: <!UNRESOLVED_REFERENCE!>otherpackage.Case13<!>?) =
|
||||||
<!DEBUG_INFO_EXPRESSION_TYPE("kotlin.Nothing")!>if ((x == null !is Boolean) !== true) {
|
<!DEBUG_INFO_EXPRESSION_TYPE("kotlin.Boolean")!>if ((x == null !is Boolean) !== true) {
|
||||||
throw Exception()
|
throw Exception()
|
||||||
} else {
|
} else {
|
||||||
<!DEBUG_INFO_EXPRESSION_TYPE("ERROR CLASS: Symbol not found for otherpackage.Case13?")!>x<!>
|
<!DEBUG_INFO_EXPRESSION_TYPE("ERROR CLASS: Symbol not found for otherpackage.Case13? & kotlin.Boolean & ERROR CLASS: Symbol not found for otherpackage.Case13?")!>x<!>
|
||||||
<!DEBUG_INFO_EXPRESSION_TYPE("ERROR CLASS: Symbol not found for otherpackage.Case13?")!>x<!>.<!OVERLOAD_RESOLUTION_AMBIGUITY!>equals<!>(x)
|
<!DEBUG_INFO_EXPRESSION_TYPE("ERROR CLASS: Symbol not found for otherpackage.Case13? & kotlin.Boolean & ERROR CLASS: Symbol not found for otherpackage.Case13?")!>x<!>.equals(x)
|
||||||
}<!>
|
}<!>
|
||||||
|
|
||||||
// TESTCASE NUMBER: 14
|
// TESTCASE NUMBER: 14
|
||||||
|
|||||||
@@ -203,7 +203,7 @@ fun case_11(x: TypealiasNullableString<!REDUNDANT_NULLABLE!>?<!>, y: TypealiasNu
|
|||||||
} else {
|
} else {
|
||||||
if (y != z) {
|
if (y != z) {
|
||||||
if (nullableStringProperty == z) {
|
if (nullableStringProperty == z) {
|
||||||
if (u != z || u != v) {
|
if (u != z || <!SENSELESS_COMPARISON!>u != v<!>) {
|
||||||
<!DEBUG_INFO_EXPRESSION_TYPE("TypealiasNullableString?")!>x<!>
|
<!DEBUG_INFO_EXPRESSION_TYPE("TypealiasNullableString?")!>x<!>
|
||||||
<!DEBUG_INFO_EXPRESSION_TYPE("TypealiasNullableString?")!>x<!>.equals(null)
|
<!DEBUG_INFO_EXPRESSION_TYPE("TypealiasNullableString?")!>x<!>.equals(null)
|
||||||
<!DEBUG_INFO_EXPRESSION_TYPE("TypealiasNullableString?")!>x<!>.propT
|
<!DEBUG_INFO_EXPRESSION_TYPE("TypealiasNullableString?")!>x<!>.propT
|
||||||
@@ -790,7 +790,7 @@ fun case_42() {
|
|||||||
fun case_43(x: TypealiasNullableString) {
|
fun case_43(x: TypealiasNullableString) {
|
||||||
val z = null
|
val z = null
|
||||||
|
|
||||||
if (x == z && <!DEBUG_INFO_EXPRESSION_TYPE("TypealiasNullableString")!>x<!> == z) {
|
if (x == z && <!SENSELESS_COMPARISON!><!DEBUG_INFO_EXPRESSION_TYPE("TypealiasNullableString & kotlin.Nothing?")!>x<!> == z<!>) {
|
||||||
<!DEBUG_INFO_EXPRESSION_TYPE("TypealiasNullableString")!>x<!>
|
<!DEBUG_INFO_EXPRESSION_TYPE("TypealiasNullableString")!>x<!>
|
||||||
<!DEBUG_INFO_EXPRESSION_TYPE("TypealiasNullableString")!>x<!>.hashCode()
|
<!DEBUG_INFO_EXPRESSION_TYPE("TypealiasNullableString")!>x<!>.hashCode()
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user