[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
This commit is contained in:
Nikolay Lunyak
2023-05-10 15:40:46 +03:00
committed by Space Team
parent 99ff36c77a
commit 7b45f75213
7 changed files with 45 additions and 55 deletions
@@ -1284,7 +1284,7 @@ object DIAGNOSTICS_LIST : DiagnosticList("FirErrors") {
parameter<FirTypeParameterSymbol>("typeParameter") parameter<FirTypeParameterSymbol>("typeParameter")
} }
val NO_COMPANION_OBJECT by error<KtExpression>(PositioningStrategy.SELECTOR_BY_QUALIFIED) { val NO_COMPANION_OBJECT by error<KtExpression>(PositioningStrategy.SELECTOR_BY_QUALIFIED) {
parameter<FirRegularClassSymbol>("klass") parameter<FirClassLikeSymbol<*>>("klass")
} }
val EXPRESSION_EXPECTED_PACKAGE_FOUND by error<KtExpression>(PositioningStrategy.SELECTOR_BY_QUALIFIED) val EXPRESSION_EXPECTED_PACKAGE_FOUND by error<KtExpression>(PositioningStrategy.SELECTOR_BY_QUALIFIED)
} }
@@ -671,7 +671,7 @@ object FirErrors {
// Context tracking // Context tracking
val TYPE_PARAMETER_IS_NOT_AN_EXPRESSION by error1<KtSimpleNameExpression, FirTypeParameterSymbol>() val TYPE_PARAMETER_IS_NOT_AN_EXPRESSION by error1<KtSimpleNameExpression, FirTypeParameterSymbol>()
val TYPE_PARAMETER_ON_LHS_OF_DOT by error1<KtSimpleNameExpression, FirTypeParameterSymbol>() val TYPE_PARAMETER_ON_LHS_OF_DOT by error1<KtSimpleNameExpression, FirTypeParameterSymbol>()
val NO_COMPANION_OBJECT by error1<KtExpression, FirRegularClassSymbol>(SourceElementPositioningStrategies.SELECTOR_BY_QUALIFIED) val NO_COMPANION_OBJECT by error1<KtExpression, FirClassLikeSymbol<*>>(SourceElementPositioningStrategies.SELECTOR_BY_QUALIFIED)
val EXPRESSION_EXPECTED_PACKAGE_FOUND by error0<KtExpression>(SourceElementPositioningStrategies.SELECTOR_BY_QUALIFIED) val EXPRESSION_EXPECTED_PACKAGE_FOUND by error0<KtExpression>(SourceElementPositioningStrategies.SELECTOR_BY_QUALIFIED)
// Function contracts // Function contracts
@@ -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.resolve.inference.model.ConeLambdaArgumentConstraintPosition
import org.jetbrains.kotlin.fir.symbols.ConeTypeParameterLookupTag import org.jetbrains.kotlin.fir.symbols.ConeTypeParameterLookupTag
import org.jetbrains.kotlin.fir.symbols.impl.FirCallableSymbol 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.FirNamedFunctionSymbol
import org.jetbrains.kotlin.fir.symbols.impl.FirRegularClassSymbol
import org.jetbrains.kotlin.fir.types.* import org.jetbrains.kotlin.fir.types.*
import org.jetbrains.kotlin.lexer.KtTokens import org.jetbrains.kotlin.lexer.KtTokens
import org.jetbrains.kotlin.name.SpecialNames import org.jetbrains.kotlin.name.SpecialNames
@@ -64,7 +64,7 @@ private fun ConeDiagnostic.toKtDiagnostic(
is ConeVisibilityError -> FirErrors.INVISIBLE_REFERENCE.createOn(source, this.symbol) is ConeVisibilityError -> FirErrors.INVISIBLE_REFERENCE.createOn(source, this.symbol)
is ConeInapplicableWrongReceiver -> FirErrors.UNRESOLVED_REFERENCE_WRONG_RECEIVER.createOn(source, this.candidateSymbols) 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 { is ConeAmbiguityError -> when {
applicability.isSuccess -> FirErrors.OVERLOAD_RESOLUTION_AMBIGUITY.createOn(source, this.candidates.map { it.symbol }) applicability.isSuccess -> FirErrors.OVERLOAD_RESOLUTION_AMBIGUITY.createOn(source, this.candidates.map { it.symbol })
applicability == CandidateApplicability.UNSAFE_CALL -> { applicability == CandidateApplicability.UNSAFE_CALL -> {
@@ -7,7 +7,9 @@ package org.jetbrains.kotlin.fir
import org.jetbrains.kotlin.KtSourceElement import org.jetbrains.kotlin.KtSourceElement
import org.jetbrains.kotlin.config.ApiVersion 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.FirClass
import org.jetbrains.kotlin.fir.declarations.fullyExpandedClass
import org.jetbrains.kotlin.fir.diagnostics.ConeDiagnostic import org.jetbrains.kotlin.fir.diagnostics.ConeDiagnostic
import org.jetbrains.kotlin.fir.expressions.FirExpression import org.jetbrains.kotlin.fir.expressions.FirExpression
import org.jetbrains.kotlin.fir.expressions.FirResolvedQualifier 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.resolve.typeForQualifier
import org.jetbrains.kotlin.fir.symbols.impl.FirClassLikeSymbol import org.jetbrains.kotlin.fir.symbols.impl.FirClassLikeSymbol
import org.jetbrains.kotlin.fir.symbols.impl.FirRegularClassSymbol 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.fir.types.FirTypeProjection
import org.jetbrains.kotlin.name.ClassId import org.jetbrains.kotlin.name.ClassId
import org.jetbrains.kotlin.name.FqName import org.jetbrains.kotlin.name.FqName
@@ -47,35 +50,36 @@ fun BodyResolveComponents.resolveRootPartOfQualifier(
for (scope in createCurrentScopeList()) { for (scope in createCurrentScopeList()) {
scope.getSingleVisibleClassifier(session, this, name)?.let { scope.getSingleVisibleClassifier(session, this, name)?.let {
if (it is FirRegularClassSymbol) { val klass = (it as? FirClassLikeSymbol<*>)?.fullyExpandedClass(session)
val isVisible = session.visibilityChecker.isClassLikeVisible( ?: return@let
it.fir,
session, val isVisible = session.visibilityChecker.isClassLikeVisible(
file, klass.fir,
containingDeclarations, session,
) file,
if (!isVisible) { containingDeclarations,
return@let )
} if (!isVisible) {
val classId = it.classId return@let
return buildResolvedQualifier { }
this.source = source val classId = it.classId
packageFqName = classId.packageFqName return buildResolvedQualifier {
relativeClassFqName = classId.relativeClassName this.source = source
symbol = it packageFqName = classId.packageFqName
this.typeArguments.addAll(typeArguments) relativeClassFqName = classId.relativeClassName
this.nonFatalDiagnostics.addAll( symbol = it
extractNonFatalDiagnostics( this.typeArguments.addAll(typeArguments)
source, this.nonFatalDiagnostics.addAll(
explicitReceiver = null, extractNonFatalDiagnostics(
it, source,
extraNotFatalDiagnostics = nonFatalDiagnosticsFromExpression, explicitReceiver = null,
session.languageVersionSettings.apiVersion it,
) extraNotFatalDiagnostics = nonFatalDiagnosticsFromExpression,
session.languageVersionSettings.apiVersion
) )
}.apply { )
resultType = typeForQualifier(this) }.apply {
} resultType = typeForQualifier(this)
} }
} }
} }
@@ -6,11 +6,13 @@
package org.jetbrains.kotlin.fir.resolve.calls package org.jetbrains.kotlin.fir.resolve.calls
import org.jetbrains.kotlin.descriptors.ClassKind 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.FirDeclarationOrigin
import org.jetbrains.kotlin.fir.declarations.FirRegularClass import org.jetbrains.kotlin.fir.declarations.FirRegularClass
import org.jetbrains.kotlin.fir.declarations.FirResolvePhase import org.jetbrains.kotlin.fir.declarations.FirResolvePhase
import org.jetbrains.kotlin.fir.declarations.builder.buildErrorFunction import org.jetbrains.kotlin.fir.declarations.builder.buildErrorFunction
import org.jetbrains.kotlin.fir.declarations.builder.buildErrorProperty 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.diagnostics.ConeDiagnostic
import org.jetbrains.kotlin.fir.expressions.* import org.jetbrains.kotlin.fir.expressions.*
import org.jetbrains.kotlin.fir.moduleData 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) { 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)) result.addDiagnostic(Unsupported("References to variables aren't supported yet", callSite.calleeReference.source))
} }
} else if (objectsByName && } else if (objectsByName && symbol.isRegularClassWithoutCompanion(callInfo.session)) {
symbol is FirRegularClassSymbol &&
symbol.classKind != ClassKind.OBJECT &&
symbol.companionObjectSymbol == null
) {
result.addDiagnostic(NoCompanionObject) result.addDiagnostic(NoCompanionObject)
} }
if (callInfo.origin == FirFunctionCallOrigin.Operator && symbol is FirPropertySymbol) { if (callInfo.origin == FirFunctionCallOrigin.Operator && symbol is FirPropertySymbol) {
@@ -100,6 +98,11 @@ class CandidateFactory private constructor(
return result 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<*> { private fun FirBasedSymbol<*>.unwrapIntegerOperatorSymbolIfNeeded(callInfo: CallInfo): FirBasedSymbol<*> {
if (this !is FirNamedFunctionSymbol) return this if (this !is FirNamedFunctionSymbol) return this
// There is no need to unwrap unary operators // There is no need to unwrap unary operators
@@ -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() {
<!NO_COMPANION_OBJECT!>ItemKey<!> // K1: ok, K2: NO_COMPANION_OBJECT
}
@@ -1,3 +1,4 @@
// FIR_IDENTICAL
// ISSUE: KT-58523 // ISSUE: KT-58523
// FILE: pkg.kt // FILE: pkg.kt