FIR checker: avoid redundant casting to resolved type ref

This commit is contained in:
Jinseong Jeon
2021-02-06 22:59:37 -08:00
committed by Dmitriy Novozhilov
parent 37a702b962
commit a9322a01ce
9 changed files with 30 additions and 46 deletions
@@ -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
} }
} }
@@ -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
@@ -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) {
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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)
@@ -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(