[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")
}
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)
}
@@ -671,7 +671,7 @@ object FirErrors {
// Context tracking
val TYPE_PARAMETER_IS_NOT_AN_EXPRESSION 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)
// 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.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 -> {
@@ -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)
}
}
}
@@ -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
@@ -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
// FILE: pkg.kt