From 64c5608f3186152044fa79a21a60a09fa2fc947a Mon Sep 17 00:00:00 2001 From: pyos Date: Fri, 5 Feb 2021 11:20:57 +0100 Subject: [PATCH] FIR: expect nullable type for elvis LHS --- .../FirBlackBoxCodegenTestGenerated.java | 6 +++ .../kotlin/fir/resolve/ResolutionMode.kt | 5 +++ ...ControlFlowStatementsResolveTransformer.kt | 15 ++++--- .../box/elvis/ofNonNullableResultType.kt | 7 +++ .../ir/irText/expressions/kt30796.fir.kt.txt | 11 ++--- .../ir/irText/expressions/kt30796.fir.txt | 44 +++++++++---------- .../codegen/BlackBoxCodegenTestGenerated.java | 6 +++ .../IrBlackBoxCodegenTestGenerated.java | 6 +++ .../LightAnalysisModeTestGenerated.java | 5 +++ .../IrJsCodegenBoxES6TestGenerated.java | 5 +++ .../IrJsCodegenBoxTestGenerated.java | 5 +++ .../semantics/JsCodegenBoxTestGenerated.java | 5 +++ .../IrCodegenBoxWasmTestGenerated.java | 5 +++ 13 files changed, 91 insertions(+), 34 deletions(-) create mode 100644 compiler/testData/codegen/box/elvis/ofNonNullableResultType.kt diff --git a/compiler/fir/fir2ir/tests-gen/org/jetbrains/kotlin/test/runners/codegen/FirBlackBoxCodegenTestGenerated.java b/compiler/fir/fir2ir/tests-gen/org/jetbrains/kotlin/test/runners/codegen/FirBlackBoxCodegenTestGenerated.java index eb521be52a6..70f85227e17 100644 --- a/compiler/fir/fir2ir/tests-gen/org/jetbrains/kotlin/test/runners/codegen/FirBlackBoxCodegenTestGenerated.java +++ b/compiler/fir/fir2ir/tests-gen/org/jetbrains/kotlin/test/runners/codegen/FirBlackBoxCodegenTestGenerated.java @@ -13644,6 +13644,12 @@ public class FirBlackBoxCodegenTestGenerated extends AbstractFirBlackBoxCodegenT runTest("compiler/testData/codegen/box/elvis/nullNullOk.kt"); } + @Test + @TestMetadata("ofNonNullableResultType.kt") + public void testOfNonNullableResultType() throws Exception { + runTest("compiler/testData/codegen/box/elvis/ofNonNullableResultType.kt"); + } + @Test @TestMetadata("primitive.kt") public void testPrimitive() throws Exception { diff --git a/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/ResolutionMode.kt b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/ResolutionMode.kt index 44d33bb116f..e7a0251a093 100644 --- a/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/ResolutionMode.kt +++ b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/ResolutionMode.kt @@ -26,6 +26,11 @@ sealed class ResolutionMode { fun withExpectedType(expectedTypeRef: FirTypeRef?): ResolutionMode = expectedTypeRef?.let { ResolutionMode.WithExpectedType(it) } ?: ResolutionMode.ContextDependent +@JvmName("withExpectedTypeNullable") +fun withExpectedType(coneType: ConeKotlinType?): ResolutionMode { + return coneType?.let { withExpectedType(it) } ?: ResolutionMode.ContextDependent +} + fun withExpectedType(coneType: ConeKotlinType): ResolutionMode { val typeRef = buildResolvedTypeRef { type = coneType diff --git a/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/transformers/body/resolve/FirControlFlowStatementsResolveTransformer.kt b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/transformers/body/resolve/FirControlFlowStatementsResolveTransformer.kt index 3864150cf6e..00ab34356f2 100644 --- a/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/transformers/body/resolve/FirControlFlowStatementsResolveTransformer.kt +++ b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/transformers/body/resolve/FirControlFlowStatementsResolveTransformer.kt @@ -5,7 +5,6 @@ package org.jetbrains.kotlin.fir.resolve.transformers.body.resolve -import org.jetbrains.kotlin.fir.FirFakeSourceElementKind import org.jetbrains.kotlin.fir.FirTargetElement import org.jetbrains.kotlin.fir.diagnostics.ConeSimpleDiagnostic import org.jetbrains.kotlin.fir.diagnostics.DiagnosticKind @@ -18,7 +17,7 @@ import org.jetbrains.kotlin.fir.resolve.transformers.FirSyntheticCallGenerator import org.jetbrains.kotlin.fir.resolve.transformers.FirWhenExhaustivenessTransformer import org.jetbrains.kotlin.fir.resolve.withExpectedType import org.jetbrains.kotlin.fir.resolvedTypeFromPrototype -import org.jetbrains.kotlin.fir.types.FirImplicitTypeRef +import org.jetbrains.kotlin.fir.types.* import org.jetbrains.kotlin.fir.types.builder.buildErrorTypeRef import org.jetbrains.kotlin.fir.visitors.CompositeTransformResult import org.jetbrains.kotlin.fir.visitors.compose @@ -228,12 +227,14 @@ class FirControlFlowStatementsResolveTransformer(transformer: FirBodyResolveTran ): CompositeTransformResult { if (elvisExpression.calleeReference is FirResolvedNamedReference) return elvisExpression.compose() elvisExpression.transformAnnotations(transformer, data) - val expectedArgumentType = - if (data is ResolutionMode.WithExpectedType && data.expectedType !is FirImplicitTypeRef) data - else ResolutionMode.ContextDependent - elvisExpression.transformLhs(transformer, expectedArgumentType) + + val expectedType = data.expectedType?.coneTypeSafe() + val resolutionModeForLhs = withExpectedType(expectedType?.withNullability(ConeNullability.NULLABLE)) + elvisExpression.transformLhs(transformer, resolutionModeForLhs) dataFlowAnalyzer.exitElvisLhs(elvisExpression) - elvisExpression.transformRhs(transformer, expectedArgumentType) + + val resolutionModeForRhs = withExpectedType(expectedType) + elvisExpression.transformRhs(transformer, resolutionModeForRhs) val result = syntheticCallGenerator.generateCalleeForElvisExpression(elvisExpression, resolutionContext)?.let { callCompleter.completeCall(it, data.expectedType).result diff --git a/compiler/testData/codegen/box/elvis/ofNonNullableResultType.kt b/compiler/testData/codegen/box/elvis/ofNonNullableResultType.kt new file mode 100644 index 00000000000..0564ce69ccd --- /dev/null +++ b/compiler/testData/codegen/box/elvis/ofNonNullableResultType.kt @@ -0,0 +1,7 @@ +fun f(): T? = "OK" as? T + +fun g(): Nothing = throw RuntimeException("fail") + +fun h(): T = run { f() } ?: run { g() } + +fun box(): String = h() diff --git a/compiler/testData/ir/irText/expressions/kt30796.fir.kt.txt b/compiler/testData/ir/irText/expressions/kt30796.fir.kt.txt index 78adb7af6f6..067424caa70 100644 --- a/compiler/testData/ir/irText/expressions/kt30796.fir.kt.txt +++ b/compiler/testData/ir/irText/expressions/kt30796.fir.kt.txt @@ -50,17 +50,17 @@ fun test(value: T, value2: T) { } } val x5: Any = { // BLOCK - val : Any = magic() + val : Any? = magic() when { EQEQ(arg0 = , arg1 = null) -> 42 else -> } } val x6: Any = { // BLOCK - val : Any = { // BLOCK + val : Any? = { // BLOCK val : T = value when { - EQEQ(arg0 = , arg1 = null) -> magic() + EQEQ(arg0 = , arg1 = null) -> magic() else -> } } @@ -70,8 +70,8 @@ fun test(value: T, value2: T) { } } val x7: Any = { // BLOCK - val : Any = { // BLOCK - val : Any = magic() + val : Any? = { // BLOCK + val : Any? = magic() when { EQEQ(arg0 = , arg1 = null) -> value else -> @@ -83,3 +83,4 @@ fun test(value: T, value2: T) { } } } + diff --git a/compiler/testData/ir/irText/expressions/kt30796.fir.txt b/compiler/testData/ir/irText/expressions/kt30796.fir.txt index 3e33c57eb70..e6aab2f4ce2 100644 --- a/compiler/testData/ir/irText/expressions/kt30796.fir.txt +++ b/compiler/testData/ir/irText/expressions/kt30796.fir.txt @@ -97,65 +97,65 @@ FILE fqName: fileName:/kt30796.kt then: GET_VAR 'val tmp_5: T of .test [val] declared in .test' type=T of .test origin=null VAR name:x5 type:kotlin.Any [val] BLOCK type=kotlin.Any origin=ELVIS - VAR IR_TEMPORARY_VARIABLE name:tmp_7 type:kotlin.Any [val] - CALL 'public final fun magic (): T of .magic declared in ' type=kotlin.Any origin=null - : kotlin.Any + VAR IR_TEMPORARY_VARIABLE name:tmp_7 type:kotlin.Any? [val] + CALL 'public final fun magic (): T of .magic declared in ' type=kotlin.Any? origin=null + : kotlin.Any? WHEN type=kotlin.Any origin=ELVIS BRANCH if: CALL 'public final fun EQEQ (arg0: kotlin.Any?, arg1: kotlin.Any?): kotlin.Boolean declared in kotlin.internal.ir' type=kotlin.Boolean origin=EQEQ - arg0: GET_VAR 'val tmp_7: kotlin.Any [val] declared in .test' type=kotlin.Any origin=null + arg0: GET_VAR 'val tmp_7: kotlin.Any? [val] declared in .test' type=kotlin.Any? origin=null arg1: CONST Null type=kotlin.Nothing? value=null then: CONST Int type=kotlin.Int value=42 BRANCH if: CONST Boolean type=kotlin.Boolean value=true - then: GET_VAR 'val tmp_7: kotlin.Any [val] declared in .test' type=kotlin.Any origin=null + then: GET_VAR 'val tmp_7: kotlin.Any? [val] declared in .test' type=kotlin.Any? origin=null VAR name:x6 type:kotlin.Any [val] BLOCK type=kotlin.Any origin=ELVIS - VAR IR_TEMPORARY_VARIABLE name:tmp_8 type:kotlin.Any [val] - BLOCK type=kotlin.Any origin=ELVIS + VAR IR_TEMPORARY_VARIABLE name:tmp_8 type:kotlin.Any? [val] + BLOCK type=kotlin.Any? origin=ELVIS VAR IR_TEMPORARY_VARIABLE name:tmp_9 type:T of .test [val] GET_VAR 'value: T of .test declared in .test' type=T of .test origin=null - WHEN type=kotlin.Any origin=ELVIS + WHEN type=kotlin.Any? origin=ELVIS BRANCH if: CALL 'public final fun EQEQ (arg0: kotlin.Any?, arg1: kotlin.Any?): kotlin.Boolean declared in kotlin.internal.ir' type=kotlin.Boolean origin=EQEQ arg0: GET_VAR 'val tmp_9: T of .test [val] declared in .test' type=T of .test origin=null arg1: CONST Null type=kotlin.Nothing? value=null - then: CALL 'public final fun magic (): T of .magic declared in ' type=kotlin.Any origin=null - : kotlin.Any + then: CALL 'public final fun magic (): T of .magic declared in ' type=kotlin.Any? origin=null + : kotlin.Any? BRANCH if: CONST Boolean type=kotlin.Boolean value=true then: GET_VAR 'val tmp_9: T of .test [val] declared in .test' type=T of .test origin=null WHEN type=kotlin.Any origin=ELVIS BRANCH if: CALL 'public final fun EQEQ (arg0: kotlin.Any?, arg1: kotlin.Any?): kotlin.Boolean declared in kotlin.internal.ir' type=kotlin.Boolean origin=EQEQ - arg0: GET_VAR 'val tmp_8: kotlin.Any [val] declared in .test' type=kotlin.Any origin=null + arg0: GET_VAR 'val tmp_8: kotlin.Any? [val] declared in .test' type=kotlin.Any? origin=null arg1: CONST Null type=kotlin.Nothing? value=null then: CONST Int type=kotlin.Int value=42 BRANCH if: CONST Boolean type=kotlin.Boolean value=true - then: GET_VAR 'val tmp_8: kotlin.Any [val] declared in .test' type=kotlin.Any origin=null + then: GET_VAR 'val tmp_8: kotlin.Any? [val] declared in .test' type=kotlin.Any? origin=null VAR name:x7 type:kotlin.Any [val] BLOCK type=kotlin.Any origin=ELVIS - VAR IR_TEMPORARY_VARIABLE name:tmp_10 type:kotlin.Any [val] - BLOCK type=kotlin.Any origin=ELVIS - VAR IR_TEMPORARY_VARIABLE name:tmp_11 type:kotlin.Any [val] - CALL 'public final fun magic (): T of .magic declared in ' type=kotlin.Any origin=null - : kotlin.Any - WHEN type=kotlin.Any origin=ELVIS + VAR IR_TEMPORARY_VARIABLE name:tmp_10 type:kotlin.Any? [val] + BLOCK type=kotlin.Any? origin=ELVIS + VAR IR_TEMPORARY_VARIABLE name:tmp_11 type:kotlin.Any? [val] + CALL 'public final fun magic (): T of .magic declared in ' type=kotlin.Any? origin=null + : kotlin.Any? + WHEN type=kotlin.Any? origin=ELVIS BRANCH if: CALL 'public final fun EQEQ (arg0: kotlin.Any?, arg1: kotlin.Any?): kotlin.Boolean declared in kotlin.internal.ir' type=kotlin.Boolean origin=EQEQ - arg0: GET_VAR 'val tmp_11: kotlin.Any [val] declared in .test' type=kotlin.Any origin=null + arg0: GET_VAR 'val tmp_11: kotlin.Any? [val] declared in .test' type=kotlin.Any? origin=null arg1: CONST Null type=kotlin.Nothing? value=null then: GET_VAR 'value: T of .test declared in .test' type=T of .test origin=null BRANCH if: CONST Boolean type=kotlin.Boolean value=true - then: GET_VAR 'val tmp_11: kotlin.Any [val] declared in .test' type=kotlin.Any origin=null + then: GET_VAR 'val tmp_11: kotlin.Any? [val] declared in .test' type=kotlin.Any? origin=null WHEN type=kotlin.Any origin=ELVIS BRANCH if: CALL 'public final fun EQEQ (arg0: kotlin.Any?, arg1: kotlin.Any?): kotlin.Boolean declared in kotlin.internal.ir' type=kotlin.Boolean origin=EQEQ - arg0: GET_VAR 'val tmp_10: kotlin.Any [val] declared in .test' type=kotlin.Any origin=null + arg0: GET_VAR 'val tmp_10: kotlin.Any? [val] declared in .test' type=kotlin.Any? origin=null arg1: CONST Null type=kotlin.Nothing? value=null then: CONST Int type=kotlin.Int value=42 BRANCH if: CONST Boolean type=kotlin.Boolean value=true - then: GET_VAR 'val tmp_10: kotlin.Any [val] declared in .test' type=kotlin.Any origin=null + then: GET_VAR 'val tmp_10: kotlin.Any? [val] declared in .test' type=kotlin.Any? origin=null diff --git a/compiler/tests-common-new/tests-gen/org/jetbrains/kotlin/test/runners/codegen/BlackBoxCodegenTestGenerated.java b/compiler/tests-common-new/tests-gen/org/jetbrains/kotlin/test/runners/codegen/BlackBoxCodegenTestGenerated.java index 0d276b1f143..f9d2ebea1ef 100644 --- a/compiler/tests-common-new/tests-gen/org/jetbrains/kotlin/test/runners/codegen/BlackBoxCodegenTestGenerated.java +++ b/compiler/tests-common-new/tests-gen/org/jetbrains/kotlin/test/runners/codegen/BlackBoxCodegenTestGenerated.java @@ -13644,6 +13644,12 @@ public class BlackBoxCodegenTestGenerated extends AbstractBlackBoxCodegenTest { runTest("compiler/testData/codegen/box/elvis/nullNullOk.kt"); } + @Test + @TestMetadata("ofNonNullableResultType.kt") + public void testOfNonNullableResultType() throws Exception { + runTest("compiler/testData/codegen/box/elvis/ofNonNullableResultType.kt"); + } + @Test @TestMetadata("primitive.kt") public void testPrimitive() throws Exception { diff --git a/compiler/tests-common-new/tests-gen/org/jetbrains/kotlin/test/runners/codegen/IrBlackBoxCodegenTestGenerated.java b/compiler/tests-common-new/tests-gen/org/jetbrains/kotlin/test/runners/codegen/IrBlackBoxCodegenTestGenerated.java index a5b60776c46..42eaa7c9f1c 100644 --- a/compiler/tests-common-new/tests-gen/org/jetbrains/kotlin/test/runners/codegen/IrBlackBoxCodegenTestGenerated.java +++ b/compiler/tests-common-new/tests-gen/org/jetbrains/kotlin/test/runners/codegen/IrBlackBoxCodegenTestGenerated.java @@ -13644,6 +13644,12 @@ public class IrBlackBoxCodegenTestGenerated extends AbstractIrBlackBoxCodegenTes runTest("compiler/testData/codegen/box/elvis/nullNullOk.kt"); } + @Test + @TestMetadata("ofNonNullableResultType.kt") + public void testOfNonNullableResultType() throws Exception { + runTest("compiler/testData/codegen/box/elvis/ofNonNullableResultType.kt"); + } + @Test @TestMetadata("primitive.kt") public void testPrimitive() throws Exception { diff --git a/compiler/tests-gen/org/jetbrains/kotlin/codegen/LightAnalysisModeTestGenerated.java b/compiler/tests-gen/org/jetbrains/kotlin/codegen/LightAnalysisModeTestGenerated.java index 037244e41a9..8b46e23e3fb 100644 --- a/compiler/tests-gen/org/jetbrains/kotlin/codegen/LightAnalysisModeTestGenerated.java +++ b/compiler/tests-gen/org/jetbrains/kotlin/codegen/LightAnalysisModeTestGenerated.java @@ -11220,6 +11220,11 @@ public class LightAnalysisModeTestGenerated extends AbstractLightAnalysisModeTes runTest("compiler/testData/codegen/box/elvis/nullNullOk.kt"); } + @TestMetadata("ofNonNullableResultType.kt") + public void testOfNonNullableResultType() throws Exception { + runTest("compiler/testData/codegen/box/elvis/ofNonNullableResultType.kt"); + } + @TestMetadata("primitive.kt") public void testPrimitive() throws Exception { runTest("compiler/testData/codegen/box/elvis/primitive.kt"); diff --git a/js/js.tests/tests-gen/org/jetbrains/kotlin/js/test/es6/semantics/IrJsCodegenBoxES6TestGenerated.java b/js/js.tests/tests-gen/org/jetbrains/kotlin/js/test/es6/semantics/IrJsCodegenBoxES6TestGenerated.java index 616a670a869..610047dfa2a 100644 --- a/js/js.tests/tests-gen/org/jetbrains/kotlin/js/test/es6/semantics/IrJsCodegenBoxES6TestGenerated.java +++ b/js/js.tests/tests-gen/org/jetbrains/kotlin/js/test/es6/semantics/IrJsCodegenBoxES6TestGenerated.java @@ -10015,6 +10015,11 @@ public class IrJsCodegenBoxES6TestGenerated extends AbstractIrJsCodegenBoxES6Tes runTest("compiler/testData/codegen/box/elvis/nullNullOk.kt"); } + @TestMetadata("ofNonNullableResultType.kt") + public void testOfNonNullableResultType() throws Exception { + runTest("compiler/testData/codegen/box/elvis/ofNonNullableResultType.kt"); + } + @TestMetadata("primitive.kt") public void testPrimitive() throws Exception { runTest("compiler/testData/codegen/box/elvis/primitive.kt"); diff --git a/js/js.tests/tests-gen/org/jetbrains/kotlin/js/test/ir/semantics/IrJsCodegenBoxTestGenerated.java b/js/js.tests/tests-gen/org/jetbrains/kotlin/js/test/ir/semantics/IrJsCodegenBoxTestGenerated.java index 037a75ef67b..5ee340ea5bb 100644 --- a/js/js.tests/tests-gen/org/jetbrains/kotlin/js/test/ir/semantics/IrJsCodegenBoxTestGenerated.java +++ b/js/js.tests/tests-gen/org/jetbrains/kotlin/js/test/ir/semantics/IrJsCodegenBoxTestGenerated.java @@ -9500,6 +9500,11 @@ public class IrJsCodegenBoxTestGenerated extends AbstractIrJsCodegenBoxTest { runTest("compiler/testData/codegen/box/elvis/nullNullOk.kt"); } + @TestMetadata("ofNonNullableResultType.kt") + public void testOfNonNullableResultType() throws Exception { + runTest("compiler/testData/codegen/box/elvis/ofNonNullableResultType.kt"); + } + @TestMetadata("primitive.kt") public void testPrimitive() throws Exception { runTest("compiler/testData/codegen/box/elvis/primitive.kt"); diff --git a/js/js.tests/tests-gen/org/jetbrains/kotlin/js/test/semantics/JsCodegenBoxTestGenerated.java b/js/js.tests/tests-gen/org/jetbrains/kotlin/js/test/semantics/JsCodegenBoxTestGenerated.java index 1051675f628..0011f4a413b 100644 --- a/js/js.tests/tests-gen/org/jetbrains/kotlin/js/test/semantics/JsCodegenBoxTestGenerated.java +++ b/js/js.tests/tests-gen/org/jetbrains/kotlin/js/test/semantics/JsCodegenBoxTestGenerated.java @@ -9500,6 +9500,11 @@ public class JsCodegenBoxTestGenerated extends AbstractJsCodegenBoxTest { runTest("compiler/testData/codegen/box/elvis/nullNullOk.kt"); } + @TestMetadata("ofNonNullableResultType.kt") + public void testOfNonNullableResultType() throws Exception { + runTest("compiler/testData/codegen/box/elvis/ofNonNullableResultType.kt"); + } + @TestMetadata("primitive.kt") public void testPrimitive() throws Exception { runTest("compiler/testData/codegen/box/elvis/primitive.kt"); diff --git a/js/js.tests/tests-gen/org/jetbrains/kotlin/js/test/wasm/semantics/IrCodegenBoxWasmTestGenerated.java b/js/js.tests/tests-gen/org/jetbrains/kotlin/js/test/wasm/semantics/IrCodegenBoxWasmTestGenerated.java index d39ca056001..6d2b6c862c2 100644 --- a/js/js.tests/tests-gen/org/jetbrains/kotlin/js/test/wasm/semantics/IrCodegenBoxWasmTestGenerated.java +++ b/js/js.tests/tests-gen/org/jetbrains/kotlin/js/test/wasm/semantics/IrCodegenBoxWasmTestGenerated.java @@ -4549,6 +4549,11 @@ public class IrCodegenBoxWasmTestGenerated extends AbstractIrCodegenBoxWasmTest runTest("compiler/testData/codegen/box/elvis/nullNullOk.kt"); } + @TestMetadata("ofNonNullableResultType.kt") + public void testOfNonNullableResultType() throws Exception { + runTest("compiler/testData/codegen/box/elvis/ofNonNullableResultType.kt"); + } + @TestMetadata("primitive.kt") public void testPrimitive() throws Exception { runTest("compiler/testData/codegen/box/elvis/primitive.kt");