[LL FIR] add guards to type resolver
We should protect return types from value parameters/property accessors and backing fields from repeatable modifications. Such declarations can be modified during type resolution by `transformTypeToArrayType` or property getter type propagation, so we should be able to restore the original reference in the case of exceptions (PCE for instance) ^KT-61422
This commit is contained in:
+46
-5
@@ -103,6 +103,31 @@ private class LLFirTypeTargetResolver(
|
|||||||
}
|
}
|
||||||
|
|
||||||
override fun doLazyResolveUnderLock(target: FirElementWithResolveState) {
|
override fun doLazyResolveUnderLock(target: FirElementWithResolveState) {
|
||||||
|
when (target) {
|
||||||
|
is FirFunction -> resolve(target, TypeStateKeepers.FUNCTION)
|
||||||
|
is FirProperty -> resolve(target, TypeStateKeepers.PROPERTY)
|
||||||
|
is FirCallableDeclaration,
|
||||||
|
is FirDanglingModifierList,
|
||||||
|
is FirFileAnnotationsContainer,
|
||||||
|
is FirTypeAlias,
|
||||||
|
is FirScript,
|
||||||
|
is FirRegularClass,
|
||||||
|
-> rawResolve(target)
|
||||||
|
|
||||||
|
is FirFile, is FirAnonymousInitializer, is FirCodeFragment -> {}
|
||||||
|
else -> errorWithAttachment("Unknown declaration ${target::class.simpleName}") {
|
||||||
|
withFirEntry("declaration", target)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun <T : FirElementWithResolveState> resolve(target: T, keeper: StateKeeper<T, Unit>) {
|
||||||
|
resolveWithKeeper(target, Unit, keeper) {
|
||||||
|
rawResolve(target)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun rawResolve(target: FirElementWithResolveState) {
|
||||||
when (target) {
|
when (target) {
|
||||||
is FirConstructor -> {
|
is FirConstructor -> {
|
||||||
// ConstructedTypeRef should be resolved only with type parameters, but not with nested classes and classes from supertypes
|
// ConstructedTypeRef should be resolved only with type parameters, but not with nested classes and classes from supertypes
|
||||||
@@ -128,11 +153,9 @@ private class LLFirTypeTargetResolver(
|
|||||||
is FirDanglingModifierList, is FirFileAnnotationsContainer, is FirCallableDeclaration, is FirTypeAlias -> {
|
is FirDanglingModifierList, is FirFileAnnotationsContainer, is FirCallableDeclaration, is FirTypeAlias -> {
|
||||||
target.accept(transformer, null)
|
target.accept(transformer, null)
|
||||||
}
|
}
|
||||||
is FirRegularClass -> {
|
|
||||||
resolveClassTypes(target)
|
is FirRegularClass -> resolveClassTypes(target)
|
||||||
}
|
else -> errorWithAttachment("Unknown declaration ${target::class.simpleName}") {
|
||||||
is FirFile, is FirAnonymousInitializer, is FirCodeFragment -> {}
|
|
||||||
else -> errorWithAttachment("Unknown declaration ${target::class}") {
|
|
||||||
withFirEntry("declaration", target)
|
withFirEntry("declaration", target)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -157,3 +180,21 @@ private class LLFirTypeTargetResolver(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private object TypeStateKeepers {
|
||||||
|
val FUNCTION: StateKeeper<FirFunction, Unit> = stateKeeper { function, context ->
|
||||||
|
add(CALLABLE_DECLARATION, context)
|
||||||
|
entityList(function.valueParameters, CALLABLE_DECLARATION, context)
|
||||||
|
}
|
||||||
|
|
||||||
|
val PROPERTY: StateKeeper<FirProperty, Unit> = stateKeeper { property, context ->
|
||||||
|
add(CALLABLE_DECLARATION, context)
|
||||||
|
entity(property.getter, FUNCTION, context)
|
||||||
|
entity(property.setter, FUNCTION, context)
|
||||||
|
entity(property.backingField, CALLABLE_DECLARATION, context)
|
||||||
|
}
|
||||||
|
|
||||||
|
private val CALLABLE_DECLARATION: StateKeeper<FirCallableDeclaration, Unit> = stateKeeper { _, _ ->
|
||||||
|
add(FirCallableDeclaration::returnTypeRef, FirCallableDeclaration::replaceReturnTypeRef)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user