[FIR] Report missing TYPECHECKER_HAS_RUN_INTO_RECURSIVE_PROBLEM for local functions

^KT-59376
^KT-55221 Fixed
This commit is contained in:
Ivan Kochurkin
2023-07-12 15:29:55 +02:00
committed by Space Team
parent d9736ec88c
commit dac8688a29
16 changed files with 41 additions and 34 deletions
@@ -5,10 +5,9 @@
package org.jetbrains.kotlin.fir.analysis.collectors package org.jetbrains.kotlin.fir.analysis.collectors
import org.jetbrains.kotlin.diagnostics.DiagnosticReporter
import org.jetbrains.kotlin.fir.FirSession import org.jetbrains.kotlin.fir.FirSession
import org.jetbrains.kotlin.fir.analysis.checkers.context.MutableCheckerContext import org.jetbrains.kotlin.fir.analysis.checkers.context.MutableCheckerContext
import org.jetbrains.kotlin.fir.analysis.collectors.components.AbstractDiagnosticCollectorComponent
import org.jetbrains.kotlin.diagnostics.DiagnosticReporter
import org.jetbrains.kotlin.fir.resolve.ScopeSession import org.jetbrains.kotlin.fir.resolve.ScopeSession
import org.jetbrains.kotlin.fir.resolve.transformers.ReturnTypeCalculatorForFullBodyResolve import org.jetbrains.kotlin.fir.resolve.transformers.ReturnTypeCalculatorForFullBodyResolve
@@ -21,7 +20,7 @@ class SimpleDiagnosticsCollector(
return CheckerRunningDiagnosticCollectorVisitor( return CheckerRunningDiagnosticCollectorVisitor(
MutableCheckerContext( MutableCheckerContext(
this, this,
ReturnTypeCalculatorForFullBodyResolve ReturnTypeCalculatorForFullBodyResolve.Default
), ),
components components
) )
@@ -567,7 +567,7 @@ internal class AdapterGenerator(
} }
// On the other hand, the actual type should be either a functional type or a subtype of a class that has a contributed `invoke`. // On the other hand, the actual type should be either a functional type or a subtype of a class that has a contributed `invoke`.
val expectedFunctionType = getFunctionTypeForPossibleSamType(parameter.returnTypeRef.coneType) val expectedFunctionType = getFunctionTypeForPossibleSamType(parameter.returnTypeRef.coneType)
return argument.isFunctional(session, scopeSession, expectedFunctionType, ReturnTypeCalculatorForFullBodyResolve) return argument.isFunctional(session, scopeSession, expectedFunctionType, ReturnTypeCalculatorForFullBodyResolve.Default)
} }
internal fun getFunctionTypeForPossibleSamType(parameterType: ConeKotlinType): ConeKotlinType? { internal fun getFunctionTypeForPossibleSamType(parameterType: ConeKotlinType): ConeKotlinType? {
@@ -13,7 +13,23 @@ import org.jetbrains.kotlin.fir.scopes.FakeOverrideTypeCalculator
import org.jetbrains.kotlin.fir.types.FirResolvedTypeRef import org.jetbrains.kotlin.fir.types.FirResolvedTypeRef
import org.jetbrains.kotlin.fir.types.builder.buildErrorTypeRef import org.jetbrains.kotlin.fir.types.builder.buildErrorTypeRef
object ReturnTypeCalculatorForFullBodyResolve : ReturnTypeCalculator() { class ReturnTypeCalculatorForFullBodyResolve private constructor(
private val diagnosticKind: DiagnosticKind,
private val reason: String,
) : ReturnTypeCalculator() {
companion object {
// It's actual only for local functions because simple members are being resolved at another phase.
// Local properties are just unresolved if they are used recursively.
val Default = ReturnTypeCalculatorForFullBodyResolve(
DiagnosticKind.RecursionInImplicitTypes,
"Recursion with local function"
)
val Contract = ReturnTypeCalculatorForFullBodyResolve(
DiagnosticKind.InferenceError,
"Cannot calculate return type during full-body resolution (local class/object?)"
)
}
override val fakeOverrideTypeCalculator: FakeOverrideTypeCalculator override val fakeOverrideTypeCalculator: FakeOverrideTypeCalculator
get() = FakeOverrideTypeCalculator.Forced get() = FakeOverrideTypeCalculator.Forced
@@ -24,11 +40,6 @@ object ReturnTypeCalculatorForFullBodyResolve : ReturnTypeCalculator() {
return FakeOverrideTypeCalculator.Forced.computeReturnType(declaration) return FakeOverrideTypeCalculator.Forced.computeReturnType(declaration)
} }
return buildErrorTypeRef { return buildErrorTypeRef { diagnostic = ConeSimpleDiagnostic("$reason: ${declaration.render()}", diagnosticKind) }
diagnostic = ConeSimpleDiagnostic(
"Cannot calculate return type during full-body resolution (local class/object?): ${declaration.render()}",
DiagnosticKind.InferenceError
)
}
} }
} }
@@ -154,7 +154,7 @@ class FirTypeIntersectionScopeContext(
overrideService.extractBothWaysOverridable(allMembersWithScope.maxByVisibility(), allMembersWithScope, overrideChecker) overrideService.extractBothWaysOverridable(allMembersWithScope.maxByVisibility(), allMembersWithScope, overrideChecker)
val group = groupWithPrivate.filter { !Visibilities.isPrivate(it.member.fir.visibility) }.ifEmpty { groupWithPrivate } val group = groupWithPrivate.filter { !Visibilities.isPrivate(it.member.fir.visibility) }.ifEmpty { groupWithPrivate }
val nonSubsumed = if (forClassUseSiteScope) group.nonSubsumed() else group val nonSubsumed = if (forClassUseSiteScope) group.nonSubsumed() else group
val mostSpecific = overrideService.selectMostSpecificMembers(nonSubsumed, ReturnTypeCalculatorForFullBodyResolve) val mostSpecific = overrideService.selectMostSpecificMembers(nonSubsumed, ReturnTypeCalculatorForFullBodyResolve.Default)
val nonTrivial = if (forClassUseSiteScope) { val nonTrivial = if (forClassUseSiteScope) {
// Create a non-trivial intersection override when the base methods come from different scopes, // Create a non-trivial intersection override when the base methods come from different scopes,
// even if one of them is more specific than the others, i.e. when there is more than one method that is not subsumed. // even if one of them is more specific than the others, i.e. when there is more than one method that is not subsumed.
@@ -24,7 +24,7 @@ abstract class FirAbstractBodyResolveTransformerDispatcher(
phase: FirResolvePhase, phase: FirResolvePhase,
override var implicitTypeOnly: Boolean, override var implicitTypeOnly: Boolean,
scopeSession: ScopeSession, scopeSession: ScopeSession,
val returnTypeCalculator: ReturnTypeCalculator = ReturnTypeCalculatorForFullBodyResolve, val returnTypeCalculator: ReturnTypeCalculator = ReturnTypeCalculatorForFullBodyResolve.Default,
outerBodyResolveContext: BodyResolveContext? = null, outerBodyResolveContext: BodyResolveContext? = null,
val firResolveContextCollector: FirResolveContextCollector? = null, val firResolveContextCollector: FirResolveContextCollector? = null,
) : FirAbstractBodyResolveTransformer(phase) { ) : FirAbstractBodyResolveTransformer(phase) {
@@ -6,7 +6,7 @@
package org.jetbrains.kotlin.fir.resolve.transformers.body.resolve package org.jetbrains.kotlin.fir.resolve.transformers.body.resolve
import org.jetbrains.kotlin.fir.FirSession import org.jetbrains.kotlin.fir.FirSession
import org.jetbrains.kotlin.fir.declarations.* import org.jetbrains.kotlin.fir.declarations.FirResolvePhase
import org.jetbrains.kotlin.fir.resolve.ScopeSession import org.jetbrains.kotlin.fir.resolve.ScopeSession
import org.jetbrains.kotlin.fir.resolve.transformers.ReturnTypeCalculator import org.jetbrains.kotlin.fir.resolve.transformers.ReturnTypeCalculator
import org.jetbrains.kotlin.fir.resolve.transformers.ReturnTypeCalculatorForFullBodyResolve import org.jetbrains.kotlin.fir.resolve.transformers.ReturnTypeCalculatorForFullBodyResolve
@@ -16,7 +16,7 @@ open class FirBodyResolveTransformer(
phase: FirResolvePhase, phase: FirResolvePhase,
implicitTypeOnly: Boolean, implicitTypeOnly: Boolean,
scopeSession: ScopeSession, scopeSession: ScopeSession,
returnTypeCalculator: ReturnTypeCalculator = ReturnTypeCalculatorForFullBodyResolve, returnTypeCalculator: ReturnTypeCalculator = ReturnTypeCalculatorForFullBodyResolve.Default,
outerBodyResolveContext: BodyResolveContext? = null, outerBodyResolveContext: BodyResolveContext? = null,
firResolveContextCollector: FirResolveContextCollector? = null firResolveContextCollector: FirResolveContextCollector? = null
) : FirAbstractBodyResolveTransformerDispatcher( ) : FirAbstractBodyResolveTransformerDispatcher(
@@ -24,7 +24,6 @@ import org.jetbrains.kotlin.fir.resolve.transformers.ReturnTypeCalculatorForFull
import org.jetbrains.kotlin.fir.resolve.transformers.contracts.runContractResolveForLocalClass import org.jetbrains.kotlin.fir.resolve.transformers.contracts.runContractResolveForLocalClass
import org.jetbrains.kotlin.fir.scopes.FakeOverrideTypeCalculator import org.jetbrains.kotlin.fir.scopes.FakeOverrideTypeCalculator
import org.jetbrains.kotlin.fir.scopes.fakeOverrideSubstitution import org.jetbrains.kotlin.fir.scopes.fakeOverrideSubstitution
import org.jetbrains.kotlin.fir.delegatedWrapperData
import org.jetbrains.kotlin.fir.scopes.impl.originalForWrappedIntegerOperator import org.jetbrains.kotlin.fir.scopes.impl.originalForWrappedIntegerOperator
import org.jetbrains.kotlin.fir.symbols.impl.FirCallableSymbol import org.jetbrains.kotlin.fir.symbols.impl.FirCallableSymbol
import org.jetbrains.kotlin.fir.symbols.impl.FirSyntheticPropertySymbol import org.jetbrains.kotlin.fir.symbols.impl.FirSyntheticPropertySymbol
@@ -193,7 +192,7 @@ open class ReturnTypeCalculatorWithJump(
override fun tryCalculateReturnTypeOrNull(declaration: FirCallableDeclaration): FirResolvedTypeRef { override fun tryCalculateReturnTypeOrNull(declaration: FirCallableDeclaration): FirResolvedTypeRef {
// Local declarations must be handled by `ReturnTypeCalculatorForFullBodyResolve` to avoid resolution cycles in LL FIR. // Local declarations must be handled by `ReturnTypeCalculatorForFullBodyResolve` to avoid resolution cycles in LL FIR.
if (declaration.visibility == Visibilities.Local) { if (declaration.visibility == Visibilities.Local) {
return ReturnTypeCalculatorForFullBodyResolve.tryCalculateReturnType(declaration) return ReturnTypeCalculatorForFullBodyResolve.Default.tryCalculateReturnType(declaration)
} }
if (declaration is FirValueParameter && declaration.returnTypeRef is FirImplicitTypeRef) { if (declaration is FirValueParameter && declaration.returnTypeRef is FirImplicitTypeRef) {
@@ -25,6 +25,7 @@ import org.jetbrains.kotlin.fir.moduleData
import org.jetbrains.kotlin.fir.references.builder.buildSimpleNamedReference import org.jetbrains.kotlin.fir.references.builder.buildSimpleNamedReference
import org.jetbrains.kotlin.fir.resolve.ResolutionMode import org.jetbrains.kotlin.fir.resolve.ResolutionMode
import org.jetbrains.kotlin.fir.resolve.ScopeSession import org.jetbrains.kotlin.fir.resolve.ScopeSession
import org.jetbrains.kotlin.fir.resolve.transformers.ReturnTypeCalculatorForFullBodyResolve
import org.jetbrains.kotlin.fir.resolve.transformers.body.resolve.BodyResolveContext import org.jetbrains.kotlin.fir.resolve.transformers.body.resolve.BodyResolveContext
import org.jetbrains.kotlin.fir.resolve.transformers.body.resolve.FirAbstractBodyResolveTransformerDispatcher import org.jetbrains.kotlin.fir.resolve.transformers.body.resolve.FirAbstractBodyResolveTransformerDispatcher
import org.jetbrains.kotlin.fir.resolve.transformers.body.resolve.FirDeclarationsResolveTransformer import org.jetbrains.kotlin.fir.resolve.transformers.body.resolve.FirDeclarationsResolveTransformer
@@ -45,6 +46,7 @@ abstract class FirAbstractContractResolveTransformerDispatcher(
FirResolvePhase.CONTRACTS, FirResolvePhase.CONTRACTS,
implicitTypeOnly = false, implicitTypeOnly = false,
scopeSession, scopeSession,
returnTypeCalculator = ReturnTypeCalculatorForFullBodyResolve.Contract,
outerBodyResolveContext = outerBodyResolveContext outerBodyResolveContext = outerBodyResolveContext
) { ) {
final override val expressionsTransformer: FirExpressionsResolveTransformer = final override val expressionsTransformer: FirExpressionsResolveTransformer =
@@ -49,7 +49,7 @@ fun <F : FirClassLikeDeclaration> F.runContractResolveForLocalClass(
targetedClasses: Set<FirClassLikeDeclaration> targetedClasses: Set<FirClassLikeDeclaration>
): F { ): F {
val newContext = outerBodyResolveContext.createSnapshotForLocalClasses( val newContext = outerBodyResolveContext.createSnapshotForLocalClasses(
ReturnTypeCalculatorForFullBodyResolve, ReturnTypeCalculatorForFullBodyResolve.Contract,
targetedClasses targetedClasses
) )
val transformer = FirContractResolveTransformer(session, scopeSession, newContext) val transformer = FirContractResolveTransformer(session, scopeSession, newContext)
@@ -15,11 +15,7 @@ import org.jetbrains.kotlin.fir.resolve.ResolutionMode
import org.jetbrains.kotlin.fir.resolve.ScopeSession import org.jetbrains.kotlin.fir.resolve.ScopeSession
import org.jetbrains.kotlin.fir.resolve.transformers.ReturnTypeCalculator import org.jetbrains.kotlin.fir.resolve.transformers.ReturnTypeCalculator
import org.jetbrains.kotlin.fir.resolve.transformers.ReturnTypeCalculatorForFullBodyResolve import org.jetbrains.kotlin.fir.resolve.transformers.ReturnTypeCalculatorForFullBodyResolve
import org.jetbrains.kotlin.fir.resolve.transformers.body.resolve.BodyResolveContext import org.jetbrains.kotlin.fir.resolve.transformers.body.resolve.*
import org.jetbrains.kotlin.fir.resolve.transformers.body.resolve.FirAbstractBodyResolveTransformerDispatcher
import org.jetbrains.kotlin.fir.resolve.transformers.body.resolve.FirDeclarationsResolveTransformer
import org.jetbrains.kotlin.fir.resolve.transformers.body.resolve.FirExpressionsResolveTransformer
import org.jetbrains.kotlin.fir.resolve.transformers.body.resolve.FirResolveContextCollector
import org.jetbrains.kotlin.fir.visitors.transformSingle import org.jetbrains.kotlin.fir.visitors.transformSingle
open class FirAnnotationArgumentsMappingTransformer( open class FirAnnotationArgumentsMappingTransformer(
@@ -27,7 +23,7 @@ open class FirAnnotationArgumentsMappingTransformer(
scopeSession: ScopeSession, scopeSession: ScopeSession,
resolvePhase: FirResolvePhase, resolvePhase: FirResolvePhase,
outerBodyResolveContext: BodyResolveContext? = null, outerBodyResolveContext: BodyResolveContext? = null,
returnTypeCalculator: ReturnTypeCalculator = ReturnTypeCalculatorForFullBodyResolve, returnTypeCalculator: ReturnTypeCalculator = ReturnTypeCalculatorForFullBodyResolve.Default,
firResolveContextCollector: FirResolveContextCollector? = null, firResolveContextCollector: FirResolveContextCollector? = null,
) : FirAbstractBodyResolveTransformerDispatcher( ) : FirAbstractBodyResolveTransformerDispatcher(
session, session,
@@ -34,7 +34,7 @@ open class FirAnnotationArgumentsResolveTransformer(
scopeSession: ScopeSession, scopeSession: ScopeSession,
resolvePhase: FirResolvePhase, resolvePhase: FirResolvePhase,
outerBodyResolveContext: BodyResolveContext? = null, outerBodyResolveContext: BodyResolveContext? = null,
returnTypeCalculator: ReturnTypeCalculator = ReturnTypeCalculatorForFullBodyResolve, returnTypeCalculator: ReturnTypeCalculator = ReturnTypeCalculatorForFullBodyResolve.Default,
firResolveContextCollector: FirResolveContextCollector? = null, firResolveContextCollector: FirResolveContextCollector? = null,
) : FirAbstractBodyResolveTransformerDispatcher( ) : FirAbstractBodyResolveTransformerDispatcher(
session, session,
@@ -2,7 +2,7 @@
fun foo() { fun foo() {
fun fact(n: Int) = { fun fact(n: Int) = {
if (n > 0) { if (n > 0) {
fact(n - 1) <!UNRESOLVED_REFERENCE!>*<!> n <!TYPECHECKER_HAS_RUN_INTO_RECURSIVE_PROBLEM!>fact(n - 1)<!> <!UNRESOLVED_REFERENCE!>*<!> n
} }
else { else {
1 1
@@ -1,3 +1,3 @@
fun foo() { fun foo() {
fun bar() = (fun() = bar()) fun bar() = (fun() = <!TYPECHECKER_HAS_RUN_INTO_RECURSIVE_PROBLEM!>bar()<!>)
} }
@@ -1,5 +1,5 @@
fun foo() { fun foo() {
fun bar() = { fun bar() = {
bar() <!TYPECHECKER_HAS_RUN_INTO_RECURSIVE_PROBLEM, TYPECHECKER_HAS_RUN_INTO_RECURSIVE_PROBLEM!>bar()<!>
} }
} }
@@ -1,8 +1,8 @@
fun foo() { fun foo() {
fun bar1() = bar1() fun bar1() = <!TYPECHECKER_HAS_RUN_INTO_RECURSIVE_PROBLEM!>bar1()<!>
fun bar2() = 1 <!OVERLOAD_RESOLUTION_AMBIGUITY!>+<!> bar2() fun bar2() = 1 <!OVERLOAD_RESOLUTION_AMBIGUITY!>+<!> <!TYPECHECKER_HAS_RUN_INTO_RECURSIVE_PROBLEM!>bar2()<!>
fun bar3() = id(bar3()) fun bar3() = id(<!TYPECHECKER_HAS_RUN_INTO_RECURSIVE_PROBLEM!>bar3()<!>)
} }
fun <T> id(x: T) = x fun <T> id(x: T) = x
@@ -3,7 +3,7 @@ fun main(args: Array<String>) {
fun f() = run { fun f() = run {
<!WRONG_MODIFIER_TARGET!>private<!> class C { <!WRONG_MODIFIER_TARGET!>private<!> class C {
private fun foo() { private fun foo() {
f().<!UNRESOLVED_REFERENCE!>foo<!>(); <!TYPECHECKER_HAS_RUN_INTO_RECURSIVE_PROBLEM!>f()<!>.<!UNRESOLVED_REFERENCE!>foo<!>();
} }
} }