From 7b45f7521398fd256f7b1ff355cab8ca2f43723a Mon Sep 17 00:00:00 2001 From: Nikolay Lunyak Date: Wed, 10 May 2023 15:40:46 +0300 Subject: [PATCH] [FIR] KT-58523: Check the companion presence when resolving type-aliases The change in `QualifiedNameResolution.kt` is backed by `starImportOnTypeAlias.fir.kt` and `javaStaticMembersViaTypeAlias.fir.kt`. Note that referencing inner classes via type-aliases is prohibited, but referencing enum entries is not. ^KT-58523 Fixed --- .../diagnostics/FirDiagnosticsList.kt | 2 +- .../fir/analysis/diagnostics/FirErrors.kt | 2 +- .../coneDiagnosticToFirDiagnostic.kt | 4 +- .../kotlin/fir/QualifiedNameResolution.kt | 60 ++++++++++--------- .../fir/resolve/calls/CandidateFactory.kt | 13 ++-- ...olutionToTypealiasInsteadOfProperty.fir.kt | 18 ------ .../resolutionToTypealiasInsteadOfProperty.kt | 1 + 7 files changed, 45 insertions(+), 55 deletions(-) delete mode 100644 compiler/testData/diagnostics/tests/resolutionToTypealiasInsteadOfProperty.fir.kt diff --git a/compiler/fir/checkers/checkers-component-generator/src/org/jetbrains/kotlin/fir/checkers/generator/diagnostics/FirDiagnosticsList.kt b/compiler/fir/checkers/checkers-component-generator/src/org/jetbrains/kotlin/fir/checkers/generator/diagnostics/FirDiagnosticsList.kt index 535fca95ca1..1858401c809 100644 --- a/compiler/fir/checkers/checkers-component-generator/src/org/jetbrains/kotlin/fir/checkers/generator/diagnostics/FirDiagnosticsList.kt +++ b/compiler/fir/checkers/checkers-component-generator/src/org/jetbrains/kotlin/fir/checkers/generator/diagnostics/FirDiagnosticsList.kt @@ -1284,7 +1284,7 @@ object DIAGNOSTICS_LIST : DiagnosticList("FirErrors") { parameter("typeParameter") } val NO_COMPANION_OBJECT by error(PositioningStrategy.SELECTOR_BY_QUALIFIED) { - parameter("klass") + parameter>("klass") } val EXPRESSION_EXPECTED_PACKAGE_FOUND by error(PositioningStrategy.SELECTOR_BY_QUALIFIED) } diff --git a/compiler/fir/checkers/gen/org/jetbrains/kotlin/fir/analysis/diagnostics/FirErrors.kt b/compiler/fir/checkers/gen/org/jetbrains/kotlin/fir/analysis/diagnostics/FirErrors.kt index e1eca6d78cd..dac5b55dccc 100644 --- a/compiler/fir/checkers/gen/org/jetbrains/kotlin/fir/analysis/diagnostics/FirErrors.kt +++ b/compiler/fir/checkers/gen/org/jetbrains/kotlin/fir/analysis/diagnostics/FirErrors.kt @@ -671,7 +671,7 @@ object FirErrors { // Context tracking val TYPE_PARAMETER_IS_NOT_AN_EXPRESSION by error1() val TYPE_PARAMETER_ON_LHS_OF_DOT by error1() - val NO_COMPANION_OBJECT by error1(SourceElementPositioningStrategies.SELECTOR_BY_QUALIFIED) + val NO_COMPANION_OBJECT by error1>(SourceElementPositioningStrategies.SELECTOR_BY_QUALIFIED) val EXPRESSION_EXPECTED_PACKAGE_FOUND by error0(SourceElementPositioningStrategies.SELECTOR_BY_QUALIFIED) // Function contracts 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 546b0094416..2cd707548e8 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 @@ -25,8 +25,8 @@ import org.jetbrains.kotlin.fir.resolve.inference.model.ConeExpectedTypeConstrai import org.jetbrains.kotlin.fir.resolve.inference.model.ConeLambdaArgumentConstraintPosition import org.jetbrains.kotlin.fir.symbols.ConeTypeParameterLookupTag import org.jetbrains.kotlin.fir.symbols.impl.FirCallableSymbol +import org.jetbrains.kotlin.fir.symbols.impl.FirClassLikeSymbol import org.jetbrains.kotlin.fir.symbols.impl.FirNamedFunctionSymbol -import org.jetbrains.kotlin.fir.symbols.impl.FirRegularClassSymbol import org.jetbrains.kotlin.fir.types.* import org.jetbrains.kotlin.lexer.KtTokens import org.jetbrains.kotlin.name.SpecialNames @@ -64,7 +64,7 @@ private fun ConeDiagnostic.toKtDiagnostic( is ConeVisibilityError -> FirErrors.INVISIBLE_REFERENCE.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 as FirRegularClassSymbol) + is ConeNoCompanionObject -> FirErrors.NO_COMPANION_OBJECT.createOn(source, this.candidateSymbol as FirClassLikeSymbol<*>) is ConeAmbiguityError -> when { applicability.isSuccess -> FirErrors.OVERLOAD_RESOLUTION_AMBIGUITY.createOn(source, this.candidates.map { it.symbol }) applicability == CandidateApplicability.UNSAFE_CALL -> { diff --git a/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/QualifiedNameResolution.kt b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/QualifiedNameResolution.kt index 3da6a5b45b5..528b4b82a51 100644 --- a/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/QualifiedNameResolution.kt +++ b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/QualifiedNameResolution.kt @@ -7,7 +7,9 @@ package org.jetbrains.kotlin.fir import org.jetbrains.kotlin.KtSourceElement import org.jetbrains.kotlin.config.ApiVersion +import org.jetbrains.kotlin.descriptors.ClassKind import org.jetbrains.kotlin.fir.declarations.FirClass +import org.jetbrains.kotlin.fir.declarations.fullyExpandedClass import org.jetbrains.kotlin.fir.diagnostics.ConeDiagnostic import org.jetbrains.kotlin.fir.expressions.FirExpression import org.jetbrains.kotlin.fir.expressions.FirResolvedQualifier @@ -21,6 +23,7 @@ import org.jetbrains.kotlin.fir.resolve.transformers.body.resolve.resultType import org.jetbrains.kotlin.fir.resolve.typeForQualifier import org.jetbrains.kotlin.fir.symbols.impl.FirClassLikeSymbol import org.jetbrains.kotlin.fir.symbols.impl.FirRegularClassSymbol +import org.jetbrains.kotlin.fir.symbols.impl.FirTypeAliasSymbol import org.jetbrains.kotlin.fir.types.FirTypeProjection import org.jetbrains.kotlin.name.ClassId import org.jetbrains.kotlin.name.FqName @@ -47,35 +50,36 @@ fun BodyResolveComponents.resolveRootPartOfQualifier( for (scope in createCurrentScopeList()) { scope.getSingleVisibleClassifier(session, this, name)?.let { - if (it is FirRegularClassSymbol) { - val isVisible = session.visibilityChecker.isClassLikeVisible( - it.fir, - session, - file, - containingDeclarations, - ) - if (!isVisible) { - return@let - } - val classId = it.classId - return buildResolvedQualifier { - this.source = source - packageFqName = classId.packageFqName - relativeClassFqName = classId.relativeClassName - symbol = it - this.typeArguments.addAll(typeArguments) - this.nonFatalDiagnostics.addAll( - extractNonFatalDiagnostics( - source, - explicitReceiver = null, - it, - extraNotFatalDiagnostics = nonFatalDiagnosticsFromExpression, - session.languageVersionSettings.apiVersion - ) + val klass = (it as? FirClassLikeSymbol<*>)?.fullyExpandedClass(session) + ?: return@let + + val isVisible = session.visibilityChecker.isClassLikeVisible( + klass.fir, + session, + file, + containingDeclarations, + ) + if (!isVisible) { + return@let + } + val classId = it.classId + return buildResolvedQualifier { + this.source = source + packageFqName = classId.packageFqName + relativeClassFqName = classId.relativeClassName + symbol = it + this.typeArguments.addAll(typeArguments) + this.nonFatalDiagnostics.addAll( + extractNonFatalDiagnostics( + source, + explicitReceiver = null, + it, + extraNotFatalDiagnostics = nonFatalDiagnosticsFromExpression, + session.languageVersionSettings.apiVersion ) - }.apply { - resultType = typeForQualifier(this) - } + ) + }.apply { + resultType = typeForQualifier(this) } } } diff --git a/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/calls/CandidateFactory.kt b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/calls/CandidateFactory.kt index 54bc3eb2c93..2c3779d999d 100644 --- a/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/calls/CandidateFactory.kt +++ b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/calls/CandidateFactory.kt @@ -6,11 +6,13 @@ package org.jetbrains.kotlin.fir.resolve.calls import org.jetbrains.kotlin.descriptors.ClassKind +import org.jetbrains.kotlin.fir.FirSession import org.jetbrains.kotlin.fir.declarations.FirDeclarationOrigin import org.jetbrains.kotlin.fir.declarations.FirRegularClass import org.jetbrains.kotlin.fir.declarations.FirResolvePhase import org.jetbrains.kotlin.fir.declarations.builder.buildErrorFunction import org.jetbrains.kotlin.fir.declarations.builder.buildErrorProperty +import org.jetbrains.kotlin.fir.declarations.fullyExpandedClass import org.jetbrains.kotlin.fir.diagnostics.ConeDiagnostic import org.jetbrains.kotlin.fir.expressions.* import org.jetbrains.kotlin.fir.moduleData @@ -86,11 +88,7 @@ class CandidateFactory private constructor( if (symbol is FirValueParameterSymbol || symbol is FirPropertySymbol && symbol.isLocal || symbol is FirBackingFieldSymbol) { result.addDiagnostic(Unsupported("References to variables aren't supported yet", callSite.calleeReference.source)) } - } else if (objectsByName && - symbol is FirRegularClassSymbol && - symbol.classKind != ClassKind.OBJECT && - symbol.companionObjectSymbol == null - ) { + } else if (objectsByName && symbol.isRegularClassWithoutCompanion(callInfo.session)) { result.addDiagnostic(NoCompanionObject) } if (callInfo.origin == FirFunctionCallOrigin.Operator && symbol is FirPropertySymbol) { @@ -100,6 +98,11 @@ class CandidateFactory private constructor( return result } + private fun FirBasedSymbol<*>.isRegularClassWithoutCompanion(session: FirSession): Boolean { + val referencedClass = (this as? FirClassLikeSymbol<*>)?.fullyExpandedClass(session) ?: return false + return referencedClass.classKind != ClassKind.OBJECT && referencedClass.companionObjectSymbol == null + } + private fun FirBasedSymbol<*>.unwrapIntegerOperatorSymbolIfNeeded(callInfo: CallInfo): FirBasedSymbol<*> { if (this !is FirNamedFunctionSymbol) return this // There is no need to unwrap unary operators diff --git a/compiler/testData/diagnostics/tests/resolutionToTypealiasInsteadOfProperty.fir.kt b/compiler/testData/diagnostics/tests/resolutionToTypealiasInsteadOfProperty.fir.kt deleted file mode 100644 index c2040427ce4..00000000000 --- a/compiler/testData/diagnostics/tests/resolutionToTypealiasInsteadOfProperty.fir.kt +++ /dev/null @@ -1,18 +0,0 @@ -// ISSUE: KT-58523 - -// FILE: pkg.kt - -package pkg - -class Klass -typealias ItemKey = Klass - -// FILE: main.kt - -import pkg.ItemKey - -val ItemKey = 42 - -fun main() { - ItemKey // K1: ok, K2: NO_COMPANION_OBJECT -} diff --git a/compiler/testData/diagnostics/tests/resolutionToTypealiasInsteadOfProperty.kt b/compiler/testData/diagnostics/tests/resolutionToTypealiasInsteadOfProperty.kt index c0563cc0dbc..4b90ff85eb6 100644 --- a/compiler/testData/diagnostics/tests/resolutionToTypealiasInsteadOfProperty.kt +++ b/compiler/testData/diagnostics/tests/resolutionToTypealiasInsteadOfProperty.kt @@ -1,3 +1,4 @@ +// FIR_IDENTICAL // ISSUE: KT-58523 // FILE: pkg.kt