[FIR] Resolve return expressions in independent context

This commit is contained in:
Dmitriy Novozhilov
2020-03-02 17:40:15 +03:00
parent d4f57fb835
commit ec01893237
8 changed files with 69 additions and 19 deletions
@@ -174,10 +174,16 @@ class FirControlFlowStatementsResolveTransformer(transformer: FirBodyResolveTran
// ------------------------------- Jumps -------------------------------
override fun <E : FirTargetElement> transformJump(jump: FirJump<E>, data: ResolutionMode): CompositeTransformResult<FirStatement> {
var result = transformer.transformExpression(jump, data).single
val expectedTypeRef = (jump as? FirReturnExpression)?.target?.labeledElement?.returnTypeRef
val mode = if (expectedTypeRef != null) {
ResolutionMode.WithExpectedType(expectedTypeRef)
} else {
ResolutionMode.ContextIndependent
}
var result = transformer.transformExpression(jump, mode).single
if (result is FirReturnExpression) {
val expectedType = result.target.labeledElement.returnTypeRef.coneTypeSafe<ConeKotlinType>()
result = result.transformResult(integerLiteralTypeApproximator, expectedType)
result = result.transformResult(integerLiteralTypeApproximator, expectedTypeRef!!.coneTypeSafe())
}
dataFlowAnalyzer.exitJump(jump)
return result.compose()
@@ -0,0 +1,11 @@
interface Box<T>
public fun <T> foo(nextFunction: (T) -> T): Box<T> = null!!
fun leaves(value: String, forward: Boolean): Box<String> {
if (forward) {
return foo { "" }
} else {
return foo { "" }
}
}
@@ -0,0 +1,23 @@
FILE: untouchedReturnInIf.kt
public abstract interface Box<T> : R|kotlin/Any| {
}
public final fun <T> foo(nextFunction: R|(T) -> T|): R|Box<T>| {
^foo Null(null)!!
}
public final fun leaves(value: R|kotlin/String|, forward: R|kotlin/Boolean|): R|Box<kotlin/String>| {
when () {
R|<local>/forward| -> {
^leaves R|/foo|<R|kotlin/String|>(<L> = foo@fun <anonymous>(it: R|kotlin/String|): R|kotlin/String| {
^ String()
}
)
}
else -> {
^leaves R|/foo|<R|kotlin/String|>(<L> = foo@fun <anonymous>(it: R|kotlin/String|): R|kotlin/String| {
^ String()
}
)
}
}
}
@@ -9,9 +9,9 @@ FILE: typesInLocalFunctions.kt
lval s: R|Some| = R|/Some.Some|()
when () {
Boolean(true) -> {
^foo fun <implicit>.<anonymous>(): <implicit> {
when () {
(s# is Some) -> {
^foo fun <anonymous>(): R|kotlin/Boolean| {
^ when () {
(R|<local>/s| is R|Some|) -> {
Boolean(true)
}
else -> {
@@ -23,8 +23,8 @@ FILE: typesInLocalFunctions.kt
}
else -> {
^foo fun <implicit>.<anonymous>(): <implicit> {
Boolean(true)
^foo fun <anonymous>(): R|kotlin/Boolean| {
^ Boolean(true)
}
}
@@ -338,6 +338,11 @@ public class FirDiagnosticsTestGenerated extends AbstractFirDiagnosticsTest {
runTest("compiler/fir/resolve/testData/resolve/typeParameterVsNested.kt");
}
@TestMetadata("typesInLocalFunctions.kt")
public void testTypesInLocalFunctions() throws Exception {
runTest("compiler/fir/resolve/testData/resolve/typesInLocalFunctions.kt");
}
@TestMetadata("varargInPrimaryConstructor.kt")
public void testVarargInPrimaryConstructor() throws Exception {
runTest("compiler/fir/resolve/testData/resolve/varargInPrimaryConstructor.kt");
@@ -460,6 +465,11 @@ public class FirDiagnosticsTestGenerated extends AbstractFirDiagnosticsTest {
runTest("compiler/fir/resolve/testData/resolve/arguments/tryInLambda.kt");
}
@TestMetadata("untouchedReturnInIf.kt")
public void testUntouchedReturnInIf() throws Exception {
runTest("compiler/fir/resolve/testData/resolve/arguments/untouchedReturnInIf.kt");
}
@TestMetadata("vararg.kt")
public void testVararg() throws Exception {
runTest("compiler/fir/resolve/testData/resolve/arguments/vararg.kt");
@@ -1361,11 +1371,6 @@ public class FirDiagnosticsTestGenerated extends AbstractFirDiagnosticsTest {
public void testJavaAccessorConversion() throws Exception {
runTest("compiler/fir/resolve/testData/resolve/problems/javaAccessorConversion.kt");
}
@TestMetadata("typesInLocalFunctions.kt")
public void testTypesInLocalFunctions() throws Exception {
runTest("compiler/fir/resolve/testData/resolve/problems/typesInLocalFunctions.kt");
}
}
@TestMetadata("compiler/fir/resolve/testData/resolve/references")
@@ -338,6 +338,11 @@ public class FirDiagnosticsWithLightTreeTestGenerated extends AbstractFirDiagnos
runTest("compiler/fir/resolve/testData/resolve/typeParameterVsNested.kt");
}
@TestMetadata("typesInLocalFunctions.kt")
public void testTypesInLocalFunctions() throws Exception {
runTest("compiler/fir/resolve/testData/resolve/typesInLocalFunctions.kt");
}
@TestMetadata("varargInPrimaryConstructor.kt")
public void testVarargInPrimaryConstructor() throws Exception {
runTest("compiler/fir/resolve/testData/resolve/varargInPrimaryConstructor.kt");
@@ -460,6 +465,11 @@ public class FirDiagnosticsWithLightTreeTestGenerated extends AbstractFirDiagnos
runTest("compiler/fir/resolve/testData/resolve/arguments/tryInLambda.kt");
}
@TestMetadata("untouchedReturnInIf.kt")
public void testUntouchedReturnInIf() throws Exception {
runTest("compiler/fir/resolve/testData/resolve/arguments/untouchedReturnInIf.kt");
}
@TestMetadata("vararg.kt")
public void testVararg() throws Exception {
runTest("compiler/fir/resolve/testData/resolve/arguments/vararg.kt");
@@ -1361,11 +1371,6 @@ public class FirDiagnosticsWithLightTreeTestGenerated extends AbstractFirDiagnos
public void testJavaAccessorConversion() throws Exception {
runTest("compiler/fir/resolve/testData/resolve/problems/javaAccessorConversion.kt");
}
@TestMetadata("typesInLocalFunctions.kt")
public void testTypesInLocalFunctions() throws Exception {
runTest("compiler/fir/resolve/testData/resolve/problems/typesInLocalFunctions.kt");
}
}
@TestMetadata("compiler/fir/resolve/testData/resolve/references")
@@ -36,7 +36,7 @@ fun main(x: Inv<Int>) {
}
foo1 {
if (x.hashCode() == 0) return@foo1 <!UNRESOLVED_REFERENCE!>::bar<!>
if (x.hashCode() == 0) return@foo1 ::bar
::bar
}