[FIR] Force resolving all declaration while resolving of body with implicit type

This commit is contained in:
Dmitriy Novozhilov
2019-08-21 13:31:50 +03:00
parent e374242adf
commit f1e56c4b3e
5 changed files with 181 additions and 28 deletions
@@ -41,9 +41,12 @@ import org.jetbrains.kotlin.utils.addIfNotNull
open class FirBodyResolveTransformer( open class FirBodyResolveTransformer(
final override val session: FirSession, final override val session: FirSession,
phase: FirResolvePhase, phase: FirResolvePhase,
val implicitTypeOnly: Boolean, implicitTypeOnly: Boolean,
val scopeSession: ScopeSession = ScopeSession() val scopeSession: ScopeSession = ScopeSession()
) : FirAbstractPhaseTransformer<Any?>(phase), BodyResolveComponents { ) : FirAbstractPhaseTransformer<Any?>(phase), BodyResolveComponents {
var implicitTypeOnly: Boolean = implicitTypeOnly
private set
final override val returnTypeCalculator: ReturnTypeCalculator = ReturnTypeCalculatorWithJump(session, scopeSession) final override val returnTypeCalculator: ReturnTypeCalculator = ReturnTypeCalculatorWithJump(session, scopeSession)
final override val labels: SetMultimap<Name, ConeKotlinType> = LinkedHashMultimap.create() final override val labels: SetMultimap<Name, ConeKotlinType> = LinkedHashMultimap.create()
final override val noExpectedType = FirImplicitTypeRefImpl(null) final override val noExpectedType = FirImplicitTypeRefImpl(null)
@@ -554,17 +557,19 @@ open class FirBodyResolveTransformer(
if ((returnTypeRef !is FirImplicitTypeRef) && implicitTypeOnly) { if ((returnTypeRef !is FirImplicitTypeRef) && implicitTypeOnly) {
return namedFunction.compose() return namedFunction.compose()
} }
if (returnTypeRef is FirImplicitTypeRef) { return withFullBodyResolve {
namedFunction.transformReturnTypeRef(StoreType, FirComputingImplicitTypeRef) if (returnTypeRef is FirImplicitTypeRef) {
} namedFunction.transformReturnTypeRef(StoreType, FirComputingImplicitTypeRef)
}
val receiverTypeRef = namedFunction.receiverTypeRef
return if (receiverTypeRef != null) { val receiverTypeRef = namedFunction.receiverTypeRef
withLabelAndReceiverType(namedFunction.name, namedFunction, receiverTypeRef.coneTypeUnsafe()) { if (receiverTypeRef != null) {
transformFunctionWithGivenSignature(namedFunction, returnTypeRef, receiverTypeRef) 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) { if (returnTypeRef is FirImplicitTypeRef) {
property.transformReturnTypeRef(StoreType, FirComputingImplicitTypeRef) property.transformReturnTypeRef(StoreType, FirComputingImplicitTypeRef)
} }
return withScopeCleanup(localScopes) { return withFullBodyResolve {
localScopes.addIfNotNull(primaryConstructorParametersScope) withScopeCleanup(localScopes) {
withContainer(property) { localScopes.addIfNotNull(primaryConstructorParametersScope)
property.transformChildrenWithoutAccessors(this, returnTypeRef) withContainer(property) {
if (property.initializer != null) { property.transformChildrenWithoutAccessors(this, returnTypeRef)
storeVariableReturnType(property) if (property.initializer != null) {
} storeVariableReturnType(property)
withScopeCleanup(localScopes) { }
localScopes.add(FirLocalScope().apply { withScopeCleanup(localScopes) {
storeBackingField(property) localScopes.add(FirLocalScope().apply {
}) storeBackingField(property)
property.transformAccessors() })
property.transformAccessors()
}
} }
property.resolvePhase = transformerPhase
property.compose()
} }
property.resolvePhase = transformerPhase
property.compose()
} }
} }
@@ -777,6 +784,16 @@ open class FirBodyResolveTransformer(
} }
} }
private inline fun <T> withFullBodyResolve(crossinline l: () -> T): T {
if (!implicitTypeOnly) return l()
implicitTypeOnly = false
return try {
l()
} finally {
implicitTypeOnly = true
}
}
internal fun <T> storeTypeFromCallee(access: T) where T : FirQualifiedAccess, T : FirExpression { internal fun <T> storeTypeFromCallee(access: T) where T : FirQualifiedAccess, T : FirExpression {
access.resultType = callCompleter.typeFromCallee(access) access.resultType = callCompleter.typeFromCallee(access)
} }
+47
View File
@@ -0,0 +1,47 @@
fun <T> 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
}
}
+84
View File
@@ -0,0 +1,84 @@
FILE: localObject.kt
public final fun <T> run(block: R|kotlin/Function0<T>|): R|T| {
^run R|<local>/block|.R|FakeOverride<kotlin/Function0.invoke: R|T|>|()
}
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|<R|kotlin/Int|>(<L> = run@fun <anonymous>(): R|kotlin/Int| {
lval obj: R|Foo| = object : R|Foo| {
private constructor(): R|kotlin/Any| {
super<R|kotlin/Any|>()
}
public final override fun foo(): R|kotlin/Int| {
^foo R|<local>/x|.R|kotlin/Int.plus|(Int(1))
}
}
Int(2)
}
)
}
public final class TestProperty : R|kotlin/Any| {
public constructor(): R|TestProperty| {
super<R|kotlin/Any|>()
}
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<R|kotlin/Any|>()
}
public final override fun foo(): R|kotlin/Int| {
^foo R|/TestProperty.intConst|.R|kotlin/Int.plus|(Int(1))
}
}
F|/TestProperty.x| = R|<local>/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<R|kotlin/Any|>()
}
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|<R|kotlin/Int|>(<L> = run@fun <anonymous>(): R|kotlin/Int| {
lval obj: R|Foo| = object : R|Foo| {
private constructor(): R|kotlin/Any| {
super<R|kotlin/Any|>()
}
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|
}
@@ -99,6 +99,11 @@ public class FirResolveTestCaseGenerated extends AbstractFirResolveTestCase {
runTest("compiler/fir/resolve/testData/resolve/intersectionTypes.kt"); 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") @TestMetadata("nestedClass.kt")
public void testNestedClass() throws Exception { public void testNestedClass() throws Exception {
runTest("compiler/fir/resolve/testData/resolve/nestedClass.kt"); runTest("compiler/fir/resolve/testData/resolve/nestedClass.kt");
+3 -3
View File
@@ -63,10 +63,10 @@ FILE fqName:<root> fileName:/bangbang.kt
BRANCH BRANCH
if: TYPE_OP type=kotlin.Boolean origin=INSTANCEOF typeOperand=kotlin.String? if: TYPE_OP type=kotlin.Boolean origin=INSTANCEOF typeOperand=kotlin.String?
GET_VAR 'a: X of <root>.test4 declared in <root>.test4' type=X of <root>.test4 origin=null GET_VAR 'a: X of <root>.test4 declared in <root>.test4' type=X of <root>.test4 origin=null
then: BLOCK type=kotlin.Unit origin=EXCLEXCL then: BLOCK type=X of <root>.test4 origin=EXCLEXCL
VAR name:<bangbang> type:X of <root>.test4 [val] VAR name:<bangbang> type:X of <root>.test4 [val]
GET_VAR 'a: X of <root>.test4 declared in <root>.test4' type=X of <root>.test4 origin=null GET_VAR 'a: X of <root>.test4 declared in <root>.test4' type=X of <root>.test4 origin=null
WHEN type=kotlin.Unit origin=EXCLEXCL WHEN type=X of <root>.test4 origin=EXCLEXCL
BRANCH 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 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 <bangbang>: X of <root>.test4 [val] declared in <root>.test4' type=X of <root>.test4 origin=null arg0: GET_VAR 'val <bangbang>: X of <root>.test4 [val] declared in <root>.test4' type=X of <root>.test4 origin=null
@@ -76,7 +76,7 @@ FILE fqName:<root> fileName:/bangbang.kt
BRANCH BRANCH
if: CONST Boolean type=kotlin.Boolean value=true if: CONST Boolean type=kotlin.Boolean value=true
then: GET_VAR 'val <bangbang>: X of <root>.test4 [val] declared in <root>.test4' type=X of <root>.test4 origin=null then: GET_VAR 'val <bangbang>: X of <root>.test4 [val] declared in <root>.test4' type=X of <root>.test4 origin=null
WHEN type=kotlin.Unit origin=IF WHEN type=IrErrorType origin=IF
BRANCH BRANCH
if: TYPE_OP type=kotlin.Boolean origin=INSTANCEOF typeOperand=kotlin.String? if: TYPE_OP type=kotlin.Boolean origin=INSTANCEOF typeOperand=kotlin.String?
GET_VAR 'a: X of <root>.test4 declared in <root>.test4' type=X of <root>.test4 origin=null GET_VAR 'a: X of <root>.test4 declared in <root>.test4' type=X of <root>.test4 origin=null