[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(
|
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)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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");
|
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");
|
||||||
|
|||||||
@@ -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
|
||||||
|
|||||||
Reference in New Issue
Block a user