FIR checker: avoid redundant casting to resolved type ref
This commit is contained in:
committed by
Dmitriy Novozhilov
parent
37a702b962
commit
a9322a01ce
@@ -22,23 +22,19 @@ import org.jetbrains.kotlin.fir.expressions.FirFunctionCall
|
|||||||
import org.jetbrains.kotlin.fir.expressions.FirQualifiedAccessExpression
|
import org.jetbrains.kotlin.fir.expressions.FirQualifiedAccessExpression
|
||||||
import org.jetbrains.kotlin.fir.expressions.impl.FirEmptyExpressionBlock
|
import org.jetbrains.kotlin.fir.expressions.impl.FirEmptyExpressionBlock
|
||||||
import org.jetbrains.kotlin.fir.references.FirResolvedNamedReference
|
import org.jetbrains.kotlin.fir.references.FirResolvedNamedReference
|
||||||
import org.jetbrains.kotlin.fir.resolve.firSymbolProvider
|
|
||||||
import org.jetbrains.kotlin.fir.resolve.fullyExpandedType
|
import org.jetbrains.kotlin.fir.resolve.fullyExpandedType
|
||||||
import org.jetbrains.kotlin.fir.resolve.toSymbol
|
import org.jetbrains.kotlin.fir.resolve.toSymbol
|
||||||
import org.jetbrains.kotlin.fir.resolve.transformers.firClassLike
|
import org.jetbrains.kotlin.fir.resolve.transformers.firClassLike
|
||||||
import org.jetbrains.kotlin.fir.scopes.ProcessorAction
|
import org.jetbrains.kotlin.fir.scopes.ProcessorAction
|
||||||
import org.jetbrains.kotlin.fir.scopes.processOverriddenFunctions
|
import org.jetbrains.kotlin.fir.scopes.processOverriddenFunctions
|
||||||
import org.jetbrains.kotlin.fir.scopes.unsubstitutedScope
|
import org.jetbrains.kotlin.fir.scopes.unsubstitutedScope
|
||||||
import org.jetbrains.kotlin.fir.symbols.StandardClassIds
|
|
||||||
import org.jetbrains.kotlin.fir.symbols.impl.FirFunctionSymbol
|
import org.jetbrains.kotlin.fir.symbols.impl.FirFunctionSymbol
|
||||||
import org.jetbrains.kotlin.fir.symbols.impl.FirNamedFunctionSymbol
|
|
||||||
import org.jetbrains.kotlin.fir.symbols.impl.FirRegularClassSymbol
|
import org.jetbrains.kotlin.fir.symbols.impl.FirRegularClassSymbol
|
||||||
import org.jetbrains.kotlin.fir.typeCheckerContext
|
import org.jetbrains.kotlin.fir.typeCheckerContext
|
||||||
import org.jetbrains.kotlin.fir.types.*
|
import org.jetbrains.kotlin.fir.types.*
|
||||||
import org.jetbrains.kotlin.lexer.KtModifierKeywordToken
|
import org.jetbrains.kotlin.lexer.KtModifierKeywordToken
|
||||||
import org.jetbrains.kotlin.lexer.KtTokens
|
import org.jetbrains.kotlin.lexer.KtTokens
|
||||||
import org.jetbrains.kotlin.psi.KtModifierList
|
import org.jetbrains.kotlin.psi.KtModifierList
|
||||||
import org.jetbrains.kotlin.psi.KtObjectLiteralExpression
|
|
||||||
import org.jetbrains.kotlin.psi.psiUtil.visibilityModifierType
|
import org.jetbrains.kotlin.psi.psiUtil.visibilityModifierType
|
||||||
import org.jetbrains.kotlin.utils.addToStdlib.safeAs
|
import org.jetbrains.kotlin.utils.addToStdlib.safeAs
|
||||||
|
|
||||||
@@ -132,7 +128,7 @@ fun ConeKotlinType.toRegularClass(session: FirSession): FirRegularClass? {
|
|||||||
* or null of something goes wrong.
|
* or null of something goes wrong.
|
||||||
*/
|
*/
|
||||||
fun FirTypeRef.toRegularClass(session: FirSession): FirRegularClass? {
|
fun FirTypeRef.toRegularClass(session: FirSession): FirRegularClass? {
|
||||||
return safeAs<FirResolvedTypeRef>()?.type?.toRegularClass(session)
|
return coneType.toRegularClass(session)
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -289,18 +285,15 @@ private fun FirDeclaration.hasBody(): Boolean = when (this) {
|
|||||||
* or null if couldn't find any.
|
* or null if couldn't find any.
|
||||||
*/
|
*/
|
||||||
fun FirClass<*>.findNonInterfaceSupertype(context: CheckerContext): FirTypeRef? {
|
fun FirClass<*>.findNonInterfaceSupertype(context: CheckerContext): FirTypeRef? {
|
||||||
for (it in superTypeRefs) {
|
for (superTypeRef in superTypeRefs) {
|
||||||
val lookupTag = it.safeAs<FirResolvedTypeRef>()
|
val lookupTag = superTypeRef.coneType.safeAs<ConeClassLikeType>()?.lookupTag ?: continue
|
||||||
?.type.safeAs<ConeClassLikeType>()
|
|
||||||
?.lookupTag
|
|
||||||
?: continue
|
|
||||||
|
|
||||||
val fir = lookupTag.toSymbol(context.session)
|
val fir = lookupTag.toSymbol(context.session)
|
||||||
?.fir.safeAs<FirClass<*>>()
|
?.fir.safeAs<FirClass<*>>()
|
||||||
?: continue
|
?: continue
|
||||||
|
|
||||||
if (fir.classKind != ClassKind.INTERFACE) {
|
if (fir.classKind != ClassKind.INTERFACE) {
|
||||||
return it
|
return superTypeRef
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+2
@@ -44,6 +44,8 @@ object FirConflictingProjectionChecker : FirBasicDeclarationChecker() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private fun checkTypeRef(typeRef: FirTypeRef, context: CheckerContext, reporter: DiagnosticReporter) {
|
private fun checkTypeRef(typeRef: FirTypeRef, context: CheckerContext, reporter: DiagnosticReporter) {
|
||||||
|
// TODO: remaining implicit types should be resolved as an error type, along with proper error kind,
|
||||||
|
// e.g., type mismatch, can't infer parameter type, syntax error, etc.
|
||||||
val declaration = typeRef.safeAs<FirResolvedTypeRef>()
|
val declaration = typeRef.safeAs<FirResolvedTypeRef>()
|
||||||
?.coneTypeSafe<ConeClassLikeType>()
|
?.coneTypeSafe<ConeClassLikeType>()
|
||||||
?.lookupTag
|
?.lookupTag
|
||||||
|
|||||||
+1
-2
@@ -136,8 +136,7 @@ object FirOverrideChecker : FirRegularClassChecker() {
|
|||||||
typeCheckerContext: AbstractTypeCheckerContext,
|
typeCheckerContext: AbstractTypeCheckerContext,
|
||||||
context: CheckerContext,
|
context: CheckerContext,
|
||||||
): FirMemberDeclaration? {
|
): FirMemberDeclaration? {
|
||||||
val overridingReturnType = returnTypeRef.safeAs<FirResolvedTypeRef>()?.type
|
val overridingReturnType = returnTypeRef.coneType
|
||||||
?: return null
|
|
||||||
|
|
||||||
// Don't report *_ON_OVERRIDE diagnostics according to an error return type. That should be reported separately.
|
// Don't report *_ON_OVERRIDE diagnostics according to an error return type. That should be reported separately.
|
||||||
if (overridingReturnType is ConeKotlinErrorType) {
|
if (overridingReturnType is ConeKotlinErrorType) {
|
||||||
|
|||||||
+5
-14
@@ -12,8 +12,8 @@ import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors
|
|||||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.reportOn
|
import org.jetbrains.kotlin.fir.analysis.diagnostics.reportOn
|
||||||
import org.jetbrains.kotlin.fir.declarations.*
|
import org.jetbrains.kotlin.fir.declarations.*
|
||||||
import org.jetbrains.kotlin.fir.resolve.firSymbolProvider
|
import org.jetbrains.kotlin.fir.resolve.firSymbolProvider
|
||||||
import org.jetbrains.kotlin.fir.types.ConeClassLikeType
|
import org.jetbrains.kotlin.fir.types.classId
|
||||||
import org.jetbrains.kotlin.fir.types.FirResolvedTypeRef
|
import org.jetbrains.kotlin.fir.types.coneType
|
||||||
import org.jetbrains.kotlin.utils.addToStdlib.safeAs
|
import org.jetbrains.kotlin.utils.addToStdlib.safeAs
|
||||||
|
|
||||||
object FirSealedSupertypeChecker : FirMemberDeclarationChecker() {
|
object FirSealedSupertypeChecker : FirMemberDeclarationChecker() {
|
||||||
@@ -41,10 +41,7 @@ object FirSealedSupertypeChecker : FirMemberDeclarationChecker() {
|
|||||||
|
|
||||||
private fun checkTopLevelDeclaration(declaration: FirClass<*>, context: CheckerContext, reporter: DiagnosticReporter) {
|
private fun checkTopLevelDeclaration(declaration: FirClass<*>, context: CheckerContext, reporter: DiagnosticReporter) {
|
||||||
for (it in declaration.superTypeRefs) {
|
for (it in declaration.superTypeRefs) {
|
||||||
val classId = it.safeAs<FirResolvedTypeRef>()
|
val classId = it.coneType.classId ?: continue
|
||||||
?.type.safeAs<ConeClassLikeType>()
|
|
||||||
?.lookupTag?.classId
|
|
||||||
?: continue
|
|
||||||
|
|
||||||
if (classId.isLocal) {
|
if (classId.isLocal) {
|
||||||
continue
|
continue
|
||||||
@@ -63,10 +60,7 @@ object FirSealedSupertypeChecker : FirMemberDeclarationChecker() {
|
|||||||
|
|
||||||
private fun checkLocalDeclaration(declaration: FirClass<*>, context: CheckerContext, reporter: DiagnosticReporter) {
|
private fun checkLocalDeclaration(declaration: FirClass<*>, context: CheckerContext, reporter: DiagnosticReporter) {
|
||||||
for (it in declaration.superTypeRefs) {
|
for (it in declaration.superTypeRefs) {
|
||||||
val classId = it.safeAs<FirResolvedTypeRef>()
|
val classId = it.coneType.classId ?: continue
|
||||||
?.type.safeAs<ConeClassLikeType>()
|
|
||||||
?.lookupTag?.classId
|
|
||||||
?: continue
|
|
||||||
|
|
||||||
if (classId.isLocal) {
|
if (classId.isLocal) {
|
||||||
continue
|
continue
|
||||||
@@ -85,10 +79,7 @@ object FirSealedSupertypeChecker : FirMemberDeclarationChecker() {
|
|||||||
|
|
||||||
private fun checkInnerDeclaration(declaration: FirClass<*>, context: CheckerContext, reporter: DiagnosticReporter) {
|
private fun checkInnerDeclaration(declaration: FirClass<*>, context: CheckerContext, reporter: DiagnosticReporter) {
|
||||||
for (it in declaration.superTypeRefs) {
|
for (it in declaration.superTypeRefs) {
|
||||||
val classId = it.safeAs<FirResolvedTypeRef>()
|
val classId = it.coneType.classId ?: continue
|
||||||
?.type.safeAs<ConeClassLikeType>()
|
|
||||||
?.lookupTag?.classId
|
|
||||||
?: continue
|
|
||||||
|
|
||||||
if (classId.isLocal) {
|
if (classId.isLocal) {
|
||||||
continue
|
continue
|
||||||
|
|||||||
+1
@@ -25,6 +25,7 @@ object FirCatchParameterChecker : FirTryExpressionChecker() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
val typeRef = catchParameter.returnTypeRef
|
val typeRef = catchParameter.returnTypeRef
|
||||||
|
// TODO: remaining implicit types should be resolved as an error type, along with proper error kind, most likely syntax error.
|
||||||
if (typeRef !is FirResolvedTypeRef) return
|
if (typeRef !is FirResolvedTypeRef) return
|
||||||
|
|
||||||
val coneType = typeRef.type
|
val coneType = typeRef.type
|
||||||
|
|||||||
+2
-3
@@ -16,7 +16,6 @@ import org.jetbrains.kotlin.fir.declarations.FirClass
|
|||||||
import org.jetbrains.kotlin.fir.expressions.FirQualifiedAccessExpression
|
import org.jetbrains.kotlin.fir.expressions.FirQualifiedAccessExpression
|
||||||
import org.jetbrains.kotlin.fir.references.FirSuperReference
|
import org.jetbrains.kotlin.fir.references.FirSuperReference
|
||||||
import org.jetbrains.kotlin.fir.resolve.transformers.firClassLike
|
import org.jetbrains.kotlin.fir.resolve.transformers.firClassLike
|
||||||
import org.jetbrains.kotlin.fir.types.FirResolvedTypeRef
|
|
||||||
import org.jetbrains.kotlin.utils.addToStdlib.safeAs
|
import org.jetbrains.kotlin.utils.addToStdlib.safeAs
|
||||||
|
|
||||||
object FirQualifiedSupertypeExtendedByOtherSupertypeChecker : FirQualifiedAccessChecker() {
|
object FirQualifiedSupertypeExtendedByOtherSupertypeChecker : FirQualifiedAccessChecker() {
|
||||||
@@ -26,8 +25,8 @@ object FirQualifiedSupertypeExtendedByOtherSupertypeChecker : FirQualifiedAccess
|
|||||||
?.takeIf { it.hadExplicitTypeInSource() }
|
?.takeIf { it.hadExplicitTypeInSource() }
|
||||||
?: return
|
?: return
|
||||||
|
|
||||||
val explicitType = superReference.superTypeRef.safeAs<FirResolvedTypeRef>()
|
val explicitType = superReference.superTypeRef
|
||||||
?.firClassLike(context.session)
|
.firClassLike(context.session)
|
||||||
?.followAllAlias(context.session).safeAs<FirClass<*>>()
|
?.followAllAlias(context.session).safeAs<FirClass<*>>()
|
||||||
?: return
|
?: return
|
||||||
|
|
||||||
|
|||||||
+3
-3
@@ -16,7 +16,7 @@ import org.jetbrains.kotlin.fir.expressions.FirQualifiedAccessExpression
|
|||||||
import org.jetbrains.kotlin.fir.references.FirResolvedNamedReference
|
import org.jetbrains.kotlin.fir.references.FirResolvedNamedReference
|
||||||
import org.jetbrains.kotlin.fir.resolve.toSymbol
|
import org.jetbrains.kotlin.fir.resolve.toSymbol
|
||||||
import org.jetbrains.kotlin.fir.types.ConeClassLikeType
|
import org.jetbrains.kotlin.fir.types.ConeClassLikeType
|
||||||
import org.jetbrains.kotlin.fir.types.FirResolvedTypeRef
|
import org.jetbrains.kotlin.fir.types.coneType
|
||||||
import org.jetbrains.kotlin.utils.addToStdlib.safeAs
|
import org.jetbrains.kotlin.utils.addToStdlib.safeAs
|
||||||
|
|
||||||
object FirSealedClassConstructorCallChecker : FirQualifiedAccessChecker() {
|
object FirSealedClassConstructorCallChecker : FirQualifiedAccessChecker() {
|
||||||
@@ -26,8 +26,8 @@ object FirSealedClassConstructorCallChecker : FirQualifiedAccessChecker() {
|
|||||||
?.fir.safeAs<FirConstructor>()
|
?.fir.safeAs<FirConstructor>()
|
||||||
?: return
|
?: return
|
||||||
|
|
||||||
val typeFir = constructorFir.returnTypeRef.safeAs<FirResolvedTypeRef>()
|
val typeFir = constructorFir.returnTypeRef.coneType
|
||||||
?.type.safeAs<ConeClassLikeType>()
|
.safeAs<ConeClassLikeType>()
|
||||||
?.lookupTag?.toSymbol(context.session)
|
?.lookupTag?.toSymbol(context.session)
|
||||||
?.fir as? FirRegularClass
|
?.fir as? FirRegularClass
|
||||||
?: return
|
?: return
|
||||||
|
|||||||
+10
-10
@@ -43,11 +43,11 @@ object FirUpperBoundViolatedChecker : FirQualifiedAccessChecker() {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
val parameterPairs = mutableMapOf<FirTypeParameterSymbol, FirResolvedTypeRef>()
|
val parameterPairs = mutableMapOf<FirTypeParameterSymbol, FirTypeRef>()
|
||||||
|
|
||||||
for (it in 0 until count) {
|
for (it in 0 until count) {
|
||||||
expression.typeArguments[it].safeAs<FirTypeProjectionWithVariance>()
|
expression.typeArguments[it].safeAs<FirTypeProjectionWithVariance>()
|
||||||
?.typeRef.safeAs<FirResolvedTypeRef>()
|
?.typeRef
|
||||||
?.let { that ->
|
?.let { that ->
|
||||||
if (that !is FirErrorTypeRef) {
|
if (that !is FirErrorTypeRef) {
|
||||||
parameterPairs[calleeFir.typeParameters[it].symbol] = that
|
parameterPairs[calleeFir.typeParameters[it].symbol] = that
|
||||||
@@ -60,7 +60,7 @@ object FirUpperBoundViolatedChecker : FirQualifiedAccessChecker() {
|
|||||||
// we substitute actual values to the
|
// we substitute actual values to the
|
||||||
// type parameters from the declaration
|
// type parameters from the declaration
|
||||||
val substitutor = substitutorByMap(
|
val substitutor = substitutorByMap(
|
||||||
parameterPairs.mapValues { it.value.type }
|
parameterPairs.mapValues { it.value.coneType }
|
||||||
)
|
)
|
||||||
|
|
||||||
val typeCheckerContext = context.session.typeContext.newBaseTypeCheckerContext(
|
val typeCheckerContext = context.session.typeContext.newBaseTypeCheckerContext(
|
||||||
@@ -74,14 +74,14 @@ object FirUpperBoundViolatedChecker : FirQualifiedAccessChecker() {
|
|||||||
return@forEach
|
return@forEach
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!satisfiesBounds(proto, actual.type, substitutor, typeCheckerContext)) {
|
if (!satisfiesBounds(proto, actual.coneType, substitutor, typeCheckerContext)) {
|
||||||
reporter.reportOn(actual.source, proto, actual.type, context)
|
reporter.reportOn(actual.source, proto, actual.coneType, context)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
// we must analyze nested things like
|
// we must analyze nested things like
|
||||||
// S<S<K, L>, T<K, L>>()
|
// S<S<K, L>, T<K, L>>()
|
||||||
actual.type.safeAs<ConeClassLikeType>()?.let {
|
actual.coneType.safeAs<ConeClassLikeType>()?.let {
|
||||||
val errorOccurred = analyzeTypeParameters(it, context, reporter, typeCheckerContext, actual.source)
|
val errorOccurred = analyzeTypeParameters(it, context, reporter, typeCheckerContext, actual.source)
|
||||||
|
|
||||||
if (errorOccurred) {
|
if (errorOccurred) {
|
||||||
@@ -125,8 +125,8 @@ object FirUpperBoundViolatedChecker : FirQualifiedAccessChecker() {
|
|||||||
val actualConstructor = functionCall.calleeReference.safeAs<FirResolvedNamedReference>()
|
val actualConstructor = functionCall.calleeReference.safeAs<FirResolvedNamedReference>()
|
||||||
?.resolvedSymbol.safeAs<FirConstructorSymbol>()
|
?.resolvedSymbol.safeAs<FirConstructorSymbol>()
|
||||||
?.fir.safeAs<FirConstructor>()
|
?.fir.safeAs<FirConstructor>()
|
||||||
?.returnTypeRef.safeAs<FirResolvedTypeRef>()
|
?.returnTypeRef?.coneType
|
||||||
?.type.safeAs<ConeClassLikeType>()
|
?.safeAs<ConeClassLikeType>()
|
||||||
?: return
|
?: return
|
||||||
|
|
||||||
val count = min(protoConstructor.typeParameters.size, actualConstructor.typeArguments.size)
|
val count = min(protoConstructor.typeParameters.size, actualConstructor.typeArguments.size)
|
||||||
@@ -158,7 +158,7 @@ object FirUpperBoundViolatedChecker : FirQualifiedAccessChecker() {
|
|||||||
constructorsParameterPairs.forEach { (proto, actual) ->
|
constructorsParameterPairs.forEach { (proto, actual) ->
|
||||||
// just in case
|
// just in case
|
||||||
var intersection = typeCheckerContext.intersectTypes(
|
var intersection = typeCheckerContext.intersectTypes(
|
||||||
proto.fir.bounds.filterIsInstance<FirResolvedTypeRef>().map { it.type }
|
proto.fir.bounds.map { it.coneType }
|
||||||
).safeAs<ConeKotlinType>() ?: return@forEach
|
).safeAs<ConeKotlinType>() ?: return@forEach
|
||||||
|
|
||||||
intersection = declarationSiteSubstitutor.substituteOrSelf(intersection)
|
intersection = declarationSiteSubstitutor.substituteOrSelf(intersection)
|
||||||
@@ -245,7 +245,7 @@ object FirUpperBoundViolatedChecker : FirQualifiedAccessChecker() {
|
|||||||
typeCheckerContext: AbstractTypeCheckerContext
|
typeCheckerContext: AbstractTypeCheckerContext
|
||||||
): Boolean {
|
): Boolean {
|
||||||
var intersection = typeCheckerContext.intersectTypes(
|
var intersection = typeCheckerContext.intersectTypes(
|
||||||
prototypeSymbol.fir.bounds.filterIsInstance<FirResolvedTypeRef>().map { it.type }
|
prototypeSymbol.fir.bounds.map { it.coneType }
|
||||||
).safeAs<ConeKotlinType>() ?: return true
|
).safeAs<ConeKotlinType>() ?: return true
|
||||||
|
|
||||||
intersection = substitutor.substituteOrSelf(intersection)
|
intersection = substitutor.substituteOrSelf(intersection)
|
||||||
|
|||||||
+2
-3
@@ -15,7 +15,6 @@ import org.jetbrains.kotlin.fir.expressions.FirQualifiedAccessExpression
|
|||||||
import org.jetbrains.kotlin.fir.references.FirResolvedNamedReference
|
import org.jetbrains.kotlin.fir.references.FirResolvedNamedReference
|
||||||
import org.jetbrains.kotlin.fir.symbols.impl.FirNamedFunctionSymbol
|
import org.jetbrains.kotlin.fir.symbols.impl.FirNamedFunctionSymbol
|
||||||
import org.jetbrains.kotlin.fir.types.ConeNullability
|
import org.jetbrains.kotlin.fir.types.ConeNullability
|
||||||
import org.jetbrains.kotlin.fir.types.FirResolvedTypeRef
|
|
||||||
import org.jetbrains.kotlin.fir.types.classId
|
import org.jetbrains.kotlin.fir.types.classId
|
||||||
import org.jetbrains.kotlin.fir.types.coneType
|
import org.jetbrains.kotlin.fir.types.coneType
|
||||||
|
|
||||||
@@ -37,9 +36,9 @@ object UselessCallOnNotNullChecker : FirQualifiedAccessChecker() {
|
|||||||
((calleeReference as? FirResolvedNamedReference)?.resolvedSymbol as? FirNamedFunctionSymbol)?.callableId
|
((calleeReference as? FirResolvedNamedReference)?.resolvedSymbol as? FirNamedFunctionSymbol)?.callableId
|
||||||
|
|
||||||
private fun FirExpression.getPackage() =
|
private fun FirExpression.getPackage() =
|
||||||
(typeRef as? FirResolvedTypeRef)?.coneType?.classId?.packageFqName.toString()
|
typeRef.coneType.classId?.packageFqName.toString()
|
||||||
|
|
||||||
private fun FirExpression.getNullability() = (typeRef as FirResolvedTypeRef).type.nullability
|
private fun FirExpression.getNullability() = typeRef.coneType.nullability
|
||||||
|
|
||||||
|
|
||||||
private val triggerOn = setOf(
|
private val triggerOn = setOf(
|
||||||
|
|||||||
Reference in New Issue
Block a user