[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(
final override val session: FirSession,
phase: FirResolvePhase,
val implicitTypeOnly: Boolean,
implicitTypeOnly: Boolean,
val scopeSession: ScopeSession = ScopeSession()
) : FirAbstractPhaseTransformer<Any?>(phase), BodyResolveComponents {
var implicitTypeOnly: Boolean = implicitTypeOnly
private set
final override val returnTypeCalculator: ReturnTypeCalculator = ReturnTypeCalculatorWithJump(session, scopeSession)
final override val labels: SetMultimap<Name, ConeKotlinType> = 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 <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 {
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");
}
@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");
+3 -3
View File
@@ -63,10 +63,10 @@ FILE fqName:<root> fileName:/bangbang.kt
BRANCH
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
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]
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
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
@@ -76,7 +76,7 @@ FILE fqName:<root> fileName:/bangbang.kt
BRANCH
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
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 <root>.test4 declared in <root>.test4' type=X of <root>.test4 origin=null