[FIR] Force resolving all declaration while resolving of body with implicit type
This commit is contained in:
+42
-25
@@ -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)
|
||||
}
|
||||
|
||||
@@ -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
|
||||
}
|
||||
}
|
||||
@@ -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|
|
||||
|
||||
}
|
||||
+5
@@ -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");
|
||||
|
||||
@@ -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
|
||||
|
||||
Reference in New Issue
Block a user