diff --git a/analysis/analysis-api-fir/src/org/jetbrains/kotlin/analysis/api/fir/components/KtFirCallResolver.kt b/analysis/analysis-api-fir/src/org/jetbrains/kotlin/analysis/api/fir/components/KtFirCallResolver.kt index 170aea352fd..81826a17820 100644 --- a/analysis/analysis-api-fir/src/org/jetbrains/kotlin/analysis/api/fir/components/KtFirCallResolver.kt +++ b/analysis/analysis-api-fir/src/org/jetbrains/kotlin/analysis/api/fir/components/KtFirCallResolver.kt @@ -44,10 +44,7 @@ import org.jetbrains.kotlin.fir.expressions.builder.buildFunctionCall import org.jetbrains.kotlin.fir.expressions.impl.FirNoReceiverExpression import org.jetbrains.kotlin.fir.psi import org.jetbrains.kotlin.fir.realPsi -import org.jetbrains.kotlin.fir.references.FirErrorNamedReference -import org.jetbrains.kotlin.fir.references.FirNamedReference -import org.jetbrains.kotlin.fir.references.FirResolvedNamedReference -import org.jetbrains.kotlin.fir.references.FirSuperReference +import org.jetbrains.kotlin.fir.references.* import org.jetbrains.kotlin.fir.resolve.calls.AbstractCandidate import org.jetbrains.kotlin.fir.resolve.calls.Candidate import org.jetbrains.kotlin.fir.resolve.createConeDiagnosticForCandidateWithError @@ -176,9 +173,29 @@ internal class KtFirCallResolver( resolveFragmentOfCall = resolveFragmentOfCall ) } + + fun transformErrorReference(call: FirResolvable, calleeReference: T): KtCallInfo where T : FirNamedReference, T : FirDiagnosticHolder { + val diagnostic = calleeReference.diagnostic + val ktDiagnostic = calleeReference.createKtDiagnostic(psi) + + if (diagnostic is ConeHiddenCandidateError) + return KtErrorCallInfo(emptyList(), ktDiagnostic, token) + + val candidateCalls = mutableListOf() + if (diagnostic is ConeDiagnosticWithCandidates) { + diagnostic.candidates.mapNotNullTo(candidateCalls) { + createKtCall(psi, call, it, resolveFragmentOfCall) + } + } else { + candidateCalls.addIfNotNull(createKtCall(psi, call, null, resolveFragmentOfCall)) + } + return KtErrorCallInfo(candidateCalls, ktDiagnostic, token) + } + return when (this) { is FirResolvable -> { when (val calleeReference = calleeReference) { + is FirResolvedErrorReference -> transformErrorReference(this, calleeReference) is FirResolvedNamedReference -> when (calleeReference.resolvedSymbol) { // `calleeReference.resolvedSymbol` isn't guaranteed to be callable. For example, function type parameters used in // expression positions (e.g. `T` in `println(T)`) are parsed as `KtSimpleNameExpression` and built into @@ -194,23 +211,7 @@ internal class KtFirCallResolver( } else -> null } - is FirErrorNamedReference -> { - val diagnostic = calleeReference.diagnostic - val ktDiagnostic = calleeReference.createKtDiagnostic(psi) - - if (diagnostic is ConeHiddenCandidateError) - return KtErrorCallInfo(emptyList(), ktDiagnostic, token) - - val candidateCalls = mutableListOf() - if (diagnostic is ConeDiagnosticWithCandidates) { - diagnostic.candidates.mapNotNullTo(candidateCalls) { - createKtCall(psi, this@toKtCallInfo, it, resolveFragmentOfCall) - } - } else { - candidateCalls.addIfNotNull(createKtCall(psi, this, null, resolveFragmentOfCall)) - } - KtErrorCallInfo(candidateCalls, ktDiagnostic, token) - } + is FirErrorNamedReference -> transformErrorReference(this, calleeReference) // Unresolved delegated constructor call is untransformed and end up as an `FirSuperReference` is FirSuperReference -> { val delegatedConstructorCall = this as? FirDelegatedConstructorCall ?: return null diff --git a/compiler/fir/checkers/checkers.native/src/org/jetbrains/kotlin/fir/analysis/native/checkers/FirNativeThrowsChecker.kt b/compiler/fir/checkers/checkers.native/src/org/jetbrains/kotlin/fir/analysis/native/checkers/FirNativeThrowsChecker.kt index b7792358ba3..d422f366976 100644 --- a/compiler/fir/checkers/checkers.native/src/org/jetbrains/kotlin/fir/analysis/native/checkers/FirNativeThrowsChecker.kt +++ b/compiler/fir/checkers/checkers.native/src/org/jetbrains/kotlin/fir/analysis/native/checkers/FirNativeThrowsChecker.kt @@ -17,6 +17,7 @@ import org.jetbrains.kotlin.fir.analysis.diagnostics.native.FirNativeErrors import org.jetbrains.kotlin.fir.declarations.* import org.jetbrains.kotlin.fir.expressions.* import org.jetbrains.kotlin.fir.references.FirErrorNamedReference +import org.jetbrains.kotlin.fir.references.FirResolvedErrorReference import org.jetbrains.kotlin.fir.resolve.fullyExpandedType import org.jetbrains.kotlin.fir.resolve.toFirRegularClassSymbol import org.jetbrains.kotlin.fir.scopes.getDirectOverriddenFunctions @@ -142,8 +143,8 @@ object FirNativeThrowsChecker : FirBasicDeclarationChecker() { } if (this is FirResolvable) { - if (this.calleeReference is FirErrorNamedReference) { - return true + when (this.calleeReference) { + is FirErrorNamedReference, is FirResolvedErrorReference -> return true } } diff --git a/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/checkers/FirConstChecks.kt b/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/checkers/FirConstChecks.kt index 58cdc761502..f1959f779bd 100644 --- a/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/checkers/FirConstChecks.kt +++ b/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/checkers/FirConstChecks.kt @@ -14,6 +14,7 @@ import org.jetbrains.kotlin.fir.declarations.utils.modality import org.jetbrains.kotlin.fir.expressions.* import org.jetbrains.kotlin.fir.expressions.impl.FirNoReceiverExpression import org.jetbrains.kotlin.fir.references.FirErrorNamedReference +import org.jetbrains.kotlin.fir.references.FirResolvedErrorReference import org.jetbrains.kotlin.fir.references.FirResolvedNamedReference import org.jetbrains.kotlin.fir.resolve.toSymbol import org.jetbrains.kotlin.fir.symbols.FirBasedSymbol @@ -29,7 +30,9 @@ internal fun checkConstantArguments( expression: FirExpression, session: FirSession, ): ConstantArgumentKind? { - val expressionSymbol = expression.toResolvedCallableSymbol() + val expressionSymbol = expression.toResolvedCallableReference() + ?.takeUnless { it is FirResolvedErrorReference } + ?.resolvedSymbol as? FirCallableSymbol<*> val classKindOfParent = (expressionSymbol?.getReferencedClassSymbol(session) as? FirRegularClassSymbol) ?.classKind diff --git a/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/checkers/declaration/FirCommonConstructorDelegationIssuesChecker.kt b/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/checkers/declaration/FirCommonConstructorDelegationIssuesChecker.kt index 2037f06bd4b..a93848f3df2 100644 --- a/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/checkers/declaration/FirCommonConstructorDelegationIssuesChecker.kt +++ b/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/checkers/declaration/FirCommonConstructorDelegationIssuesChecker.kt @@ -14,6 +14,7 @@ import org.jetbrains.kotlin.fir.declarations.FirConstructor import org.jetbrains.kotlin.fir.declarations.FirRegularClass import org.jetbrains.kotlin.fir.declarations.FirResolvePhase import org.jetbrains.kotlin.fir.references.FirErrorNamedReference +import org.jetbrains.kotlin.fir.references.FirResolvedErrorReference import org.jetbrains.kotlin.fir.references.FirResolvedNamedReference import org.jetbrains.kotlin.fir.resolve.diagnostics.ConeAmbiguityError import org.jetbrains.kotlin.fir.symbols.SymbolInternals @@ -95,7 +96,9 @@ object FirCommonConstructorDelegationIssuesChecker : FirRegularClassChecker() { private fun FirConstructor.getDelegated(): FirConstructor? { this.symbol.lazyResolveToPhase(FirResolvePhase.BODY_RESOLVE) - val delegatedConstructorSymbol = (delegatedConstructor?.calleeReference as? FirResolvedNamedReference)?.resolvedSymbol + val delegatedConstructorSymbol = (delegatedConstructor?.calleeReference as? FirResolvedNamedReference) + .takeUnless { it is FirResolvedErrorReference } + ?.resolvedSymbol @OptIn(SymbolInternals::class) return delegatedConstructorSymbol?.fir as? FirConstructor } diff --git a/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/checkers/declaration/FirDelegatedPropertyChecker.kt b/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/checkers/declaration/FirDelegatedPropertyChecker.kt index dda2a2e7bfd..d61a7390151 100644 --- a/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/checkers/declaration/FirDelegatedPropertyChecker.kt +++ b/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/checkers/declaration/FirDelegatedPropertyChecker.kt @@ -18,6 +18,7 @@ import org.jetbrains.kotlin.fir.expressions.FirFunctionCall import org.jetbrains.kotlin.fir.expressions.FirImplicitInvokeCall import org.jetbrains.kotlin.fir.expressions.arguments import org.jetbrains.kotlin.fir.references.FirErrorNamedReference +import org.jetbrains.kotlin.fir.references.FirResolvedErrorReference import org.jetbrains.kotlin.fir.resolve.diagnostics.* import org.jetbrains.kotlin.fir.symbols.FirBasedSymbol import org.jetbrains.kotlin.fir.types.* @@ -63,15 +64,20 @@ object FirDelegatedPropertyChecker : FirPropertyChecker() { * @return true if any error was reported; false otherwise. */ private fun checkFunctionReferenceErrors(functionCall: FirFunctionCall): Boolean { - val errorNamedReference = functionCall.calleeReference as? FirErrorNamedReference ?: return false - if (errorNamedReference.source?.kind != KtFakeSourceElementKind.DelegatedPropertyAccessor) return false + val reference = functionCall.calleeReference + val diagnostic = when (reference) { + is FirErrorNamedReference -> reference.diagnostic + is FirResolvedErrorReference -> reference.diagnostic + else -> return false + } + if (reference.source?.kind != KtFakeSourceElementKind.DelegatedPropertyAccessor) return false val expectedFunctionSignature = (if (isGet) "getValue" else "setValue") + "(${functionCall.arguments.joinToString(", ") { it.typeRef.coneType.renderReadable() }})" val delegateDescription = if (isGet) "delegate" else "delegate for var (read-write property)" fun reportInapplicableDiagnostics(candidates: Collection>) { reporter.reportOn( - errorNamedReference.source, + reference.source, FirErrors.DELEGATE_SPECIAL_FUNCTION_NONE_APPLICABLE, expectedFunctionSignature, candidates, @@ -80,9 +86,9 @@ object FirDelegatedPropertyChecker : FirPropertyChecker() { } var errorReported = true - when (val diagnostic = errorNamedReference.diagnostic) { + when (diagnostic) { is ConeUnresolvedNameError -> reporter.reportOn( - errorNamedReference.source, + reference.source, FirErrors.DELEGATE_SPECIAL_FUNCTION_MISSING, expectedFunctionSignature, delegateType, @@ -94,7 +100,7 @@ object FirDelegatedPropertyChecker : FirPropertyChecker() { if (diagnostic.applicability.isSuccess) { // Match is successful but there are too many matches! So we report DELEGATE_SPECIAL_FUNCTION_AMBIGUITY. reporter.reportOn( - errorNamedReference.source, + reference.source, FirErrors.DELEGATE_SPECIAL_FUNCTION_AMBIGUITY, expectedFunctionSignature, diagnostic.candidates.map { it.symbol }, @@ -106,7 +112,7 @@ object FirDelegatedPropertyChecker : FirPropertyChecker() { } is ConeInapplicableWrongReceiver -> reporter.reportOn( - errorNamedReference.source, + reference.source, FirErrors.DELEGATE_SPECIAL_FUNCTION_MISSING, expectedFunctionSignature, delegateType, diff --git a/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/checkers/declaration/FirDestructuringDeclarationChecker.kt b/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/checkers/declaration/FirDestructuringDeclarationChecker.kt index e2992cd7830..7b07096713a 100644 --- a/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/checkers/declaration/FirDestructuringDeclarationChecker.kt +++ b/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/checkers/declaration/FirDestructuringDeclarationChecker.kt @@ -15,10 +15,12 @@ import org.jetbrains.kotlin.fir.declarations.FirProperty import org.jetbrains.kotlin.fir.declarations.FirResolvePhase import org.jetbrains.kotlin.fir.declarations.FirValueParameter import org.jetbrains.kotlin.fir.declarations.FirVariable +import org.jetbrains.kotlin.fir.diagnostics.ConeDiagnostic import org.jetbrains.kotlin.fir.diagnostics.ConeSimpleDiagnostic import org.jetbrains.kotlin.fir.diagnostics.DiagnosticKind import org.jetbrains.kotlin.fir.expressions.* import org.jetbrains.kotlin.fir.references.FirErrorNamedReference +import org.jetbrains.kotlin.fir.references.FirResolvedErrorReference import org.jetbrains.kotlin.fir.resolve.diagnostics.* import org.jetbrains.kotlin.fir.resolvedSymbol import org.jetbrains.kotlin.fir.symbols.SymbolInternals @@ -70,19 +72,24 @@ object FirDestructuringDeclarationChecker : FirPropertyChecker() { else -> null } ?: return - when (val reference = componentCall.calleeReference) { - is FirErrorNamedReference -> - checkComponentCall( - originalDestructuringDeclarationOrInitializerSource, - originalDestructuringDeclarationType, - reference, - declaration, - componentCall, - originalDestructuringDeclaration, - reporter, - context - ) + val diagnostic = when (val reference = componentCall.calleeReference) { + is FirErrorNamedReference -> reference.diagnostic + is FirResolvedErrorReference -> reference.diagnostic + else -> null } + if (diagnostic != null) { + checkComponentCall( + originalDestructuringDeclarationOrInitializerSource, + originalDestructuringDeclarationType, + diagnostic, + declaration, + componentCall, + originalDestructuringDeclaration, + reporter, + context + ) + } + } private fun checkInitializer( @@ -105,14 +112,14 @@ object FirDestructuringDeclarationChecker : FirPropertyChecker() { private fun checkComponentCall( source: KtSourceElement, destructuringDeclarationType: ConeKotlinType, - reference: FirErrorNamedReference, + diagnostic: ConeDiagnostic, property: FirProperty, componentCall: FirComponentCall, destructuringDeclaration: FirVariable, reporter: DiagnosticReporter, context: CheckerContext ) { - when (val diagnostic = reference.diagnostic) { + when (diagnostic) { is ConeUnresolvedNameError -> { reporter.reportOn( source, diff --git a/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/checkers/expression/FirForLoopChecker.kt b/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/checkers/expression/FirForLoopChecker.kt index e73960108c8..946c1e49f58 100644 --- a/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/checkers/expression/FirForLoopChecker.kt +++ b/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/checkers/expression/FirForLoopChecker.kt @@ -26,10 +26,12 @@ import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.NEXT_NONE_APPLICA import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.OPERATOR_MODIFIER_REQUIRED import org.jetbrains.kotlin.fir.declarations.FirProperty import org.jetbrains.kotlin.fir.declarations.utils.isOperator +import org.jetbrains.kotlin.fir.diagnostics.FirDiagnosticHolder import org.jetbrains.kotlin.fir.expressions.FirBlock import org.jetbrains.kotlin.fir.expressions.FirFunctionCall import org.jetbrains.kotlin.fir.expressions.FirWhileLoop import org.jetbrains.kotlin.fir.references.FirErrorNamedReference +import org.jetbrains.kotlin.fir.references.FirResolvedErrorReference import org.jetbrains.kotlin.fir.references.FirResolvedNamedReference import org.jetbrains.kotlin.fir.resolve.calls.UnsafeCall import org.jetbrains.kotlin.fir.resolve.diagnostics.ConeAmbiguityError @@ -104,8 +106,8 @@ object FirForLoopChecker : FirBlockChecker() { unsafeCallFactory: KtDiagnosticFactory0? = null, ): Boolean { when (val calleeReference = call.calleeReference) { - is FirErrorNamedReference -> { - when (val diagnostic = calleeReference.diagnostic) { + is FirErrorNamedReference, is FirResolvedErrorReference -> { + when (val diagnostic = (calleeReference as FirDiagnosticHolder).diagnostic) { is ConeAmbiguityError -> if (diagnostic.applicability.isSuccess) { reporter.reportOn(reportSource, ambiguityFactory, diagnostic.candidates.map { it.symbol }, context) } else if (noneApplicableFactory != null) { diff --git a/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/checkers/expression/FirSealedClassConstructorCallChecker.kt b/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/checkers/expression/FirSealedClassConstructorCallChecker.kt index b1773af183b..0aaa0c2dcb5 100644 --- a/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/checkers/expression/FirSealedClassConstructorCallChecker.kt +++ b/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/checkers/expression/FirSealedClassConstructorCallChecker.kt @@ -12,6 +12,7 @@ import org.jetbrains.kotlin.fir.analysis.checkers.context.CheckerContext import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors import org.jetbrains.kotlin.fir.declarations.utils.modality import org.jetbrains.kotlin.fir.expressions.FirQualifiedAccessExpression +import org.jetbrains.kotlin.fir.references.FirResolvedErrorReference import org.jetbrains.kotlin.fir.references.FirResolvedNamedReference import org.jetbrains.kotlin.fir.resolve.fullyExpandedType import org.jetbrains.kotlin.fir.resolve.toSymbol @@ -23,6 +24,7 @@ import org.jetbrains.kotlin.fir.types.coneType object FirSealedClassConstructorCallChecker : FirQualifiedAccessExpressionChecker() { override fun check(expression: FirQualifiedAccessExpression, context: CheckerContext, reporter: DiagnosticReporter) { val constructorSymbol = (expression.calleeReference as? FirResolvedNamedReference) + ?.takeUnless { it is FirResolvedErrorReference } ?.resolvedSymbol as? FirConstructorSymbol ?: return diff --git a/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/checkers/expression/FirUpperBoundViolatedExpressionChecker.kt b/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/checkers/expression/FirUpperBoundViolatedExpressionChecker.kt index 78a34ca7ad9..43d6485077b 100644 --- a/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/checkers/expression/FirUpperBoundViolatedExpressionChecker.kt +++ b/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/checkers/expression/FirUpperBoundViolatedExpressionChecker.kt @@ -11,13 +11,12 @@ import org.jetbrains.kotlin.fir.analysis.checkers.checkUpperBoundViolated import org.jetbrains.kotlin.fir.analysis.checkers.context.CheckerContext import org.jetbrains.kotlin.fir.expressions.FirQualifiedAccessExpression import org.jetbrains.kotlin.fir.expressions.toResolvedCallableSymbol -import org.jetbrains.kotlin.fir.references.FirErrorNamedReference +import org.jetbrains.kotlin.fir.references.FirResolvedErrorReference import org.jetbrains.kotlin.fir.references.FirResolvedNamedReference import org.jetbrains.kotlin.fir.resolve.diagnostics.ConeInapplicableWrongReceiver import org.jetbrains.kotlin.fir.resolve.fullyExpandedType import org.jetbrains.kotlin.fir.resolve.isTypeAliasedConstructor import org.jetbrains.kotlin.fir.resolve.substitution.substitutorByMap -import org.jetbrains.kotlin.fir.symbols.impl.FirCallableSymbol import org.jetbrains.kotlin.fir.symbols.impl.FirConstructorSymbol import org.jetbrains.kotlin.fir.symbols.impl.FirRegularClassSymbol import org.jetbrains.kotlin.fir.symbols.impl.FirTypeParameterSymbol @@ -29,15 +28,15 @@ object FirUpperBoundViolatedExpressionChecker : FirQualifiedAccessExpressionChec // declarations with their declared bounds. // it may be the called function declaration // or the class declaration - val calleeReference = expression.calleeReference - var calleeSymbol: FirCallableSymbol<*>? = null - if (calleeReference is FirResolvedNamedReference) { - calleeSymbol = calleeReference.toResolvedCallableSymbol() - } else if (calleeReference is FirErrorNamedReference) { - if (calleeReference.diagnostic is ConeInapplicableWrongReceiver) { - return + val calleeSymbol = when (val calleeReference = expression.calleeReference) { + is FirResolvedErrorReference -> { + if (calleeReference.diagnostic is ConeInapplicableWrongReceiver) { + return + } + calleeReference.toResolvedCallableSymbol() } - calleeSymbol = calleeReference.candidateSymbol as? FirCallableSymbol<*> + is FirResolvedNamedReference -> calleeReference.toResolvedCallableSymbol() + else -> null } val typeArguments: List diff --git a/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/checkers/extended/RedundantExplicitTypeChecker.kt b/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/checkers/extended/RedundantExplicitTypeChecker.kt index a7bbd9fa9d2..19daae0a5e2 100644 --- a/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/checkers/extended/RedundantExplicitTypeChecker.kt +++ b/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/checkers/extended/RedundantExplicitTypeChecker.kt @@ -26,11 +26,11 @@ object RedundantExplicitTypeChecker : FirPropertyChecker() { if (!declaration.isLocal) return val initializer = declaration.initializer ?: return - val typeReference = declaration.returnTypeRef + val typeReference = declaration.returnTypeRef.takeUnless { it is FirErrorTypeRef } ?: return if (typeReference.source?.kind is KtFakeSourceElementKind) return - val type = declaration.returnTypeRef.coneType + val type = typeReference.coneType if (type.toSymbol(context.session) is FirTypeAliasSymbol) return if (typeReference.annotations.isNotEmpty()) return diff --git a/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/collectors/components/ErrorNodeDiagnosticCollectorComponent.kt b/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/collectors/components/ErrorNodeDiagnosticCollectorComponent.kt index 5fb6413f4c2..5bb2fd7dcc9 100644 --- a/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/collectors/components/ErrorNodeDiagnosticCollectorComponent.kt +++ b/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/collectors/components/ErrorNodeDiagnosticCollectorComponent.kt @@ -20,6 +20,8 @@ import org.jetbrains.kotlin.fir.diagnostics.ConeSimpleDiagnostic import org.jetbrains.kotlin.fir.diagnostics.DiagnosticKind import org.jetbrains.kotlin.fir.expressions.* import org.jetbrains.kotlin.fir.references.FirErrorNamedReference +import org.jetbrains.kotlin.fir.references.FirNamedReference +import org.jetbrains.kotlin.fir.references.FirResolvedErrorReference import org.jetbrains.kotlin.fir.resolve.diagnostics.* import org.jetbrains.kotlin.fir.types.ConeErrorType import org.jetbrains.kotlin.fir.types.FirErrorTypeRef @@ -52,20 +54,28 @@ class ErrorNodeDiagnosticCollectorComponent( } override fun visitErrorNamedReference(errorNamedReference: FirErrorNamedReference, data: CheckerContext) { - val source = errorNamedReference.source ?: return - val qualifiedAccessOrAnnotationCall = data.qualifiedAccessOrAnnotationCalls.lastOrNull()?.takeIf { + processErrorReference(errorNamedReference, errorNamedReference.diagnostic, data) + } + + override fun visitResolvedErrorReference(resolvedErrorReference: FirResolvedErrorReference, data: CheckerContext) { + processErrorReference(resolvedErrorReference, resolvedErrorReference.diagnostic, data) + } + + private fun processErrorReference(reference: FirNamedReference, diagnostic: ConeDiagnostic, context: CheckerContext) { + val source = reference.source ?: return + val qualifiedAccessOrAnnotationCall = context.qualifiedAccessOrAnnotationCalls.lastOrNull()?.takeIf { // Use the source of the enclosing FirQualifiedAccess if it is exactly the call to the erroneous callee. when (it) { - is FirQualifiedAccess -> it.calleeReference == errorNamedReference - is FirAnnotationCall -> it.calleeReference == errorNamedReference + is FirQualifiedAccess -> it.calleeReference == reference + is FirAnnotationCall -> it.calleeReference == reference else -> false } } // Don't report duplicated unresolved reference on annotation entry (already reported on its type) - if (source.elementType == KtNodeTypes.ANNOTATION_ENTRY && errorNamedReference.diagnostic is ConeUnresolvedNameError) return + if (source.elementType == KtNodeTypes.ANNOTATION_ENTRY && diagnostic is ConeUnresolvedNameError) return // Already reported in FirConventionFunctionCallChecker if (source.kind == KtFakeSourceElementKind.ArrayAccessNameReference && - errorNamedReference.diagnostic is ConeUnresolvedNameError + diagnostic is ConeUnresolvedNameError ) return // If the receiver cannot be resolved, we skip reporting any further problems for this call. @@ -76,7 +86,7 @@ class ErrorNodeDiagnosticCollectorComponent( ) return } - reportFirDiagnostic(errorNamedReference.diagnostic, source, data, qualifiedAccessOrAnnotationCall?.source) + reportFirDiagnostic(diagnostic, source, context, qualifiedAccessOrAnnotationCall?.source) } private fun FirExpression?.cannotBeResolved(): Boolean { diff --git a/compiler/fir/dump/src/org/jetbrains/kotlin/fir/dump/HtmlFirDump.kt b/compiler/fir/dump/src/org/jetbrains/kotlin/fir/dump/HtmlFirDump.kt index ed0538a94d3..97b30d1c56c 100644 --- a/compiler/fir/dump/src/org/jetbrains/kotlin/fir/dump/HtmlFirDump.kt +++ b/compiler/fir/dump/src/org/jetbrains/kotlin/fir/dump/HtmlFirDump.kt @@ -1302,6 +1302,18 @@ class HtmlFirDump internal constructor(private var linkResolver: FirLinkResolver simpleName(reference.name) } } + is FirResolvedErrorReference -> { + errorWithDiagnostic { + resolved { + symbolRef(reference.resolvedSymbol) { + simpleName(reference.name) + } + } + diagnosticHover { + generate(reference.diagnostic) + } + } + } is FirResolvedNamedReference -> { resolved { symbolRef(reference.resolvedSymbol) { diff --git a/compiler/fir/fir2ir/src/org/jetbrains/kotlin/fir/backend/ConversionUtils.kt b/compiler/fir/fir2ir/src/org/jetbrains/kotlin/fir/backend/ConversionUtils.kt index 290f9dbb858..905553b3fc1 100644 --- a/compiler/fir/fir2ir/src/org/jetbrains/kotlin/fir/backend/ConversionUtils.kt +++ b/compiler/fir/fir2ir/src/org/jetbrains/kotlin/fir/backend/ConversionUtils.kt @@ -197,15 +197,6 @@ fun FirReference.toSymbolForCall( isReference ) - is FirErrorNamedReference -> - candidateSymbol?.toSymbolForCall( - dispatchReceiver, - preferGetter, - explicitReceiver, - isDelegate, - isReference - ) - is FirThisReference -> { when (val boundSymbol = boundSymbol) { is FirClassSymbol<*> -> classifierStorage.getIrClassSymbol(boundSymbol).owner.thisReceiver?.symbol diff --git a/compiler/fir/fir2ir/src/org/jetbrains/kotlin/fir/backend/generators/CallAndReferenceGenerator.kt b/compiler/fir/fir2ir/src/org/jetbrains/kotlin/fir/backend/generators/CallAndReferenceGenerator.kt index 6d8dc594862..6addde7181c 100644 --- a/compiler/fir/fir2ir/src/org/jetbrains/kotlin/fir/backend/generators/CallAndReferenceGenerator.kt +++ b/compiler/fir/fir2ir/src/org/jetbrains/kotlin/fir/backend/generators/CallAndReferenceGenerator.kt @@ -1066,12 +1066,9 @@ class CallAndReferenceGenerator( } if (ownerFunction?.extensionReceiverParameter != null) { extensionReceiver = qualifiedAccess.findIrExtensionReceiver(explicitReceiverExpression)?.let { - val symbol = when (val reference = qualifiedAccess.calleeReference) { - is FirResolvedNamedReference -> reference.resolvedSymbol - is FirErrorNamedReference -> reference.candidateSymbol - else -> null - } ?: error("Symbol for call ${qualifiedAccess.render()} not found") - (symbol.fir as? FirCallableDeclaration)?.receiverParameter?.typeRef?.let { receiverType -> + val symbol = qualifiedAccess.calleeReference.toResolvedCallableSymbol() + ?: error("Symbol for call ${qualifiedAccess.render()} not found") + symbol.fir.receiverParameter?.typeRef?.let { receiverType -> with(visitor.implicitCastInserter) { it.cast( qualifiedAccess.extensionReceiver, diff --git a/compiler/fir/raw-fir/psi2fir/tests/org/jetbrains/kotlin/fir/builder/RawFirBuilderTotalKotlinTestCase.kt b/compiler/fir/raw-fir/psi2fir/tests/org/jetbrains/kotlin/fir/builder/RawFirBuilderTotalKotlinTestCase.kt index bf1ef35a67c..aa10fa13402 100644 --- a/compiler/fir/raw-fir/psi2fir/tests/org/jetbrains/kotlin/fir/builder/RawFirBuilderTotalKotlinTestCase.kt +++ b/compiler/fir/raw-fir/psi2fir/tests/org/jetbrains/kotlin/fir/builder/RawFirBuilderTotalKotlinTestCase.kt @@ -10,6 +10,7 @@ import org.jetbrains.kotlin.fir.FirElement import org.jetbrains.kotlin.fir.declarations.FirDeclaration import org.jetbrains.kotlin.fir.declarations.FirFile import org.jetbrains.kotlin.fir.declarations.FirProperty +import org.jetbrains.kotlin.fir.diagnostics.FirDiagnosticHolder import org.jetbrains.kotlin.fir.expressions.FirErrorExpression import org.jetbrains.kotlin.fir.expressions.FirExpression import org.jetbrains.kotlin.fir.expressions.FirQualifiedAccess @@ -18,6 +19,7 @@ import org.jetbrains.kotlin.fir.expressions.impl.FirExpressionStub import org.jetbrains.kotlin.fir.isCatchParameter import org.jetbrains.kotlin.fir.psi import org.jetbrains.kotlin.fir.references.FirErrorNamedReference +import org.jetbrains.kotlin.fir.references.FirResolvedErrorReference import org.jetbrains.kotlin.fir.render import org.jetbrains.kotlin.fir.renderer.FirRenderer import org.jetbrains.kotlin.fir.visitors.FirVisitor @@ -82,12 +84,14 @@ class RawFirBuilderTotalKotlinTestCase : AbstractRawFirBuilderTestCase() { } override fun visitQualifiedAccess(qualifiedAccess: FirQualifiedAccess, data: FirElement) { - val calleeReference = qualifiedAccess.calleeReference - if (calleeReference is FirErrorNamedReference) { - errorReferences++ - println(calleeReference.diagnostic.reason) - } else { - normalReferences++ + when (val calleeReference = qualifiedAccess.calleeReference) { + is FirErrorNamedReference, is FirResolvedErrorReference -> { + errorReferences++ + println((calleeReference as FirDiagnosticHolder).diagnostic.reason) + } + else -> { + normalReferences++ + } } visitStatement(qualifiedAccess, data) } diff --git a/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/FirCallResolver.kt b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/FirCallResolver.kt index d12ce0b494f..c6a5b2b3e64 100644 --- a/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/FirCallResolver.kt +++ b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/FirCallResolver.kt @@ -285,6 +285,7 @@ class FirCallResolver( val diagnostic = when (nameReference) { is FirErrorReferenceWithCandidate -> nameReference.diagnostic + is FirResolvedErrorReference -> nameReference.diagnostic is FirErrorNamedReference -> nameReference.diagnostic else -> null } @@ -371,7 +372,7 @@ class FirCallResolver( when { noSuccessfulCandidates -> { - val errorReference = buildErrorReference( + val errorReference = buildReferenceWithErrorCandidate( info, if (applicability == CandidateApplicability.K2_UNSUPPORTED) { val unsupportedResolutionDiagnostic = reducedCandidates.firstOrNull()?.diagnostics?.firstOrNull() as? Unsupported @@ -386,7 +387,7 @@ class FirCallResolver( } reducedCandidates.size > 1 -> { if (resolvedCallableReferenceAtom.hasBeenPostponed) { - val errorReference = buildErrorReference( + val errorReference = buildReferenceWithErrorCandidate( info, ConeAmbiguityError(info.name, applicability, reducedCandidates), callableReferenceAccess.source @@ -530,7 +531,7 @@ class FirCallResolver( explicitReceiver = null ) } else { - buildErrorReference( + buildReferenceWithErrorCandidate( callInfo, if (annotationClassSymbol != null) ConeIllegalAnnotationError(reference.name) //calleeReference and annotationTypeRef are both error nodes so we need to avoid doubling of the diagnostic report @@ -635,133 +636,132 @@ class FirCallResolver( expectedCandidates: Collection? = null ): FirNamedReference { val source = reference.source - return when { + + val diagnostic = when { expectedCallKind != null -> { fun isValueParametersNotEmpty(candidate: Candidate): Boolean { return (candidate.symbol.fir as? FirFunction)?.valueParameters?.size?.let { it > 0 } ?: false } - val candidate = candidates.singleOrNull() + when (expectedCallKind) { + CallKind.Function -> ConeFunctionCallExpectedError(name, candidates.any { isValueParametersNotEmpty(it) }, candidates) + else -> { + val singleExpectedCandidate = expectedCandidates?.singleOrNull() - val diagnostic = if (expectedCallKind == CallKind.Function) { - ConeFunctionCallExpectedError(name, candidates.any { isValueParametersNotEmpty(it) }, candidates) - } else { - val singleExpectedCandidate = expectedCandidates?.singleOrNull() + var fir = singleExpectedCandidate?.symbol?.fir + if (fir is FirTypeAlias) { + fir = (fir.expandedTypeRef.coneType.fullyExpandedType(session).toSymbol(session) as? FirRegularClassSymbol)?.fir + } - var fir = singleExpectedCandidate?.symbol?.fir - if (fir is FirTypeAlias) { - fir = (fir.expandedTypeRef.coneType.fullyExpandedType(session).toSymbol(session) as? FirRegularClassSymbol)?.fir - } - - if (fir is FirRegularClass) { - ConeResolutionToClassifierError(singleExpectedCandidate!!, fir.symbol) - } else { - val coneType = explicitReceiver?.typeRef?.coneType - when { - coneType != null && !coneType.isUnit -> { - ConeFunctionExpectedError( - name.asString(), - (fir as? FirCallableDeclaration)?.returnTypeRef?.coneType ?: coneType - ) + when (fir) { + is FirRegularClass -> { + ConeResolutionToClassifierError(singleExpectedCandidate!!, fir.symbol) } - singleExpectedCandidate != null && !singleExpectedCandidate.currentApplicability.isSuccess -> { - createConeDiagnosticForCandidateWithError( - singleExpectedCandidate.currentApplicability, - singleExpectedCandidate - ) + else -> { + val coneType = explicitReceiver?.typeRef?.coneType + when { + coneType != null && !coneType.isUnit -> { + ConeFunctionExpectedError( + name.asString(), + (fir as? FirCallableDeclaration)?.returnTypeRef?.coneType ?: coneType + ) + } + singleExpectedCandidate != null && !singleExpectedCandidate.currentApplicability.isSuccess -> { + createConeDiagnosticForCandidateWithError( + singleExpectedCandidate.currentApplicability, + singleExpectedCandidate + ) + } + else -> ConeUnresolvedNameError(name) + } } - else -> ConeUnresolvedNameError(name) } } } - - if (candidate != null) { - createErrorReferenceWithExistingCandidate( - candidate, - diagnostic, - source, - transformer.resolutionContext, - components.resolutionStageRunner - ) - } else { - buildErrorReference(callInfo, diagnostic, source) - } } candidates.isEmpty() -> { - val diagnostic = if (name.asString() == "invoke" && explicitReceiver is FirConstExpression<*>) { + if (name.asString() == "invoke" && explicitReceiver is FirConstExpression<*>) { ConeFunctionExpectedError(explicitReceiver.value?.toString() ?: "", explicitReceiver.typeRef.coneType) } else { ConeUnresolvedNameError(name) } - - buildErrorReference( - callInfo, - diagnostic, - source - ) } - candidates.size > 1 -> buildErrorReference( - callInfo, - ConeAmbiguityError(name, applicability, candidates), - source - ) + candidates.size > 1 -> ConeAmbiguityError(name, applicability, candidates) !applicability.isSuccess -> { val candidate = candidates.single() - val diagnostic = createConeDiagnosticForCandidateWithError(applicability, candidate) - createErrorReferenceWithExistingCandidate( - candidate, - diagnostic, - source, - transformer.resolutionContext, - components.resolutionStageRunner - ) + createConeDiagnosticForCandidateWithError(applicability, candidate) } - else -> { - val candidate = candidates.single() - val coneSymbol = candidate.symbol - if (coneSymbol is FirBackingFieldSymbol) { - coneSymbol.fir.propertySymbol.fir.isReferredViaField = true - return buildBackingFieldReference { - this.source = source - resolvedSymbol = coneSymbol - } - } - if ((coneSymbol as? FirPropertySymbol)?.hasExplicitBackingField == true) { - return FirPropertyWithExplicitBackingFieldResolvedNamedReference( - source, name, candidate.symbol, candidate.hasVisibleBackingField - ) - } - /* - * This `if` is an optimization for local variables and properties without type parameters - * Since they have no type variables, so we can don't run completion on them at all and create - * resolved reference immediately - * - * But for callable reference resolution we should keep candidate, because it was resolved - * with special resolution stages, which saved in candidate additional reference info, - * like `resultingTypeForCallableReference` - */ - if ( - createResolvedReferenceWithoutCandidateForLocalVariables && - explicitReceiver?.typeRef?.coneTypeSafe() == null && - coneSymbol is FirVariableSymbol && - (coneSymbol !is FirPropertySymbol || (coneSymbol.fir as FirMemberDeclaration).typeParameters.isEmpty()) - ) { - return buildResolvedNamedReference { - this.source = source - this.name = name - resolvedSymbol = coneSymbol - } - } - FirNamedReferenceWithCandidate(source, name, candidate) + else -> null + } + + if (diagnostic != null) { + return createErrorReferenceForSingleCandidate(candidates.singleOrNull(), diagnostic, callInfo, source) + } + + // successful candidate + + val candidate = candidates.single() + val coneSymbol = candidate.symbol + if (coneSymbol is FirBackingFieldSymbol) { + coneSymbol.fir.propertySymbol.fir.isReferredViaField = true + return buildBackingFieldReference { + this.source = source + resolvedSymbol = coneSymbol } } + if ((coneSymbol as? FirPropertySymbol)?.hasExplicitBackingField == true) { + return FirPropertyWithExplicitBackingFieldResolvedNamedReference( + source, name, candidate.symbol, candidate.hasVisibleBackingField + ) + } + /* + * This `if` is an optimization for local variables and properties without type parameters + * Since they have no type variables, so we can don't run completion on them at all and create + * resolved reference immediately + * + * But for callable reference resolution we should keep candidate, because it was resolved + * with special resolution stages, which saved in candidate additional reference info, + * like `resultingTypeForCallableReference` + */ + if ( + createResolvedReferenceWithoutCandidateForLocalVariables && + explicitReceiver?.typeRef?.coneTypeSafe() == null && + coneSymbol is FirVariableSymbol && + (coneSymbol !is FirPropertySymbol || (coneSymbol.fir as FirMemberDeclaration).typeParameters.isEmpty()) + ) { + return buildResolvedNamedReference { + this.source = source + this.name = name + resolvedSymbol = coneSymbol + } + } + return FirNamedReferenceWithCandidate(source, name, candidate) + } + + private fun createErrorReferenceForSingleCandidate( + candidate: Candidate?, + diagnostic: ConeDiagnostic, + callInfo: CallInfo, + source: KtSourceElement? + ): FirNamedReference { + if (candidate == null) return buildReferenceWithErrorCandidate(callInfo, diagnostic, source) + return when (diagnostic) { + is ConeUnresolvedError, is ConeHiddenCandidateError -> buildReferenceWithErrorCandidate(callInfo, diagnostic, source) + else -> createErrorReferenceWithExistingCandidate( + candidate, + diagnostic, + source, + transformer.resolutionContext, + components.resolutionStageRunner + ) + } } - private fun buildErrorReference( + private fun buildReferenceWithErrorCandidate( callInfo: CallInfo, diagnostic: ConeDiagnostic, source: KtSourceElement? diff --git a/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/transformers/FirCallCompletionResultsWriterTransformer.kt b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/transformers/FirCallCompletionResultsWriterTransformer.kt index 02cde021c5f..6c33480eed8 100644 --- a/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/transformers/FirCallCompletionResultsWriterTransformer.kt +++ b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/transformers/FirCallCompletionResultsWriterTransformer.kt @@ -15,6 +15,7 @@ import org.jetbrains.kotlin.fir.declarations.builder.buildReceiverParameterCopy import org.jetbrains.kotlin.fir.declarations.utils.isInline import org.jetbrains.kotlin.fir.declarations.utils.isLocal import org.jetbrains.kotlin.fir.declarations.utils.visibility +import org.jetbrains.kotlin.fir.diagnostics.ConeDiagnostic import org.jetbrains.kotlin.fir.diagnostics.ConeSimpleDiagnostic import org.jetbrains.kotlin.fir.diagnostics.DiagnosticKind import org.jetbrains.kotlin.fir.expressions.* @@ -22,6 +23,7 @@ import org.jetbrains.kotlin.fir.expressions.impl.FirPropertyAccessExpressionImpl import org.jetbrains.kotlin.fir.references.FirNamedReference import org.jetbrains.kotlin.fir.references.builder.buildErrorNamedReference import org.jetbrains.kotlin.fir.references.builder.buildResolvedCallableReference +import org.jetbrains.kotlin.fir.references.builder.buildResolvedErrorReference import org.jetbrains.kotlin.fir.references.builder.buildResolvedNamedReference import org.jetbrains.kotlin.fir.resolve.* import org.jetbrains.kotlin.fir.resolve.calls.Candidate @@ -37,9 +39,7 @@ import org.jetbrains.kotlin.fir.scopes.impl.ConvertibleIntegerOperators.binaryOp import org.jetbrains.kotlin.fir.scopes.impl.isWrappedIntegerOperator import org.jetbrains.kotlin.fir.scopes.impl.isWrappedIntegerOperatorForUnsignedType import org.jetbrains.kotlin.fir.symbols.FirBasedSymbol -import org.jetbrains.kotlin.fir.symbols.impl.FirConstructorSymbol -import org.jetbrains.kotlin.fir.symbols.impl.FirNamedFunctionSymbol -import org.jetbrains.kotlin.fir.symbols.impl.FirPropertySymbol +import org.jetbrains.kotlin.fir.symbols.impl.* import org.jetbrains.kotlin.fir.types.* import org.jetbrains.kotlin.fir.types.builder.buildErrorTypeRef import org.jetbrains.kotlin.fir.types.builder.buildResolvedTypeRef @@ -379,11 +379,7 @@ class FirCallCompletionResultsWriterTransformer( session.lookupTracker?.recordTypeResolveAsLookup(resultType, typeRef.source ?: callableReferenceAccess.source, context.file.source) val resolvedReference = when (calleeReference) { - is FirErrorReferenceWithCandidate -> buildErrorNamedReference { - source = calleeReference.source - diagnostic = calleeReference.diagnostic - candidateSymbol = calleeReference.candidateSymbol - } + is FirErrorReferenceWithCandidate -> calleeReference.toErrorReference(calleeReference.diagnostic) else -> buildResolvedCallableReference { source = calleeReference.source name = calleeReference.name @@ -400,6 +396,23 @@ class FirCallCompletionResultsWriterTransformer( .transformExtensionReceiver(StoreReceiver, subCandidate.chosenExtensionReceiverExpression()) } + private fun FirNamedReferenceWithCandidate.toErrorReference(diagnostic: ConeDiagnostic): FirNamedReference { + val calleeReference = this + return when (calleeReference.candidateSymbol) { + is FirErrorPropertySymbol, is FirErrorFunctionSymbol -> buildErrorNamedReference { + source = calleeReference.source + candidateSymbol = calleeReference.candidateSymbol + this.diagnostic = diagnostic + } + else -> buildResolvedErrorReference { + source = calleeReference.source + name = calleeReference.name + resolvedSymbol = calleeReference.candidateSymbol + this.diagnostic = diagnostic + } + } + } + override fun transformVariableAssignment( variableAssignment: FirVariableAssignment, data: ExpectedArgumentType?, @@ -866,18 +879,14 @@ class FirCallCompletionResultsWriterTransformer( else -> null } - return if (errorDiagnostic != null) { - buildErrorNamedReference { - source = this@toResolvedReference.source - diagnostic = errorDiagnostic - candidateSymbol = this@toResolvedReference.candidateSymbol - } - } else { - buildResolvedNamedReference { + return when (errorDiagnostic) { + null -> buildResolvedNamedReference { source = this@toResolvedReference.source name = this@toResolvedReference.name resolvedSymbol = this@toResolvedReference.candidateSymbol } + + else -> toErrorReference(errorDiagnostic) } } } diff --git a/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/transformers/IntegerLiteralAndOperatorApproximationTransformer.kt b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/transformers/IntegerLiteralAndOperatorApproximationTransformer.kt index c50e389b5f5..783e9cd8846 100644 --- a/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/transformers/IntegerLiteralAndOperatorApproximationTransformer.kt +++ b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/transformers/IntegerLiteralAndOperatorApproximationTransformer.kt @@ -14,13 +14,13 @@ import org.jetbrains.kotlin.fir.expressions.FirExpression import org.jetbrains.kotlin.fir.expressions.FirIntegerLiteralOperatorCall import org.jetbrains.kotlin.fir.expressions.FirStatement import org.jetbrains.kotlin.fir.expressions.builder.buildFunctionCall +import org.jetbrains.kotlin.fir.references.FirResolvedErrorReference import org.jetbrains.kotlin.fir.references.FirResolvedNamedReference +import org.jetbrains.kotlin.fir.references.builder.buildResolvedErrorReference import org.jetbrains.kotlin.fir.references.builder.buildResolvedNamedReference -import org.jetbrains.kotlin.fir.resolve.BodyResolveComponents import org.jetbrains.kotlin.fir.resolve.ScopeSession import org.jetbrains.kotlin.fir.resolve.scope import org.jetbrains.kotlin.fir.resolve.transformers.body.resolve.resultType -import org.jetbrains.kotlin.fir.resolvedSymbol import org.jetbrains.kotlin.fir.resolvedTypeFromPrototype import org.jetbrains.kotlin.fir.scopes.FakeOverrideTypeCalculator import org.jetbrains.kotlin.fir.scopes.getFunctions @@ -90,13 +90,21 @@ class IntegerLiteralAndOperatorApproximationTransformer( val wrappedFunctionSymbol = calleeReference.resolvedSymbol as FirNamedFunctionSymbol val originalFunctionSymbol = wrappedFunctionSymbol.fir.originalForWrappedIntegerOperator!! - call.replaceCalleeReference( - buildResolvedNamedReference { + val newCalleeReference = when (calleeReference) { + is FirResolvedErrorReference -> buildResolvedErrorReference { + name = calleeReference.name + source = calleeReference.source + resolvedSymbol = originalFunctionSymbol + diagnostic = calleeReference.diagnostic + } + else -> buildResolvedNamedReference { name = calleeReference.name source = calleeReference.source resolvedSymbol = originalFunctionSymbol } - ) + } + + call.replaceCalleeReference(newCalleeReference) } if (approximatedType.isInt || approximatedType.isUInt) return call diff --git a/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/transformers/body/resolve/FirArrayOfCallTransformer.kt b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/transformers/body/resolve/FirArrayOfCallTransformer.kt index 14aaf36c62c..996051ea95a 100644 --- a/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/transformers/body/resolve/FirArrayOfCallTransformer.kt +++ b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/transformers/body/resolve/FirArrayOfCallTransformer.kt @@ -11,6 +11,7 @@ import org.jetbrains.kotlin.fir.declarations.FirSimpleFunction import org.jetbrains.kotlin.fir.expressions.* import org.jetbrains.kotlin.fir.expressions.builder.buildArgumentList import org.jetbrains.kotlin.fir.expressions.builder.buildArrayOfCall +import org.jetbrains.kotlin.fir.references.FirResolvedErrorReference import org.jetbrains.kotlin.fir.references.FirResolvedNamedReference import org.jetbrains.kotlin.fir.resolve.calls.FirNamedReferenceWithCandidate import org.jetbrains.kotlin.fir.symbols.FirBasedSymbol @@ -79,6 +80,7 @@ internal class FirArrayOfCallTransformer : FirDefaultTransformer() { private fun FirFunctionCall.getOriginalFunction(): FirCallableDeclaration? { val symbol: FirBasedSymbol<*>? = when (val reference = calleeReference) { + is FirResolvedErrorReference -> null is FirResolvedNamedReference -> reference.resolvedSymbol is FirNamedReferenceWithCandidate -> reference.candidateSymbol else -> null diff --git a/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/transformers/body/resolve/FirDeclarationsResolveTransformer.kt b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/transformers/body/resolve/FirDeclarationsResolveTransformer.kt index ad46c75b971..2bb06b34af9 100644 --- a/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/transformers/body/resolve/FirDeclarationsResolveTransformer.kt +++ b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/transformers/body/resolve/FirDeclarationsResolveTransformer.kt @@ -26,6 +26,7 @@ import org.jetbrains.kotlin.fir.expressions.* import org.jetbrains.kotlin.fir.expressions.builder.buildReturnExpression import org.jetbrains.kotlin.fir.expressions.builder.buildUnitExpression import org.jetbrains.kotlin.fir.expressions.impl.FirLazyBlock +import org.jetbrains.kotlin.fir.references.FirResolvedErrorReference import org.jetbrains.kotlin.fir.references.FirResolvedNamedReference import org.jetbrains.kotlin.fir.resolve.* import org.jetbrains.kotlin.fir.resolve.calls.FirNamedReferenceWithCandidate @@ -362,7 +363,8 @@ open class FirDeclarationsResolveTransformer(transformer: FirAbstractBodyResolve return provideDelegateCall } - if (provideDelegateCall.calleeReference is FirResolvedNamedReference) { + val provideDelegateReference = provideDelegateCall.calleeReference + if (provideDelegateReference is FirResolvedNamedReference && provideDelegateReference !is FirResolvedErrorReference) { return provideDelegateCall } diff --git a/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/transformers/body/resolve/FirExpressionsResolveTransformer.kt b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/transformers/body/resolve/FirExpressionsResolveTransformer.kt index 6dbb1feeab9..10c1558b539 100644 --- a/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/transformers/body/resolve/FirExpressionsResolveTransformer.kt +++ b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/transformers/body/resolve/FirExpressionsResolveTransformer.kt @@ -23,6 +23,7 @@ import org.jetbrains.kotlin.fir.extensions.extensionService import org.jetbrains.kotlin.fir.references.* import org.jetbrains.kotlin.fir.references.builder.buildErrorNamedReference import org.jetbrains.kotlin.fir.references.builder.buildExplicitSuperReference +import org.jetbrains.kotlin.fir.references.builder.buildResolvedErrorReference import org.jetbrains.kotlin.fir.references.builder.buildSimpleNamedReference import org.jetbrains.kotlin.fir.references.impl.FirSimpleNamedReference import org.jetbrains.kotlin.fir.resolve.* @@ -891,9 +892,10 @@ open class FirExpressionsResolveTransformer(transformer: FirAbstractBodyResolveT else -> { val altererNames = alteredAssignments.map { it.second::class.qualifiedName } - val errorReference = buildErrorNamedReference { + val errorReference = buildResolvedErrorReference { source = resolvedReference.source - candidateSymbol = resolvedReference.resolvedSymbol + name = resolvedReference.name + resolvedSymbol = resolvedReference.resolvedSymbol diagnostic = ConeAmbiguousAlteredAssign(altererNames) } completeAssignment.replaceCalleeReference(errorReference) diff --git a/compiler/fir/tree/src/org/jetbrains/kotlin/fir/renderer/FirRenderer.kt b/compiler/fir/tree/src/org/jetbrains/kotlin/fir/renderer/FirRenderer.kt index 9aaf3db99bb..5d2ed27135b 100644 --- a/compiler/fir/tree/src/org/jetbrains/kotlin/fir/renderer/FirRenderer.kt +++ b/compiler/fir/tree/src/org/jetbrains/kotlin/fir/renderer/FirRenderer.kt @@ -839,9 +839,16 @@ class FirRenderer( } print(">") } + if (resolvedNamedReference is FirResolvedErrorReference) { + print("<${resolvedNamedReference.diagnostic.reason}>#") + } print("|") } + override fun visitResolvedErrorReference(resolvedErrorReference: FirResolvedErrorReference) { + visitResolvedNamedReference(resolvedErrorReference) + } + private fun FirBasedSymbol<*>.unwrapIntersectionOverrides(): FirBasedSymbol<*> { (this as? FirCallableSymbol<*>)?.baseForIntersectionOverride?.let { return it.unwrapIntersectionOverrides() } return this diff --git a/compiler/tests-common/tests/org/jetbrains/kotlin/fir/FirResolveBench.kt b/compiler/tests-common/tests/org/jetbrains/kotlin/fir/FirResolveBench.kt index 95685cad9d3..efca8ecbb93 100644 --- a/compiler/tests-common/tests/org/jetbrains/kotlin/fir/FirResolveBench.kt +++ b/compiler/tests-common/tests/org/jetbrains/kotlin/fir/FirResolveBench.kt @@ -11,11 +11,13 @@ import org.jetbrains.kotlin.KtIoFileSourceFile import org.jetbrains.kotlin.fir.builder.RawFirBuilder import org.jetbrains.kotlin.fir.declarations.FirFile import org.jetbrains.kotlin.fir.diagnostics.ConeStubDiagnostic +import org.jetbrains.kotlin.fir.diagnostics.FirDiagnosticHolder import org.jetbrains.kotlin.fir.expressions.FirFunctionCall import org.jetbrains.kotlin.fir.expressions.FirPropertyAccessExpression import org.jetbrains.kotlin.fir.expressions.FirQualifiedAccessExpression import org.jetbrains.kotlin.fir.lightTree.LightTree2Fir import org.jetbrains.kotlin.fir.references.FirErrorNamedReference +import org.jetbrains.kotlin.fir.references.FirResolvedErrorReference import org.jetbrains.kotlin.fir.resolve.providers.firProvider import org.jetbrains.kotlin.fir.resolve.providers.impl.FirProviderImpl import org.jetbrains.kotlin.fir.resolve.transformers.FirGlobalResolveProcessor @@ -281,8 +283,8 @@ class FirResolveBench(val withProgress: Boolean, val listener: BenchListener? = if (type is ConeErrorType) { errorFunctionCallTypes++ val psi = callee.psi - if (callee is FirErrorNamedReference && psi != null) { - reportProblem(callee.diagnostic.reason, psi) + if ((callee is FirErrorNamedReference || callee is FirResolvedErrorReference) && psi != null) { + reportProblem((callee as FirDiagnosticHolder).diagnostic.reason, psi) } } } @@ -298,8 +300,8 @@ class FirResolveBench(val withProgress: Boolean, val listener: BenchListener? = if (type is ConeErrorType) { errorQualifiedAccessTypes++ val psi = callee.psi - if (callee is FirErrorNamedReference && psi != null) { - reportProblem(callee.diagnostic.reason, psi) + if ((callee is FirErrorNamedReference || callee is FirResolvedErrorReference) && psi != null) { + reportProblem((callee as FirDiagnosticHolder).diagnostic.reason, psi) } } } diff --git a/compiler/visualizer/render-fir/src/org/jetbrains/kotlin/compiler/visualizer/FirVisualizer.kt b/compiler/visualizer/render-fir/src/org/jetbrains/kotlin/compiler/visualizer/FirVisualizer.kt index a1463372677..4aad567b505 100644 --- a/compiler/visualizer/render-fir/src/org/jetbrains/kotlin/compiler/visualizer/FirVisualizer.kt +++ b/compiler/visualizer/render-fir/src/org/jetbrains/kotlin/compiler/visualizer/FirVisualizer.kt @@ -11,6 +11,7 @@ import org.jetbrains.kotlin.descriptors.ClassKind import org.jetbrains.kotlin.fir.* import org.jetbrains.kotlin.fir.declarations.* import org.jetbrains.kotlin.fir.declarations.utils.isLocal +import org.jetbrains.kotlin.fir.diagnostics.ConeDiagnostic import org.jetbrains.kotlin.fir.expressions.* import org.jetbrains.kotlin.fir.expressions.impl.FirNoReceiverExpression import org.jetbrains.kotlin.fir.references.* @@ -675,12 +676,16 @@ class FirVisualizer(private val firFile: FirFile) : BaseRenderer() { override fun visitNamedReference(namedReference: FirNamedReference, data: StringBuilder) { if (namedReference is FirErrorNamedReference) { - data.append("[ERROR : ${namedReference.diagnostic.reason}]") + data.append(namedReference.diagnostic.dump()) return } visitElement(namedReference, data) } + private fun ConeDiagnostic.dump(): String { + return "[ERROR : ${reason}]" + } + override fun visitResolvedNamedReference(resolvedNamedReference: FirResolvedNamedReference, data: StringBuilder) { val symbol = resolvedNamedReference.resolvedSymbol renderImplicitReceiver(symbol, resolvedNamedReference.source.psi) @@ -698,6 +703,11 @@ class FirVisualizer(private val firFile: FirFile) : BaseRenderer() { } } + override fun visitResolvedErrorReference(resolvedErrorReference: FirResolvedErrorReference, data: StringBuilder) { + visitResolvedNamedReference(resolvedErrorReference, data) + data.append(resolvedErrorReference.diagnostic.dump()) + } + override fun visitResolvedCallableReference(resolvedCallableReference: FirResolvedCallableReference, data: StringBuilder) { when (val symbol = resolvedCallableReference.resolvedSymbol) { is FirPropertySymbol -> renderPropertySymbol(symbol, data) @@ -772,8 +782,11 @@ class FirVisualizer(private val firFile: FirFile) : BaseRenderer() { is FirConstructorSymbol -> visitConstructor(callee.resolvedSymbol.fir as FirConstructor, data) else -> renderFunctionSymbol(callee.resolvedSymbol as FirNamedFunctionSymbol, data, functionCall) } + if (callee is FirResolvedErrorReference) { + data.append(callee.diagnostic.dump()) + } } - is FirErrorNamedReference -> data.append("[ERROR : ${callee.diagnostic.reason}]") + is FirErrorNamedReference -> data.append(callee.diagnostic.dump()) } } diff --git a/plugins/assign-plugin/assign-plugin.k2/src/org/jetbrains/kotlin/assignment/plugin/k2/diagnostics/FirAssignmentPluginFunctionCallChecker.kt b/plugins/assign-plugin/assign-plugin.k2/src/org/jetbrains/kotlin/assignment/plugin/k2/diagnostics/FirAssignmentPluginFunctionCallChecker.kt index c7f81234cb7..ed5da0b71ce 100644 --- a/plugins/assign-plugin/assign-plugin.k2/src/org/jetbrains/kotlin/assignment/plugin/k2/diagnostics/FirAssignmentPluginFunctionCallChecker.kt +++ b/plugins/assign-plugin/assign-plugin.k2/src/org/jetbrains/kotlin/assignment/plugin/k2/diagnostics/FirAssignmentPluginFunctionCallChecker.kt @@ -16,10 +16,12 @@ import org.jetbrains.kotlin.fir.FirSession import org.jetbrains.kotlin.fir.analysis.checkers.context.CheckerContext import org.jetbrains.kotlin.fir.analysis.checkers.expression.FirFunctionCallChecker import org.jetbrains.kotlin.fir.analysis.checkers.toRegularClassSymbol +import org.jetbrains.kotlin.fir.diagnostics.FirDiagnosticHolder import org.jetbrains.kotlin.fir.expressions.FirFunctionCall import org.jetbrains.kotlin.fir.expressions.arguments import org.jetbrains.kotlin.fir.expressions.toResolvedCallableSymbol import org.jetbrains.kotlin.fir.references.FirErrorNamedReference +import org.jetbrains.kotlin.fir.references.FirResolvedErrorReference import org.jetbrains.kotlin.fir.resolve.diagnostics.ConeAmbiguityError import org.jetbrains.kotlin.fir.resolve.diagnostics.ConeDiagnosticWithSingleCandidate import org.jetbrains.kotlin.fir.resolve.diagnostics.ConeUnresolvedNameError @@ -42,10 +44,13 @@ object FirAssignmentPluginFunctionCallChecker : FirFunctionCallChecker() { private fun FirFunctionCall.isOverloadAssignCallCandidate() = arguments.size == 1 && source?.kind == KtFakeSourceElementKind.DesugaredCompoundAssignment - private fun FirFunctionCall.isFunctionResolveError() = calleeReference is FirErrorNamedReference + private fun FirFunctionCall.isFunctionResolveError() = when(calleeReference){ + is FirErrorNamedReference, is FirResolvedErrorReference -> true + else -> false + } private fun FirFunctionCall.isOverloadedAssignCallError(session: FirSession): Boolean { - val functionName = when (val diagnostic = (calleeReference as? FirErrorNamedReference)?.diagnostic) { + val functionName = when (val diagnostic = (calleeReference as? FirDiagnosticHolder)?.diagnostic) { is ConeAmbiguityError -> diagnostic.name is ConeDiagnosticWithSingleCandidate -> diagnostic.candidate.callInfo.name is ConeUnresolvedNameError -> diagnostic.name