From f1e56c4b3e3357188e846f78fb96cbdbdc2f382e Mon Sep 17 00:00:00 2001 From: Dmitriy Novozhilov Date: Wed, 21 Aug 2019 13:31:50 +0300 Subject: [PATCH] [FIR] Force resolving all declaration while resolving of body with implicit type --- .../transformers/FirBodyResolveTransformer.kt | 67 +++++++++------ .../resolve/testData/resolve/localObject.kt | 47 +++++++++++ .../resolve/testData/resolve/localObject.txt | 84 +++++++++++++++++++ .../fir/FirResolveTestCaseGenerated.java | 5 ++ .../ir/irText/expressions/bangbang.fir.txt | 6 +- 5 files changed, 181 insertions(+), 28 deletions(-) create mode 100644 compiler/fir/resolve/testData/resolve/localObject.kt create mode 100644 compiler/fir/resolve/testData/resolve/localObject.txt diff --git a/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/transformers/FirBodyResolveTransformer.kt b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/transformers/FirBodyResolveTransformer.kt index dd3b39477a2..0052c1f1b87 100644 --- a/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/transformers/FirBodyResolveTransformer.kt +++ b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/transformers/FirBodyResolveTransformer.kt @@ -41,9 +41,12 @@ import org.jetbrains.kotlin.utils.addIfNotNull open class FirBodyResolveTransformer( final override val session: FirSession, phase: FirResolvePhase, - val implicitTypeOnly: Boolean, + implicitTypeOnly: Boolean, val scopeSession: ScopeSession = ScopeSession() ) : FirAbstractPhaseTransformer(phase), BodyResolveComponents { + var implicitTypeOnly: Boolean = implicitTypeOnly + private set + final override val returnTypeCalculator: ReturnTypeCalculator = ReturnTypeCalculatorWithJump(session, scopeSession) final override val labels: SetMultimap = LinkedHashMultimap.create() final override val noExpectedType = FirImplicitTypeRefImpl(null) @@ -554,17 +557,19 @@ open class FirBodyResolveTransformer( if ((returnTypeRef !is FirImplicitTypeRef) && implicitTypeOnly) { return namedFunction.compose() } - if (returnTypeRef is FirImplicitTypeRef) { - namedFunction.transformReturnTypeRef(StoreType, FirComputingImplicitTypeRef) - } - - val receiverTypeRef = namedFunction.receiverTypeRef - return if (receiverTypeRef != null) { - withLabelAndReceiverType(namedFunction.name, namedFunction, receiverTypeRef.coneTypeUnsafe()) { - transformFunctionWithGivenSignature(namedFunction, returnTypeRef, receiverTypeRef) + return withFullBodyResolve { + if (returnTypeRef is FirImplicitTypeRef) { + namedFunction.transformReturnTypeRef(StoreType, FirComputingImplicitTypeRef) + } + + val receiverTypeRef = namedFunction.receiverTypeRef + if (receiverTypeRef != null) { + withLabelAndReceiverType(namedFunction.name, namedFunction, receiverTypeRef.coneTypeUnsafe()) { + transformFunctionWithGivenSignature(namedFunction, returnTypeRef, receiverTypeRef) + } + } else { + transformFunctionWithGivenSignature(namedFunction, returnTypeRef) } - } else { - transformFunctionWithGivenSignature(namedFunction, returnTypeRef) } } @@ -672,22 +677,24 @@ open class FirBodyResolveTransformer( if (returnTypeRef is FirImplicitTypeRef) { property.transformReturnTypeRef(StoreType, FirComputingImplicitTypeRef) } - return withScopeCleanup(localScopes) { - localScopes.addIfNotNull(primaryConstructorParametersScope) - withContainer(property) { - property.transformChildrenWithoutAccessors(this, returnTypeRef) - if (property.initializer != null) { - storeVariableReturnType(property) - } - withScopeCleanup(localScopes) { - localScopes.add(FirLocalScope().apply { - storeBackingField(property) - }) - property.transformAccessors() + return withFullBodyResolve { + withScopeCleanup(localScopes) { + localScopes.addIfNotNull(primaryConstructorParametersScope) + withContainer(property) { + property.transformChildrenWithoutAccessors(this, returnTypeRef) + if (property.initializer != null) { + storeVariableReturnType(property) + } + withScopeCleanup(localScopes) { + localScopes.add(FirLocalScope().apply { + storeBackingField(property) + }) + property.transformAccessors() + } } + property.resolvePhase = transformerPhase + property.compose() } - property.resolvePhase = transformerPhase - property.compose() } } @@ -777,6 +784,16 @@ open class FirBodyResolveTransformer( } } + private inline fun withFullBodyResolve(crossinline l: () -> T): T { + if (!implicitTypeOnly) return l() + implicitTypeOnly = false + return try { + l() + } finally { + implicitTypeOnly = true + } + } + internal fun storeTypeFromCallee(access: T) where T : FirQualifiedAccess, T : FirExpression { access.resultType = callCompleter.typeFromCallee(access) } diff --git a/compiler/fir/resolve/testData/resolve/localObject.kt b/compiler/fir/resolve/testData/resolve/localObject.kt new file mode 100644 index 00000000000..db4119be3b2 --- /dev/null +++ b/compiler/fir/resolve/testData/resolve/localObject.kt @@ -0,0 +1,47 @@ +fun run(block: () -> T): T = block() + +interface Foo { + fun foo(): Int +} + +fun tesLambda(x: Int) = run { + val obj = object : Foo { + override fun foo(): Int { + return x + 1 + } + } + 2 +} + +class TestProperty { + val intConst: Int = 1 + + var x = 1 + set(value) { + val obj = object : Foo { + override fun foo(): Int { + return intConst + 1 + } + } + field = value + } + + val y: Int + get() { + val obj = object : Foo { + override fun foo(): Int { + return intConst + 1 + } + } + 1 + } + + val z = run { + val obj = object : Foo { + override fun foo(): Int { + return x + 1 + } + } + 2 + } +} \ No newline at end of file diff --git a/compiler/fir/resolve/testData/resolve/localObject.txt b/compiler/fir/resolve/testData/resolve/localObject.txt new file mode 100644 index 00000000000..eccbba613b9 --- /dev/null +++ b/compiler/fir/resolve/testData/resolve/localObject.txt @@ -0,0 +1,84 @@ +FILE: localObject.kt + public final fun run(block: R|kotlin/Function0|): R|T| { + ^run R|/block|.R|FakeOverride|() + } + public abstract interface Foo : R|kotlin/Any| { + public abstract fun foo(): R|kotlin/Int| + + } + public final fun tesLambda(x: R|kotlin/Int|): R|kotlin/Int| { + ^tesLambda R|/run|( = run@fun (): R|kotlin/Int| { + lval obj: R|Foo| = object : R|Foo| { + private constructor(): R|kotlin/Any| { + super() + } + + public final override fun foo(): R|kotlin/Int| { + ^foo R|/x|.R|kotlin/Int.plus|(Int(1)) + } + + } + + Int(2) + } + ) + } + public final class TestProperty : R|kotlin/Any| { + public constructor(): R|TestProperty| { + super() + } + + public final val intConst: R|kotlin/Int| = Int(1) + public get(): R|kotlin/Int| + + public final var x: R|kotlin/Int| = Int(1) + public get(): R|kotlin/Int| + public set(value: R|kotlin/Int|): R|kotlin/Unit| { + lval obj: R|Foo| = object : R|Foo| { + private constructor(): R|kotlin/Any| { + super() + } + + public final override fun foo(): R|kotlin/Int| { + ^foo R|/TestProperty.intConst|.R|kotlin/Int.plus|(Int(1)) + } + + } + + F|/TestProperty.x| = R|/value| + } + + public final val y: R|kotlin/Int| + public get(): R|kotlin/Int| { + lval obj: R|Foo| = object : R|Foo| { + private constructor(): R|kotlin/Any| { + super() + } + + public final override fun foo(): R|kotlin/Int| { + ^foo R|/TestProperty.intConst|.R|kotlin/Int.plus|(Int(1)) + } + + } + + Int(1) + } + + public final val z: R|kotlin/Int| = R|/run|( = run@fun (): R|kotlin/Int| { + lval obj: R|Foo| = object : R|Foo| { + private constructor(): R|kotlin/Any| { + super() + } + + public final override fun foo(): R|kotlin/Int| { + ^foo R|/TestProperty.x|.R|kotlin/Int.plus|(Int(1)) + } + + } + + Int(2) + } + ) + public get(): R|kotlin/Int| + + } diff --git a/compiler/fir/resolve/tests/org/jetbrains/kotlin/fir/FirResolveTestCaseGenerated.java b/compiler/fir/resolve/tests/org/jetbrains/kotlin/fir/FirResolveTestCaseGenerated.java index 4b0a61ddbff..f7fb3263f31 100644 --- a/compiler/fir/resolve/tests/org/jetbrains/kotlin/fir/FirResolveTestCaseGenerated.java +++ b/compiler/fir/resolve/tests/org/jetbrains/kotlin/fir/FirResolveTestCaseGenerated.java @@ -99,6 +99,11 @@ public class FirResolveTestCaseGenerated extends AbstractFirResolveTestCase { runTest("compiler/fir/resolve/testData/resolve/intersectionTypes.kt"); } + @TestMetadata("localObject.kt") + public void testLocalObject() throws Exception { + runTest("compiler/fir/resolve/testData/resolve/localObject.kt"); + } + @TestMetadata("nestedClass.kt") public void testNestedClass() throws Exception { runTest("compiler/fir/resolve/testData/resolve/nestedClass.kt"); diff --git a/compiler/testData/ir/irText/expressions/bangbang.fir.txt b/compiler/testData/ir/irText/expressions/bangbang.fir.txt index 095605802c1..e2f45f22fe3 100644 --- a/compiler/testData/ir/irText/expressions/bangbang.fir.txt +++ b/compiler/testData/ir/irText/expressions/bangbang.fir.txt @@ -63,10 +63,10 @@ FILE fqName: fileName:/bangbang.kt BRANCH if: TYPE_OP type=kotlin.Boolean origin=INSTANCEOF typeOperand=kotlin.String? GET_VAR 'a: X of .test4 declared in .test4' type=X of .test4 origin=null - then: BLOCK type=kotlin.Unit origin=EXCLEXCL + then: BLOCK type=X of .test4 origin=EXCLEXCL VAR name: type:X of .test4 [val] GET_VAR 'a: X of .test4 declared in .test4' type=X of .test4 origin=null - WHEN type=kotlin.Unit origin=EXCLEXCL + WHEN type=X of .test4 origin=EXCLEXCL 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 : X of .test4 [val] declared in .test4' type=X of .test4 origin=null @@ -76,7 +76,7 @@ FILE fqName: fileName:/bangbang.kt BRANCH if: CONST Boolean type=kotlin.Boolean value=true then: GET_VAR 'val : X of .test4 [val] declared in .test4' type=X of .test4 origin=null - WHEN type=kotlin.Unit origin=IF + WHEN type=IrErrorType origin=IF BRANCH if: TYPE_OP type=kotlin.Boolean origin=INSTANCEOF typeOperand=kotlin.String? GET_VAR 'a: X of .test4 declared in .test4' type=X of .test4 origin=null