From 7d8a8d543f7ad188b733d020e0e62a3e0970ca41 Mon Sep 17 00:00:00 2001 From: Dmitriy Novozhilov Date: Wed, 19 Jan 2022 15:58:13 +0300 Subject: [PATCH] [FIR] Fix processing calls on unstable smartcasts with check not null call --- ...nosisCompilerFirTestdataTestGenerated.java | 6 ++++ ...TouchedTilContractsPhaseTestGenerated.java | 5 +++ .../unstableSmartcastAndAmbiguity.fir.txt | 35 +++++++++++++++++++ .../unstableSmartcastAndAmbiguity.kt | 15 ++++++++ .../runners/FirDiagnosticTestGenerated.java | 6 ++++ ...DiagnosticsWithLightTreeTestGenerated.java | 6 ++++ .../fir/resolve/calls/ResolutionStages.kt | 17 +++++---- 7 files changed, 84 insertions(+), 6 deletions(-) create mode 100644 compiler/fir/analysis-tests/testData/resolve/smartcasts/unstableSmartcastAndAmbiguity.fir.txt create mode 100644 compiler/fir/analysis-tests/testData/resolve/smartcasts/unstableSmartcastAndAmbiguity.kt diff --git a/analysis/low-level-api-fir/tests/org/jetbrains/kotlin/analysis/low/level/api/fir/diagnostic/compiler/based/DiagnosisCompilerFirTestdataTestGenerated.java b/analysis/low-level-api-fir/tests/org/jetbrains/kotlin/analysis/low/level/api/fir/diagnostic/compiler/based/DiagnosisCompilerFirTestdataTestGenerated.java index 74503b4c921..8f6eaa931c0 100644 --- a/analysis/low-level-api-fir/tests/org/jetbrains/kotlin/analysis/low/level/api/fir/diagnostic/compiler/based/DiagnosisCompilerFirTestdataTestGenerated.java +++ b/analysis/low-level-api-fir/tests/org/jetbrains/kotlin/analysis/low/level/api/fir/diagnostic/compiler/based/DiagnosisCompilerFirTestdataTestGenerated.java @@ -3699,6 +3699,12 @@ public class DiagnosisCompilerFirTestdataTestGenerated extends AbstractDiagnosis runTest("compiler/fir/analysis-tests/testData/resolve/smartcasts/smartcastsFromEquals_sameModule.kt"); } + @Test + @TestMetadata("unstableSmartcastAndAmbiguity.kt") + public void testUnstableSmartcastAndAmbiguity() throws Exception { + runTest("compiler/fir/analysis-tests/testData/resolve/smartcasts/unstableSmartcastAndAmbiguity.kt"); + } + @Nested @TestMetadata("compiler/fir/analysis-tests/testData/resolve/smartcasts/booleans") @TestDataPath("$PROJECT_ROOT") diff --git a/compiler/fir/analysis-tests/legacy-fir-tests/tests-gen/org/jetbrains/kotlin/fir/LazyBodyIsNotTouchedTilContractsPhaseTestGenerated.java b/compiler/fir/analysis-tests/legacy-fir-tests/tests-gen/org/jetbrains/kotlin/fir/LazyBodyIsNotTouchedTilContractsPhaseTestGenerated.java index 6b51bb914fa..119ecafeff0 100644 --- a/compiler/fir/analysis-tests/legacy-fir-tests/tests-gen/org/jetbrains/kotlin/fir/LazyBodyIsNotTouchedTilContractsPhaseTestGenerated.java +++ b/compiler/fir/analysis-tests/legacy-fir-tests/tests-gen/org/jetbrains/kotlin/fir/LazyBodyIsNotTouchedTilContractsPhaseTestGenerated.java @@ -3267,6 +3267,11 @@ public class LazyBodyIsNotTouchedTilContractsPhaseTestGenerated extends Abstract runTest("compiler/fir/analysis-tests/testData/resolve/smartcasts/smartcastsFromEquals_sameModule.kt"); } + @TestMetadata("unstableSmartcastAndAmbiguity.kt") + public void testUnstableSmartcastAndAmbiguity() throws Exception { + runTest("compiler/fir/analysis-tests/testData/resolve/smartcasts/unstableSmartcastAndAmbiguity.kt"); + } + @TestMetadata("compiler/fir/analysis-tests/testData/resolve/smartcasts/booleans") @TestDataPath("$PROJECT_ROOT") @RunWith(JUnit3RunnerWithInners.class) diff --git a/compiler/fir/analysis-tests/testData/resolve/smartcasts/unstableSmartcastAndAmbiguity.fir.txt b/compiler/fir/analysis-tests/testData/resolve/smartcasts/unstableSmartcastAndAmbiguity.fir.txt new file mode 100644 index 00000000000..7b7196d54cf --- /dev/null +++ b/compiler/fir/analysis-tests/testData/resolve/smartcasts/unstableSmartcastAndAmbiguity.fir.txt @@ -0,0 +1,35 @@ +FILE: unstableSmartcastAndAmbiguity.kt + public abstract class XdSwimlaneSettings : R|kotlin/Any| { + public constructor(): R|XdSwimlaneSettings| { + super() + } + + public abstract val settingsLogic: R|kotlin/String| + public get(): R|kotlin/String| + + } + public final class XdIssueBasedSwimlaneSettings : R|XdSwimlaneSettings| { + public constructor(): R|XdIssueBasedSwimlaneSettings| { + super() + } + + public final override val settingsLogic: R|kotlin/String| + public get(): R|kotlin/String| { + ^ String(hello) + } + + } + public final class XdAgile : R|kotlin/Any| { + public constructor(swimlaneSettings: R|XdSwimlaneSettings?|): R|XdAgile| { + super() + } + + public final var swimlaneSettings: R|XdSwimlaneSettings?| = R|/swimlaneSettings| + public get(): R|XdSwimlaneSettings?| + public set(value: R|XdSwimlaneSettings?|): R|kotlin/Unit| + + } + public final fun test(x: R|XdAgile|): R|kotlin/Unit| { + lval y: R|XdIssueBasedSwimlaneSettings| = (R|/x|.R|/XdAgile.swimlaneSettings| as R|XdIssueBasedSwimlaneSettings|) + R|/x|.R|/XdAgile.swimlaneSettings|!!.R|/XdSwimlaneSettings.settingsLogic| + } diff --git a/compiler/fir/analysis-tests/testData/resolve/smartcasts/unstableSmartcastAndAmbiguity.kt b/compiler/fir/analysis-tests/testData/resolve/smartcasts/unstableSmartcastAndAmbiguity.kt new file mode 100644 index 00000000000..d4791ab38f3 --- /dev/null +++ b/compiler/fir/analysis-tests/testData/resolve/smartcasts/unstableSmartcastAndAmbiguity.kt @@ -0,0 +1,15 @@ +abstract class XdSwimlaneSettings { + abstract val settingsLogic: String +} + +class XdIssueBasedSwimlaneSettings : XdSwimlaneSettings() { + override val settingsLogic: String + get() = "hello" +} + +class XdAgile(var swimlaneSettings: XdSwimlaneSettings?) + +fun test(x: XdAgile) { + val y = x.swimlaneSettings as XdIssueBasedSwimlaneSettings + x.swimlaneSettings!!.settingsLogic +} diff --git a/compiler/fir/analysis-tests/tests-gen/org/jetbrains/kotlin/test/runners/FirDiagnosticTestGenerated.java b/compiler/fir/analysis-tests/tests-gen/org/jetbrains/kotlin/test/runners/FirDiagnosticTestGenerated.java index caaf19bcd85..1e3f28e775c 100644 --- a/compiler/fir/analysis-tests/tests-gen/org/jetbrains/kotlin/test/runners/FirDiagnosticTestGenerated.java +++ b/compiler/fir/analysis-tests/tests-gen/org/jetbrains/kotlin/test/runners/FirDiagnosticTestGenerated.java @@ -3699,6 +3699,12 @@ public class FirDiagnosticTestGenerated extends AbstractFirDiagnosticTest { runTest("compiler/fir/analysis-tests/testData/resolve/smartcasts/smartcastsFromEquals_sameModule.kt"); } + @Test + @TestMetadata("unstableSmartcastAndAmbiguity.kt") + public void testUnstableSmartcastAndAmbiguity() throws Exception { + runTest("compiler/fir/analysis-tests/testData/resolve/smartcasts/unstableSmartcastAndAmbiguity.kt"); + } + @Nested @TestMetadata("compiler/fir/analysis-tests/testData/resolve/smartcasts/booleans") @TestDataPath("$PROJECT_ROOT") diff --git a/compiler/fir/analysis-tests/tests-gen/org/jetbrains/kotlin/test/runners/FirDiagnosticsWithLightTreeTestGenerated.java b/compiler/fir/analysis-tests/tests-gen/org/jetbrains/kotlin/test/runners/FirDiagnosticsWithLightTreeTestGenerated.java index afd1dfce582..009c90821cd 100644 --- a/compiler/fir/analysis-tests/tests-gen/org/jetbrains/kotlin/test/runners/FirDiagnosticsWithLightTreeTestGenerated.java +++ b/compiler/fir/analysis-tests/tests-gen/org/jetbrains/kotlin/test/runners/FirDiagnosticsWithLightTreeTestGenerated.java @@ -3699,6 +3699,12 @@ public class FirDiagnosticsWithLightTreeTestGenerated extends AbstractFirDiagnos runTest("compiler/fir/analysis-tests/testData/resolve/smartcasts/smartcastsFromEquals_sameModule.kt"); } + @Test + @TestMetadata("unstableSmartcastAndAmbiguity.kt") + public void testUnstableSmartcastAndAmbiguity() throws Exception { + runTest("compiler/fir/analysis-tests/testData/resolve/smartcasts/unstableSmartcastAndAmbiguity.kt"); + } + @Nested @TestMetadata("compiler/fir/analysis-tests/testData/resolve/smartcasts/booleans") @TestDataPath("$PROJECT_ROOT") diff --git a/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/calls/ResolutionStages.kt b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/calls/ResolutionStages.kt index 4f987228f6e..f9e8071dadf 100644 --- a/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/calls/ResolutionStages.kt +++ b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/calls/ResolutionStages.kt @@ -126,9 +126,14 @@ object CheckDispatchReceiver : ResolutionStage() { val isCandidateFromUnstableSmartcast = (candidate.originScope as? FirUnstableSmartcastTypeScope)?.isSymbolFromUnstableSmartcast(candidate.symbol) == true - if (explicitReceiverExpression is FirExpressionWithSmartcast && - !explicitReceiverExpression.isStable && - (isCandidateFromUnstableSmartcast || (isReceiverNullable && !explicitReceiverExpression.smartcastType.canBeNull)) + val smartcastedReceiver = when (explicitReceiverExpression) { + is FirCheckNotNullCall -> explicitReceiverExpression.argument + else -> explicitReceiverExpression + } as? FirExpressionWithSmartcast + + if (smartcastedReceiver != null && + !smartcastedReceiver.isStable && + (isCandidateFromUnstableSmartcast || (isReceiverNullable && !smartcastedReceiver.smartcastType.canBeNull)) ) { val dispatchReceiverType = (candidate.symbol as? FirCallableSymbol<*>)?.dispatchReceiverType?.let { context.session.typeApproximator.approximateToSuperType( @@ -137,12 +142,12 @@ object CheckDispatchReceiver : ResolutionStage() { ) ?: it } val targetType = - dispatchReceiverType ?: explicitReceiverExpression.smartcastType.coneType + dispatchReceiverType ?: smartcastedReceiver.smartcastType.coneType sink.yieldDiagnostic( UnstableSmartCast( - explicitReceiverExpression, + smartcastedReceiver, targetType, - context.session.typeContext.isTypeMismatchDueToNullability(explicitReceiverExpression.originalType.coneType, targetType) + context.session.typeContext.isTypeMismatchDueToNullability(smartcastedReceiver.originalType.coneType, targetType) ) ) } else if (isReceiverNullable) {