[FIR] Report errors about invisible types from type resolution
This commit is contained in:
committed by
teamcityserver
parent
f2c319c4ae
commit
8707be51c9
@@ -8,6 +8,7 @@ package org.jetbrains.kotlin.fir.resolve
|
||||
import org.jetbrains.kotlin.fir.FirSession
|
||||
import org.jetbrains.kotlin.fir.FirSessionComponent
|
||||
import org.jetbrains.kotlin.fir.declarations.FirFile
|
||||
import org.jetbrains.kotlin.fir.diagnostics.ConeDiagnostic
|
||||
import org.jetbrains.kotlin.fir.resolve.transformers.ScopeClassDeclaration
|
||||
import org.jetbrains.kotlin.fir.types.ConeKotlinType
|
||||
import org.jetbrains.kotlin.fir.types.FirTypeRef
|
||||
@@ -20,7 +21,7 @@ abstract class FirTypeResolver : FirSessionComponent {
|
||||
isOperandOfIsOperator: Boolean,
|
||||
useSiteFile: FirFile?,
|
||||
supertypeSupplier: SupertypeSupplier
|
||||
): ConeKotlinType
|
||||
): Pair<ConeKotlinType, ConeDiagnostic?>
|
||||
}
|
||||
|
||||
val FirSession.typeResolver: FirTypeResolver by FirSession.sessionComponentAccessor()
|
||||
|
||||
+42
-28
@@ -6,19 +6,19 @@
|
||||
package org.jetbrains.kotlin.fir.resolve.providers.impl
|
||||
|
||||
import org.jetbrains.kotlin.KtSourceElement
|
||||
import org.jetbrains.kotlin.fir.*
|
||||
import org.jetbrains.kotlin.fir.FirSession
|
||||
import org.jetbrains.kotlin.fir.ThreadSafeMutableState
|
||||
import org.jetbrains.kotlin.fir.declarations.*
|
||||
import org.jetbrains.kotlin.fir.declarations.impl.FirOuterClassTypeParameterRef
|
||||
import org.jetbrains.kotlin.fir.declarations.utils.isEnumClass
|
||||
import org.jetbrains.kotlin.fir.declarations.utils.isLocal
|
||||
import org.jetbrains.kotlin.fir.diagnostics.ConeDiagnostic
|
||||
import org.jetbrains.kotlin.fir.diagnostics.ConeSimpleDiagnostic
|
||||
import org.jetbrains.kotlin.fir.diagnostics.ConeUnexpectedTypeArgumentsError
|
||||
import org.jetbrains.kotlin.fir.diagnostics.DiagnosticKind
|
||||
import org.jetbrains.kotlin.fir.render
|
||||
import org.jetbrains.kotlin.fir.resolve.*
|
||||
import org.jetbrains.kotlin.fir.resolve.diagnostics.ConeOuterClassArgumentsRequired
|
||||
import org.jetbrains.kotlin.fir.resolve.diagnostics.ConeUnresolvedQualifierError
|
||||
import org.jetbrains.kotlin.fir.resolve.diagnostics.ConeUnsupportedDynamicType
|
||||
import org.jetbrains.kotlin.fir.resolve.diagnostics.ConeWrongNumberOfTypeArgumentsError
|
||||
import org.jetbrains.kotlin.fir.resolve.diagnostics.*
|
||||
import org.jetbrains.kotlin.fir.resolve.providers.symbolProvider
|
||||
import org.jetbrains.kotlin.fir.resolve.substitution.ConeSubstitutor
|
||||
import org.jetbrains.kotlin.fir.resolve.transformers.ScopeClassDeclaration
|
||||
@@ -30,8 +30,10 @@ import org.jetbrains.kotlin.fir.types.*
|
||||
import org.jetbrains.kotlin.fir.types.impl.ConeClassLikeTypeImpl
|
||||
import org.jetbrains.kotlin.fir.types.impl.ConeTypeParameterTypeImpl
|
||||
import org.jetbrains.kotlin.fir.types.impl.FirImplicitBuiltinTypeRef
|
||||
import org.jetbrains.kotlin.fir.visibilityChecker
|
||||
import org.jetbrains.kotlin.name.ClassId
|
||||
import org.jetbrains.kotlin.name.StandardClassIds
|
||||
import org.jetbrains.kotlin.utils.addToStdlib.runIf
|
||||
|
||||
@ThreadSafeMutableState
|
||||
class FirTypeResolverImpl(private val session: FirSession) : FirTypeResolver() {
|
||||
@@ -101,18 +103,18 @@ class FirTypeResolverImpl(private val session: FirSession) : FirTypeResolver() {
|
||||
scopeClassDeclaration: ScopeClassDeclaration,
|
||||
useSiteFile: FirFile?,
|
||||
supertypeSupplier: SupertypeSupplier
|
||||
): Pair<FirBasedSymbol<*>?, ConeSubstitutor?> {
|
||||
): Triple<FirBasedSymbol<*>?, ConeSubstitutor?, ConeDiagnostic?> {
|
||||
return when (typeRef) {
|
||||
is FirResolvedTypeRef -> {
|
||||
val resultSymbol = typeRef.coneTypeSafe<ConeLookupTagBasedType>()?.lookupTag?.let(symbolProvider::getSymbolByLookupTag)
|
||||
resultSymbol to null
|
||||
Triple(resultSymbol, null, null)
|
||||
}
|
||||
|
||||
is FirUserTypeRef -> {
|
||||
val qualifierResolver = session.qualifierResolver
|
||||
var acceptedSymbol: FirBasedSymbol<*>? = null
|
||||
var firstNonApplicable: FirBasedSymbol<*>? = null
|
||||
var substitutor: ConeSubstitutor? = null
|
||||
val notApplicableSymbols = mutableListOf<Pair<FirBasedSymbol<*>, ConeSubstitutor>>()
|
||||
val qualifier = typeRef.qualifier
|
||||
val scopes = scopeClassDeclaration.scopes
|
||||
val containingDeclarations = scopeClassDeclaration.containingDeclarations
|
||||
@@ -121,36 +123,48 @@ class FirTypeResolverImpl(private val session: FirSession) : FirTypeResolver() {
|
||||
if (acceptedSymbol != null) {
|
||||
break
|
||||
}
|
||||
val collectNonApplicable = notApplicableSymbols.isEmpty()
|
||||
scope.processClassifiersByNameWithSubstitution(qualifier.first().name) { symbol, substitutorFromScope ->
|
||||
if (acceptedSymbol != null) {
|
||||
return@processClassifiersByNameWithSubstitution
|
||||
}
|
||||
|
||||
if (acceptedSymbol != null) return@processClassifiersByNameWithSubstitution
|
||||
val resolvedSymbol = resolveSymbol(symbol, qualifier, qualifierResolver)
|
||||
?: return@processClassifiersByNameWithSubstitution
|
||||
|
||||
if (resolvedSymbol.isVisible(useSiteFile, containingDeclarations, supertypeSupplier)) {
|
||||
acceptedSymbol = resolvedSymbol
|
||||
substitutor = substitutorFromScope
|
||||
} else {
|
||||
firstNonApplicable = resolvedSymbol
|
||||
} else if (collectNonApplicable) {
|
||||
resolvedSymbol.isVisible(useSiteFile, containingDeclarations, supertypeSupplier)
|
||||
notApplicableSymbols += resolvedSymbol to substitutorFromScope
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (acceptedSymbol == null) {
|
||||
acceptedSymbol = firstNonApplicable
|
||||
}
|
||||
when {
|
||||
acceptedSymbol != null -> Triple(acceptedSymbol, substitutor, null)
|
||||
|
||||
// TODO: Imports
|
||||
val resultSymbol: FirBasedSymbol<*>? = acceptedSymbol ?: qualifierResolver.resolveSymbol(qualifier)
|
||||
resultSymbol to substitutor
|
||||
notApplicableSymbols.size == 1 -> {
|
||||
val (notApplicableSymbol, resultingSubstitutor) = notApplicableSymbols.single()
|
||||
Triple(notApplicableSymbol, resultingSubstitutor, ConeVisibilityError(notApplicableSymbol))
|
||||
}
|
||||
|
||||
else -> {
|
||||
val symbolFromQualifier = qualifierResolver.resolveSymbol(qualifier)
|
||||
val diagnostic = runIf(
|
||||
symbolFromQualifier != null &&
|
||||
!symbolFromQualifier.isVisible(useSiteFile, containingDeclarations, supertypeSupplier)
|
||||
) {
|
||||
ConeVisibilityError(symbolFromQualifier!!)
|
||||
}
|
||||
Triple(symbolFromQualifier, null, diagnostic)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
is FirImplicitBuiltinTypeRef -> {
|
||||
resolveBuiltInQualified(typeRef.id, session) to null
|
||||
Triple(resolveBuiltInQualified(typeRef.id, session), null, null)
|
||||
}
|
||||
|
||||
else -> null to null
|
||||
else -> Triple(null, null, null)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -455,11 +469,11 @@ class FirTypeResolverImpl(private val session: FirSession) : FirTypeResolver() {
|
||||
isOperandOfIsOperator: Boolean,
|
||||
useSiteFile: FirFile?,
|
||||
supertypeSupplier: SupertypeSupplier
|
||||
): ConeKotlinType {
|
||||
): Pair<ConeKotlinType, ConeDiagnostic?> {
|
||||
return when (typeRef) {
|
||||
is FirResolvedTypeRef -> typeRef.type
|
||||
is FirResolvedTypeRef -> typeRef.type to null
|
||||
is FirUserTypeRef -> {
|
||||
val (symbol, substitutor) = resolveToSymbol(typeRef, scopeClassDeclaration, useSiteFile, supertypeSupplier)
|
||||
val (symbol, substitutor, diagnostic) = resolveToSymbol(typeRef, scopeClassDeclaration, useSiteFile, supertypeSupplier)
|
||||
resolveUserType(
|
||||
typeRef,
|
||||
symbol,
|
||||
@@ -467,10 +481,10 @@ class FirTypeResolverImpl(private val session: FirSession) : FirTypeResolver() {
|
||||
areBareTypesAllowed,
|
||||
scopeClassDeclaration.topContainer ?: scopeClassDeclaration.containingDeclarations.lastOrNull(),
|
||||
isOperandOfIsOperator
|
||||
)
|
||||
) to diagnostic
|
||||
}
|
||||
is FirFunctionTypeRef -> createFunctionalType(typeRef)
|
||||
is FirDynamicTypeRef -> ConeKotlinErrorType(ConeUnsupportedDynamicType())
|
||||
is FirFunctionTypeRef -> createFunctionalType(typeRef) to null
|
||||
is FirDynamicTypeRef -> ConeKotlinErrorType(ConeUnsupportedDynamicType()) to null
|
||||
else -> error(typeRef.render())
|
||||
}
|
||||
}
|
||||
|
||||
+48
-35
@@ -11,6 +11,7 @@ import org.jetbrains.kotlin.fakeElement
|
||||
import org.jetbrains.kotlin.fir.*
|
||||
import org.jetbrains.kotlin.fir.declarations.FirFile
|
||||
import org.jetbrains.kotlin.fir.declarations.FirResolvePhase
|
||||
import org.jetbrains.kotlin.fir.diagnostics.ConeDiagnostic
|
||||
import org.jetbrains.kotlin.fir.diagnostics.ConeSimpleDiagnostic
|
||||
import org.jetbrains.kotlin.fir.diagnostics.ConeUnexpectedTypeArgumentsError
|
||||
import org.jetbrains.kotlin.fir.resolve.SupertypeSupplier
|
||||
@@ -77,17 +78,15 @@ class FirSpecificTypeResolverTransformer(
|
||||
withBareTypes(allowed = false) {
|
||||
typeRef.transformChildren(this, data)
|
||||
}
|
||||
return transformType(
|
||||
val (resolvedType, diagnostic) = typeResolver.resolveType(
|
||||
typeRef,
|
||||
typeResolver.resolveType(
|
||||
typeRef,
|
||||
data,
|
||||
areBareTypesAllowed,
|
||||
isOperandOfIsOperator,
|
||||
currentFile,
|
||||
supertypeSupplier
|
||||
)
|
||||
data,
|
||||
areBareTypesAllowed,
|
||||
isOperandOfIsOperator,
|
||||
currentFile,
|
||||
supertypeSupplier
|
||||
)
|
||||
return transformType(typeRef, resolvedType, diagnostic)
|
||||
}
|
||||
|
||||
@OptIn(PrivateForInline::class)
|
||||
@@ -98,15 +97,17 @@ class FirSpecificTypeResolverTransformer(
|
||||
functionTypeRef.transformChildren(this, data)
|
||||
val scopeOwnerLookupNames = data.scopes.flatMap { it.scopeOwnerLookupNames }
|
||||
session.lookupTracker?.recordTypeLookup(functionTypeRef, scopeOwnerLookupNames, currentFile?.source)
|
||||
val resolvedType = typeResolver.resolveType(
|
||||
val resolvedTypeWithDiagnostic = typeResolver.resolveType(
|
||||
functionTypeRef,
|
||||
data,
|
||||
areBareTypesAllowed,
|
||||
isOperandOfIsOperator,
|
||||
currentFile,
|
||||
supertypeSupplier
|
||||
).takeIfAcceptable()
|
||||
return if (resolvedType != null && resolvedType !is ConeClassErrorType) {
|
||||
)
|
||||
val resolvedType = resolvedTypeWithDiagnostic.first.takeIfAcceptable()
|
||||
val diagnostic = resolvedTypeWithDiagnostic.second
|
||||
return if (resolvedType != null && resolvedType !is ConeClassErrorType && diagnostic == null) {
|
||||
buildResolvedTypeRef {
|
||||
source = functionTypeRef.source
|
||||
type = resolvedType
|
||||
@@ -119,39 +120,51 @@ class FirSpecificTypeResolverTransformer(
|
||||
if (resolvedType != null) {
|
||||
type = resolvedType
|
||||
}
|
||||
diagnostic = (resolvedType as? ConeClassErrorType)?.diagnostic
|
||||
?: ConeSimpleDiagnostic("Unresolved functional type: ${functionTypeRef.render()}")
|
||||
this.diagnostic = diagnostic ?: (resolvedType as? ConeClassErrorType)?.diagnostic
|
||||
?: ConeSimpleDiagnostic("Unresolved functional type: ${functionTypeRef.render()}")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun transformType(typeRef: FirTypeRef, resolvedType: ConeKotlinType): FirResolvedTypeRef {
|
||||
return if (resolvedType !is ConeClassErrorType) {
|
||||
buildResolvedTypeRef {
|
||||
source = typeRef.source
|
||||
type = resolvedType
|
||||
annotations += typeRef.annotations
|
||||
delegatedTypeRef = typeRef
|
||||
}
|
||||
} else {
|
||||
buildErrorTypeRef {
|
||||
val typeRefSourceKind = typeRef.source?.kind
|
||||
val diagnosticSource = resolvedType.diagnostic.safeAs<ConeUnexpectedTypeArgumentsError>()
|
||||
?.source.safeAs<KtSourceElement>()
|
||||
private fun transformType(typeRef: FirTypeRef, resolvedType: ConeKotlinType, diagnostic: ConeDiagnostic?): FirResolvedTypeRef {
|
||||
return when {
|
||||
resolvedType is ConeClassErrorType -> {
|
||||
buildErrorTypeRef {
|
||||
val typeRefSourceKind = typeRef.source?.kind
|
||||
val diagnosticSource = resolvedType.diagnostic.safeAs<ConeUnexpectedTypeArgumentsError>()
|
||||
?.source.safeAs<KtSourceElement>()
|
||||
|
||||
source = if (diagnosticSource != null) {
|
||||
if (typeRefSourceKind is KtFakeSourceElementKind) {
|
||||
diagnosticSource.fakeElement(typeRefSourceKind)
|
||||
source = if (diagnosticSource != null) {
|
||||
if (typeRefSourceKind is KtFakeSourceElementKind) {
|
||||
diagnosticSource.fakeElement(typeRefSourceKind)
|
||||
} else {
|
||||
diagnosticSource
|
||||
}
|
||||
} else {
|
||||
diagnosticSource
|
||||
typeRef.source
|
||||
}
|
||||
} else {
|
||||
typeRef.source
|
||||
}
|
||||
|
||||
delegatedTypeRef = typeRef
|
||||
type = resolvedType
|
||||
|
||||
this.diagnostic = resolvedType.diagnostic
|
||||
}
|
||||
}
|
||||
diagnostic != null -> {
|
||||
buildErrorTypeRef {
|
||||
source = typeRef.source
|
||||
this.diagnostic = diagnostic
|
||||
type = resolvedType
|
||||
diagnostic = resolvedType.diagnostic
|
||||
delegatedTypeRef = typeRef
|
||||
}
|
||||
}
|
||||
else -> {
|
||||
buildResolvedTypeRef {
|
||||
source = typeRef.source
|
||||
type = resolvedType
|
||||
annotations += typeRef.annotations
|
||||
delegatedTypeRef = typeRef
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user