diff --git a/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/checkers/expression/FirDeprecatedQualifierChecker.kt b/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/checkers/expression/FirDeprecatedQualifierChecker.kt index 0a8e62cecd5..f1ee45a7f42 100644 --- a/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/checkers/expression/FirDeprecatedQualifierChecker.kt +++ b/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/checkers/expression/FirDeprecatedQualifierChecker.kt @@ -14,7 +14,7 @@ import org.jetbrains.kotlin.fir.symbols.impl.FirRegularClassSymbol object FirDeprecatedQualifierChecker : FirResolvedQualifierChecker() { override fun check(expression: FirResolvedQualifier, context: CheckerContext, reporter: DiagnosticReporter) { expression.nonFatalDiagnostics.filterIsInstance().forEach { diagnostic -> - FirDeprecationChecker.reportDeprecation(diagnostic.source, diagnostic.symbol, diagnostic.deprecation, reporter, context) + FirDeprecationChecker.reportDeprecation(diagnostic.source, diagnostic.candidateSymbol, diagnostic.deprecation, reporter, context) } if (expression.resolvedToCompanionObject) { val companionSymbol = (expression.symbol as? FirRegularClassSymbol)?.companionObjectSymbol ?: return diff --git a/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/diagnostics/coneDiagnosticToFirDiagnostic.kt b/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/diagnostics/coneDiagnosticToFirDiagnostic.kt index 6711886276d..08c051e3615 100644 --- a/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/diagnostics/coneDiagnosticToFirDiagnostic.kt +++ b/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/diagnostics/coneDiagnosticToFirDiagnostic.kt @@ -42,10 +42,10 @@ private fun ConeDiagnostic.toFirDiagnostic( is ConeUnresolvedQualifierError -> FirErrors.UNRESOLVED_REFERENCE.createOn(source, this.qualifier) is ConeFunctionCallExpectedError -> FirErrors.FUNCTION_CALL_EXPECTED.createOn(source, this.name.asString(), this.hasValueParameters) is ConeFunctionExpectedError -> FirErrors.FUNCTION_EXPECTED.createOn(source, this.expression, this.type) - is ConeResolutionToClassifierError -> FirErrors.RESOLUTION_TO_CLASSIFIER.createOn(source, this.classSymbol) + is ConeResolutionToClassifierError -> FirErrors.RESOLUTION_TO_CLASSIFIER.createOn(source, this.candidateSymbol) is ConeHiddenCandidateError -> FirErrors.INVISIBLE_REFERENCE.createOn(source, this.candidateSymbol) - is ConeInapplicableWrongReceiver -> FirErrors.UNRESOLVED_REFERENCE_WRONG_RECEIVER.createOn(source, this.candidates) - is ConeNoCompanionObject -> FirErrors.NO_COMPANION_OBJECT.createOn(source, this.symbol) + is ConeInapplicableWrongReceiver -> FirErrors.UNRESOLVED_REFERENCE_WRONG_RECEIVER.createOn(source, this.candidateSymbols) + is ConeNoCompanionObject -> FirErrors.NO_COMPANION_OBJECT.createOn(source, this.candidateSymbol) is ConeAmbiguityError -> when { applicability.isSuccess -> FirErrors.OVERLOAD_RESOLUTION_AMBIGUITY.createOn(source, this.candidates.map { it.symbol }) applicability == CandidateApplicability.UNSAFE_CALL -> { @@ -65,7 +65,7 @@ private fun ConeDiagnostic.toFirDiagnostic( } else -> FirErrors.NONE_APPLICABLE.createOn(source, this.candidates.map { it.symbol }) } - is ConeOperatorAmbiguityError -> FirErrors.ASSIGN_OPERATOR_AMBIGUITY.createOn(source, this.candidates) + is ConeOperatorAmbiguityError -> FirErrors.ASSIGN_OPERATOR_AMBIGUITY.createOn(source, this.candidateSymbols) is ConeVariableExpectedError -> FirErrors.VARIABLE_EXPECTED.createOn(source) is ConeValReassignmentError -> when (val symbol = this.variable) { is FirBackingFieldSymbol -> FirErrors.VAL_REASSIGNMENT_VIA_BACKING_FIELD.errorFactory.createOn(source, symbol) @@ -74,11 +74,11 @@ private fun ConeDiagnostic.toFirDiagnostic( is ConeUnexpectedTypeArgumentsError -> FirErrors.TYPE_ARGUMENTS_NOT_ALLOWED.createOn(this.source ?: source) is ConeIllegalAnnotationError -> FirErrors.NOT_AN_ANNOTATION_CLASS.createOn(source, this.name.asString()) is ConeWrongNumberOfTypeArgumentsError -> - FirErrors.WRONG_NUMBER_OF_TYPE_ARGUMENTS.createOn(this.source, this.desiredCount, this.symbol) + FirErrors.WRONG_NUMBER_OF_TYPE_ARGUMENTS.createOn(this.source, this.desiredCount, this.candidateSymbol) is ConeOuterClassArgumentsRequired -> FirErrors.OUTER_CLASS_ARGUMENTS_REQUIRED.createOn(qualifiedAccessSource ?: source, this.symbol) is ConeNoTypeArgumentsOnRhsError -> - FirErrors.NO_TYPE_ARGUMENTS_ON_RHS.createOn(qualifiedAccessSource ?: source, this.desiredCount, this.symbol) + FirErrors.NO_TYPE_ARGUMENTS_ON_RHS.createOn(qualifiedAccessSource ?: source, this.desiredCount, this.candidateSymbol) is ConeSimpleDiagnostic -> when { source.kind is FirFakeSourceElementKind && source.kind != FirFakeSourceElementKind.ReferenceInAtomicQualifiedAccess -> null else -> this.getFactory(source).createOn(qualifiedAccessSource ?: source) @@ -186,7 +186,10 @@ private fun mapInapplicableCandidateError( is NonVarargSpread -> FirErrors.NON_VARARG_SPREAD.createOn(rootCause.argument.source?.getChild(KtTokens.MUL, depth = 1)!!) is ArgumentPassedTwice -> FirErrors.ARGUMENT_PASSED_TWICE.createOn(rootCause.argument.source) is TooManyArguments -> FirErrors.TOO_MANY_ARGUMENTS.createOn(rootCause.argument.source ?: source, rootCause.function.symbol) - is NoValueForParameter -> FirErrors.NO_VALUE_FOR_PARAMETER.createOn(qualifiedAccessSource ?: source, rootCause.valueParameter.symbol) + is NoValueForParameter -> FirErrors.NO_VALUE_FOR_PARAMETER.createOn( + qualifiedAccessSource ?: source, + rootCause.valueParameter.symbol + ) is NameNotFound -> FirErrors.NAMED_PARAMETER_NOT_FOUND.createOn( rootCause.argument.source ?: source, rootCause.argument.name.asString() diff --git a/compiler/fir/cones/src/org/jetbrains/kotlin/fir/diagnostics/ConeDiagnostic.kt b/compiler/fir/cones/src/org/jetbrains/kotlin/fir/diagnostics/ConeDiagnostic.kt index f8f4e967917..a8b5cb5ce46 100644 --- a/compiler/fir/cones/src/org/jetbrains/kotlin/fir/diagnostics/ConeDiagnostic.kt +++ b/compiler/fir/cones/src/org/jetbrains/kotlin/fir/diagnostics/ConeDiagnostic.kt @@ -5,10 +5,10 @@ package org.jetbrains.kotlin.fir.diagnostics -abstract class ConeDiagnostic { - abstract val reason: String +interface ConeDiagnostic { + val reason: String } -class ConeStubDiagnostic(val original: ConeDiagnostic) : ConeDiagnostic() { +class ConeStubDiagnostic(val original: ConeDiagnostic) : ConeDiagnostic { override val reason: String get() = original.reason } \ No newline at end of file diff --git a/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/diagnostics/FirDiagnostics.kt b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/diagnostics/FirDiagnostics.kt index 8a1fc636c37..d9bfe8b8a70 100644 --- a/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/diagnostics/FirDiagnostics.kt +++ b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/diagnostics/FirDiagnostics.kt @@ -22,115 +22,127 @@ import org.jetbrains.kotlin.name.ClassId import org.jetbrains.kotlin.name.Name import org.jetbrains.kotlin.resolve.calls.tower.CandidateApplicability -sealed class ConeUnresolvedError : ConeDiagnostic() { - abstract val qualifier: String? +sealed interface ConeUnresolvedError : ConeDiagnostic { + val qualifier: String? } -class ConeUnresolvedReferenceError(val name: Name? = null) : ConeUnresolvedError() { +interface ConeDiagnosticWithCandidates : ConeDiagnostic { + val candidateSymbols: Collection> +} + +interface ConeDiagnosticWithSingleCandidate : ConeDiagnosticWithCandidates { + override val candidateSymbols: Collection> get() = listOf(candidateSymbol) + val candidateSymbol: FirBasedSymbol<*> +} + +class ConeUnresolvedReferenceError(val name: Name? = null) : ConeUnresolvedError { override val qualifier: String? get() = name?.asString() override val reason: String get() = "Unresolved reference" + if (name != null) ": ${name.asString()}" else "" } -class ConeUnresolvedSymbolError(val classId: ClassId) : ConeUnresolvedError() { +class ConeUnresolvedSymbolError(val classId: ClassId) : ConeUnresolvedError { override val qualifier: String get() = classId.asSingleFqName().asString() override val reason: String get() = "Symbol not found for $classId" } -class ConeUnresolvedQualifierError(override val qualifier: String) : ConeUnresolvedError() { +class ConeUnresolvedQualifierError(override val qualifier: String) : ConeUnresolvedError { override val reason: String get() = "Symbol not found for $qualifier" } -class ConeUnresolvedNameError(val name: Name) : ConeUnresolvedError() { +class ConeUnresolvedNameError(val name: Name) : ConeUnresolvedError { override val qualifier: String get() = name.asString() override val reason: String get() = "Unresolved name: $name" } -class ConeFunctionCallExpectedError(val name: Name, val hasValueParameters: Boolean) : ConeDiagnostic() { +class ConeFunctionCallExpectedError(val name: Name, val hasValueParameters: Boolean) : ConeDiagnostic { override val reason: String get() = "Function call expected: $name(${if (hasValueParameters) "..." else ""})" } -class ConeFunctionExpectedError(val expression: String, val type: ConeKotlinType) : ConeDiagnostic() { +class ConeFunctionExpectedError(val expression: String, val type: ConeKotlinType) : ConeDiagnostic { override val reason: String get() = "Expression '$expression' of type '$type' cannot be invoked as a function" } -class ConeResolutionToClassifierError(val classSymbol: FirRegularClassSymbol) : ConeDiagnostic() { +class ConeResolutionToClassifierError(override val candidateSymbol: FirRegularClassSymbol) : ConeDiagnosticWithSingleCandidate { override val reason: String get() = "Resolution to classifier" } class ConeHiddenCandidateError( - val candidateSymbol: FirBasedSymbol<*> -) : ConeDiagnostic() { + override val candidateSymbol: FirBasedSymbol<*> +) : ConeDiagnosticWithSingleCandidate { override val reason: String get() = "HIDDEN: ${describeSymbol(candidateSymbol)} is invisible" } -class ConeInapplicableWrongReceiver(val candidates: Collection>) : ConeDiagnostic() { +class ConeInapplicableWrongReceiver(override val candidateSymbols: Collection>) : ConeDiagnosticWithCandidates { override val reason: String get() = "None of the following candidates is applicable because of receiver type mismatch: ${ - candidates.map { - describeSymbol( - it - ) - } + candidateSymbols.map { describeSymbol(it) } }" } class ConeInapplicableCandidateError( val applicability: CandidateApplicability, val candidate: Candidate, -) : ConeDiagnostic() { - override val reason: String get() = "Inapplicable($applicability): ${describeSymbol(candidate.symbol)}" +) : ConeDiagnosticWithSingleCandidate { + override val reason: String get() = "Inapplicable($applicability): ${describeSymbol(candidateSymbol)}" + override val candidateSymbol: FirBasedSymbol<*> get() = candidate.symbol } class ConeNoCompanionObject( - val symbol: FirRegularClassSymbol -) : ConeDiagnostic() { - override val reason: String get() = "Classifier ''$symbol'' does not have a companion object, and thus must be initialized here" + override val candidateSymbol: FirRegularClassSymbol +) : ConeDiagnosticWithSingleCandidate { + override val reason: String + get() = "Classifier ''$candidateSymbol'' does not have a companion object, and thus must be initialized here" } class ConeConstraintSystemHasContradiction( val candidate: Candidate, -) : ConeDiagnostic() { - override val reason: String get() = "CS errors: ${describeSymbol(candidate.symbol)}" +) : ConeDiagnosticWithSingleCandidate { + override val reason: String get() = "CS errors: ${describeSymbol(candidateSymbol)}" + override val candidateSymbol: FirBasedSymbol<*> get() = candidate.symbol } class ConeArgumentTypeMismatchCandidateError( val expectedType: ConeKotlinType, val actualType: ConeKotlinType -) : ConeDiagnostic() { +) : ConeDiagnostic { override val reason: String get() = "Type mismatch. Expected: $expectedType, Actual: $actualType" } -class ConeAmbiguityError(val name: Name, val applicability: CandidateApplicability, val candidates: Collection) : - ConeDiagnostic() { - override val reason: String get() = "Ambiguity: $name, ${candidates.map { describeSymbol(it.symbol) }}" +class ConeAmbiguityError( + val name: Name, + val applicability: CandidateApplicability, + val candidates: Collection +) : ConeDiagnosticWithCandidates { + override val reason: String get() = "Ambiguity: $name, ${candidateSymbols.map { describeSymbol(it) }}" + override val candidateSymbols: Collection> get() = candidates.map { it.symbol } } -class ConeOperatorAmbiguityError(val candidates: Collection>) : ConeDiagnostic() { - override val reason: String get() = "Operator overload ambiguity. Compatible candidates: ${candidates.map { describeSymbol(it) }}" +class ConeOperatorAmbiguityError(override val candidateSymbols: Collection>) : ConeDiagnosticWithCandidates { + override val reason: String get() = "Operator overload ambiguity. Compatible candidates: ${candidateSymbols.map { describeSymbol(it) }}" } -class ConeVariableExpectedError : ConeDiagnostic() { +class ConeVariableExpectedError : ConeDiagnostic { override val reason: String get() = "Variable expected" } -class ConeValReassignmentError(val variable: FirVariableSymbol<*>) : ConeDiagnostic() { +class ConeValReassignmentError(val variable: FirVariableSymbol<*>) : ConeDiagnostic { override val reason: String get() = "Re-assigning a val variable" } -class ConeContractDescriptionError(override val reason: String) : ConeDiagnostic() +class ConeContractDescriptionError(override val reason: String) : ConeDiagnostic -class ConeIllegalAnnotationError(val name: Name) : ConeDiagnostic() { +class ConeIllegalAnnotationError(val name: Name) : ConeDiagnostic { override val reason: String get() = "Not a legal annotation: $name" } -interface ConeUnmatchedTypeArgumentsError { +interface ConeUnmatchedTypeArgumentsError : ConeDiagnosticWithSingleCandidate { val desiredCount: Int - val symbol: FirClassLikeSymbol<*> + override val candidateSymbol: FirClassLikeSymbol<*> } class ConeWrongNumberOfTypeArgumentsError( override val desiredCount: Int, - override val symbol: FirRegularClassSymbol, + override val candidateSymbol: FirRegularClassSymbol, source: FirSourceElement ) : ConeDiagnosticWithSource(source), ConeUnmatchedTypeArgumentsError { override val reason: String get() = "Wrong number of type arguments" @@ -138,52 +150,55 @@ class ConeWrongNumberOfTypeArgumentsError( class ConeNoTypeArgumentsOnRhsError( override val desiredCount: Int, - override val symbol: FirClassLikeSymbol<*> -) : ConeDiagnostic(), ConeUnmatchedTypeArgumentsError { + override val candidateSymbol: FirClassLikeSymbol<*> +) : ConeUnmatchedTypeArgumentsError { override val reason: String get() = "No type arguments on RHS" } class ConeOuterClassArgumentsRequired( val symbol: FirRegularClassSymbol, -) : ConeDiagnostic() { +) : ConeDiagnostic { override val reason: String = "Type arguments should be specified for an outer class" } -class ConeInstanceAccessBeforeSuperCall(val target: String) : ConeDiagnostic() { +class ConeInstanceAccessBeforeSuperCall(val target: String) : ConeDiagnostic { override val reason: String get() = "Cannot access ''${target}'' before superclass constructor has been called" } -class ConeUnsupportedCallableReferenceTarget(val fir: FirCallableDeclaration) : ConeDiagnostic() { +class ConeUnsupportedCallableReferenceTarget(val fir: FirCallableDeclaration) : ConeDiagnosticWithSingleCandidate { override val reason: String get() = "Unsupported declaration for callable reference: ${fir.render()}" + override val candidateSymbol: FirBasedSymbol<*> get() = fir.symbol } -class ConeTypeParameterSupertype(val symbol: FirTypeParameterSymbol) : ConeDiagnostic() { +class ConeTypeParameterSupertype(val symbol: FirTypeParameterSymbol) : ConeDiagnostic { override val reason: String get() = "Type parameter ${symbol.fir.name} cannot be a supertype" } -class ConeTypeParameterInQualifiedAccess(val symbol: FirTypeParameterSymbol) : ConeDiagnostic() { +class ConeTypeParameterInQualifiedAccess(val symbol: FirTypeParameterSymbol) : ConeDiagnostic { override val reason: String get() = "Type parameter ${symbol.fir.name} in qualified access" } -class ConeCyclicTypeBound(val symbol: FirTypeParameterSymbol, val bounds: ImmutableList) : ConeDiagnostic() { +class ConeCyclicTypeBound(val symbol: FirTypeParameterSymbol, val bounds: ImmutableList) : ConeDiagnostic { override val reason: String get() = "Type parameter ${symbol.fir.name} has cyclic bounds" } -class ConeImportFromSingleton(val name: Name) : ConeDiagnostic() { +class ConeImportFromSingleton(val name: Name) : ConeDiagnostic { override val reason: String get() = "Import from singleton $name is not allowed" } -open class ConeUnsupported(val message: String, val source: FirSourceElement? = null) : ConeDiagnostic() { - override val reason: String get() = message -} +open class ConeUnsupported(override val reason: String, val source: FirSourceElement? = null) : ConeDiagnostic class ConeUnsupportedDynamicType : ConeUnsupported("Dynamic types are not supported in this context") -class ConeDeprecated(val source: FirSourceElement?, val symbol: FirBasedSymbol<*>, val deprecation: Deprecation) : ConeDiagnostic() { +class ConeDeprecated( + val source: FirSourceElement?, + override val candidateSymbol: FirBasedSymbol<*>, + val deprecation: Deprecation +) : ConeDiagnosticWithSingleCandidate { override val reason: String get() = "Deprecated: ${deprecation.message}" } -class ConeLocalVariableNoTypeOrInitializer(val variable: FirVariable) : ConeDiagnostic() { +class ConeLocalVariableNoTypeOrInitializer(val variable: FirVariable) : ConeDiagnostic { override val reason: String get() = "Cannot infer variable type without initializer / getter / delegate" } diff --git a/compiler/fir/tree/src/org/jetbrains/kotlin/fir/diagnostics/CommonDiagnostics.kt b/compiler/fir/tree/src/org/jetbrains/kotlin/fir/diagnostics/CommonDiagnostics.kt index e3ba576f5fc..b4223893555 100644 --- a/compiler/fir/tree/src/org/jetbrains/kotlin/fir/diagnostics/CommonDiagnostics.kt +++ b/compiler/fir/tree/src/org/jetbrains/kotlin/fir/diagnostics/CommonDiagnostics.kt @@ -7,6 +7,6 @@ package org.jetbrains.kotlin.fir.diagnostics import org.jetbrains.kotlin.fir.FirSourceElement -class ConeUnexpectedTypeArgumentsError(override val reason: String, val source: FirSourceElement? = null) : ConeDiagnostic() +class ConeUnexpectedTypeArgumentsError(override val reason: String, val source: FirSourceElement? = null) : ConeDiagnostic -class ConeIntermediateDiagnostic(override val reason: String) : ConeDiagnostic() +class ConeIntermediateDiagnostic(override val reason: String) : ConeDiagnostic diff --git a/compiler/fir/tree/src/org/jetbrains/kotlin/fir/diagnostics/ConeSimpleDiagnostic.kt b/compiler/fir/tree/src/org/jetbrains/kotlin/fir/diagnostics/ConeSimpleDiagnostic.kt index 0156ee8cb60..65e7845aad4 100644 --- a/compiler/fir/tree/src/org/jetbrains/kotlin/fir/diagnostics/ConeSimpleDiagnostic.kt +++ b/compiler/fir/tree/src/org/jetbrains/kotlin/fir/diagnostics/ConeSimpleDiagnostic.kt @@ -7,13 +7,13 @@ package org.jetbrains.kotlin.fir.diagnostics import org.jetbrains.kotlin.fir.FirSourceElement -class ConeSimpleDiagnostic(override val reason: String, val kind: DiagnosticKind = DiagnosticKind.Other) : ConeDiagnostic() +class ConeSimpleDiagnostic(override val reason: String, val kind: DiagnosticKind = DiagnosticKind.Other) : ConeDiagnostic -class ConeNotAnnotationContainer(val text: String) : ConeDiagnostic() { +class ConeNotAnnotationContainer(val text: String) : ConeDiagnostic { override val reason: String get() = "Strange annotated expression: $text" } -abstract class ConeDiagnosticWithSource(val source: FirSourceElement) : ConeDiagnostic() +abstract class ConeDiagnosticWithSource(val source: FirSourceElement) : ConeDiagnostic class ConeUnderscoreIsReserved(source: FirSourceElement) : ConeDiagnosticWithSource(source) { override val reason: String get() = "Names _, __, ___, ..., are reserved in Kotlin" diff --git a/idea/idea-frontend-fir/src/org/jetbrains/kotlin/idea/fir/FirUtils.kt b/idea/idea-frontend-fir/src/org/jetbrains/kotlin/idea/fir/FirUtils.kt index 0b13303b9a8..bee4e13a247 100644 --- a/idea/idea-frontend-fir/src/org/jetbrains/kotlin/idea/fir/FirUtils.kt +++ b/idea/idea-frontend-fir/src/org/jetbrains/kotlin/idea/fir/FirUtils.kt @@ -47,16 +47,6 @@ internal fun FirNamedReference.getCandidateSymbols(): Collection> = when (this) { - is ConeInapplicableCandidateError -> listOf(candidate.symbol) - is ConeHiddenCandidateError -> listOf(candidateSymbol) - is ConeAmbiguityError -> candidates.map { it.symbol } - is ConeOperatorAmbiguityError -> candidates - is ConeUnsupportedCallableReferenceTarget -> listOf(fir.symbol) - is ConeUnmatchedTypeArgumentsError -> listOf(symbol) - is ConeConstraintSystemHasContradiction -> listOf(candidate.symbol) - is ConeDeprecated -> listOf(symbol) - is ConeNoTypeArgumentsOnRhsError -> listOf(symbol) - is ConeResolutionToClassifierError -> listOf(classSymbol) - is ConeWrongNumberOfTypeArgumentsError -> listOf(symbol) + is ConeDiagnosticWithCandidates -> candidateSymbols else -> emptyList() } \ No newline at end of file diff --git a/idea/idea-frontend-fir/src/org/jetbrains/kotlin/idea/references/FirReferenceResolveHelper.kt b/idea/idea-frontend-fir/src/org/jetbrains/kotlin/idea/references/FirReferenceResolveHelper.kt index e74f5ec214a..b9caa913b4a 100644 --- a/idea/idea-frontend-fir/src/org/jetbrains/kotlin/idea/references/FirReferenceResolveHelper.kt +++ b/idea/idea-frontend-fir/src/org/jetbrains/kotlin/idea/references/FirReferenceResolveHelper.kt @@ -56,7 +56,7 @@ internal object FirReferenceResolveHelper { val symbol = resolvedSymbol ?: run { val diagnostic = (this as? FirErrorTypeRef)?.diagnostic - (diagnostic as? ConeUnmatchedTypeArgumentsError)?.symbol + (diagnostic as? ConeUnmatchedTypeArgumentsError)?.candidateSymbol } return symbol?.fir?.buildSymbol(symbolBuilder)