[FIR] Fix processing calls on unstable smartcasts with check not null call

This commit is contained in:
Dmitriy Novozhilov
2022-01-19 15:58:13 +03:00
committed by TeamCityServer
parent 1a3841d66d
commit 7d8a8d543f
7 changed files with 84 additions and 6 deletions
@@ -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")
@@ -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)
@@ -0,0 +1,35 @@
FILE: unstableSmartcastAndAmbiguity.kt
public abstract class XdSwimlaneSettings : R|kotlin/Any| {
public constructor(): R|XdSwimlaneSettings| {
super<R|kotlin/Any|>()
}
public abstract val settingsLogic: R|kotlin/String|
public get(): R|kotlin/String|
}
public final class XdIssueBasedSwimlaneSettings : R|XdSwimlaneSettings| {
public constructor(): R|XdIssueBasedSwimlaneSettings| {
super<R|XdSwimlaneSettings|>()
}
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<R|kotlin/Any|>()
}
public final var swimlaneSettings: R|XdSwimlaneSettings?| = R|<local>/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|<local>/x|.R|/XdAgile.swimlaneSettings| as R|XdIssueBasedSwimlaneSettings|)
R|<local>/x|.R|/XdAgile.swimlaneSettings|!!.R|/XdSwimlaneSettings.settingsLogic|
}
@@ -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
}
@@ -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")
@@ -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")
@@ -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) {