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.impl.FirEmptyExpressionBlock
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.toSymbol
import org.jetbrains.kotlin.fir.resolve.transformers.firClassLike
import org.jetbrains.kotlin.fir.scopes.ProcessorAction
import org.jetbrains.kotlin.fir.scopes.processOverriddenFunctions
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.FirNamedFunctionSymbol
import org.jetbrains.kotlin.fir.symbols.impl.FirRegularClassSymbol
import org.jetbrains.kotlin.fir.typeCheckerContext
import org.jetbrains.kotlin.fir.types.*
import org.jetbrains.kotlin.lexer.KtModifierKeywordToken
import org.jetbrains.kotlin.lexer.KtTokens
import org.jetbrains.kotlin.psi.KtModifierList
import org.jetbrains.kotlin.psi.KtObjectLiteralExpression
import org.jetbrains.kotlin.psi.psiUtil.visibilityModifierType
import org.jetbrains.kotlin.utils.addToStdlib.safeAs
@@ -132,7 +128,7 @@ fun ConeKotlinType.toRegularClass(session: FirSession): FirRegularClass? {
* or null of something goes wrong.
*/
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.
*/
fun FirClass<*>.findNonInterfaceSupertype(context: CheckerContext): FirTypeRef? {
for (it in superTypeRefs) {
val lookupTag = it.safeAs<FirResolvedTypeRef>()
?.type.safeAs<ConeClassLikeType>()
?.lookupTag
?: continue
for (superTypeRef in superTypeRefs) {
val lookupTag = superTypeRef.coneType.safeAs<ConeClassLikeType>()?.lookupTag ?: continue
val fir = lookupTag.toSymbol(context.session)
?.fir.safeAs<FirClass<*>>()
?: continue
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) {
// 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>()
?.coneTypeSafe<ConeClassLikeType>()
?.lookupTag
@@ -136,8 +136,7 @@ object FirOverrideChecker : FirRegularClassChecker() {
typeCheckerContext: AbstractTypeCheckerContext,
context: CheckerContext,
): FirMemberDeclaration? {
val overridingReturnType = returnTypeRef.safeAs<FirResolvedTypeRef>()?.type
?: return null
val overridingReturnType = returnTypeRef.coneType
// Don't report *_ON_OVERRIDE diagnostics according to an error return type. That should be reported separately.
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.declarations.*
import org.jetbrains.kotlin.fir.resolve.firSymbolProvider
import org.jetbrains.kotlin.fir.types.ConeClassLikeType
import org.jetbrains.kotlin.fir.types.FirResolvedTypeRef
import org.jetbrains.kotlin.fir.types.classId
import org.jetbrains.kotlin.fir.types.coneType
import org.jetbrains.kotlin.utils.addToStdlib.safeAs
object FirSealedSupertypeChecker : FirMemberDeclarationChecker() {
@@ -41,10 +41,7 @@ object FirSealedSupertypeChecker : FirMemberDeclarationChecker() {
private fun checkTopLevelDeclaration(declaration: FirClass<*>, context: CheckerContext, reporter: DiagnosticReporter) {
for (it in declaration.superTypeRefs) {
val classId = it.safeAs<FirResolvedTypeRef>()
?.type.safeAs<ConeClassLikeType>()
?.lookupTag?.classId
?: continue
val classId = it.coneType.classId ?: continue
if (classId.isLocal) {
continue
@@ -63,10 +60,7 @@ object FirSealedSupertypeChecker : FirMemberDeclarationChecker() {
private fun checkLocalDeclaration(declaration: FirClass<*>, context: CheckerContext, reporter: DiagnosticReporter) {
for (it in declaration.superTypeRefs) {
val classId = it.safeAs<FirResolvedTypeRef>()
?.type.safeAs<ConeClassLikeType>()
?.lookupTag?.classId
?: continue
val classId = it.coneType.classId ?: continue
if (classId.isLocal) {
continue
@@ -85,10 +79,7 @@ object FirSealedSupertypeChecker : FirMemberDeclarationChecker() {
private fun checkInnerDeclaration(declaration: FirClass<*>, context: CheckerContext, reporter: DiagnosticReporter) {
for (it in declaration.superTypeRefs) {
val classId = it.safeAs<FirResolvedTypeRef>()
?.type.safeAs<ConeClassLikeType>()
?.lookupTag?.classId
?: continue
val classId = it.coneType.classId ?: continue
if (classId.isLocal) {
continue
@@ -25,6 +25,7 @@ object FirCatchParameterChecker : FirTryExpressionChecker() {
}
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
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.references.FirSuperReference
import org.jetbrains.kotlin.fir.resolve.transformers.firClassLike
import org.jetbrains.kotlin.fir.types.FirResolvedTypeRef
import org.jetbrains.kotlin.utils.addToStdlib.safeAs
object FirQualifiedSupertypeExtendedByOtherSupertypeChecker : FirQualifiedAccessChecker() {
@@ -26,8 +25,8 @@ object FirQualifiedSupertypeExtendedByOtherSupertypeChecker : FirQualifiedAccess
?.takeIf { it.hadExplicitTypeInSource() }
?: return
val explicitType = superReference.superTypeRef.safeAs<FirResolvedTypeRef>()
?.firClassLike(context.session)
val explicitType = superReference.superTypeRef
.firClassLike(context.session)
?.followAllAlias(context.session).safeAs<FirClass<*>>()
?: return
@@ -16,7 +16,7 @@ import org.jetbrains.kotlin.fir.expressions.FirQualifiedAccessExpression
import org.jetbrains.kotlin.fir.references.FirResolvedNamedReference
import org.jetbrains.kotlin.fir.resolve.toSymbol
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
object FirSealedClassConstructorCallChecker : FirQualifiedAccessChecker() {
@@ -26,8 +26,8 @@ object FirSealedClassConstructorCallChecker : FirQualifiedAccessChecker() {
?.fir.safeAs<FirConstructor>()
?: return
val typeFir = constructorFir.returnTypeRef.safeAs<FirResolvedTypeRef>()
?.type.safeAs<ConeClassLikeType>()
val typeFir = constructorFir.returnTypeRef.coneType
.safeAs<ConeClassLikeType>()
?.lookupTag?.toSymbol(context.session)
?.fir as? FirRegularClass
?: return
@@ -43,11 +43,11 @@ object FirUpperBoundViolatedChecker : FirQualifiedAccessChecker() {
return
}
val parameterPairs = mutableMapOf<FirTypeParameterSymbol, FirResolvedTypeRef>()
val parameterPairs = mutableMapOf<FirTypeParameterSymbol, FirTypeRef>()
for (it in 0 until count) {
expression.typeArguments[it].safeAs<FirTypeProjectionWithVariance>()
?.typeRef.safeAs<FirResolvedTypeRef>()
?.typeRef
?.let { that ->
if (that !is FirErrorTypeRef) {
parameterPairs[calleeFir.typeParameters[it].symbol] = that
@@ -60,7 +60,7 @@ object FirUpperBoundViolatedChecker : FirQualifiedAccessChecker() {
// we substitute actual values to the
// type parameters from the declaration
val substitutor = substitutorByMap(
parameterPairs.mapValues { it.value.type }
parameterPairs.mapValues { it.value.coneType }
)
val typeCheckerContext = context.session.typeContext.newBaseTypeCheckerContext(
@@ -74,14 +74,14 @@ object FirUpperBoundViolatedChecker : FirQualifiedAccessChecker() {
return@forEach
}
if (!satisfiesBounds(proto, actual.type, substitutor, typeCheckerContext)) {
reporter.reportOn(actual.source, proto, actual.type, context)
if (!satisfiesBounds(proto, actual.coneType, substitutor, typeCheckerContext)) {
reporter.reportOn(actual.source, proto, actual.coneType, context)
return
}
// we must analyze nested things like
// 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)
if (errorOccurred) {
@@ -125,8 +125,8 @@ object FirUpperBoundViolatedChecker : FirQualifiedAccessChecker() {
val actualConstructor = functionCall.calleeReference.safeAs<FirResolvedNamedReference>()
?.resolvedSymbol.safeAs<FirConstructorSymbol>()
?.fir.safeAs<FirConstructor>()
?.returnTypeRef.safeAs<FirResolvedTypeRef>()
?.type.safeAs<ConeClassLikeType>()
?.returnTypeRef?.coneType
?.safeAs<ConeClassLikeType>()
?: return
val count = min(protoConstructor.typeParameters.size, actualConstructor.typeArguments.size)
@@ -158,7 +158,7 @@ object FirUpperBoundViolatedChecker : FirQualifiedAccessChecker() {
constructorsParameterPairs.forEach { (proto, actual) ->
// just in case
var intersection = typeCheckerContext.intersectTypes(
proto.fir.bounds.filterIsInstance<FirResolvedTypeRef>().map { it.type }
proto.fir.bounds.map { it.coneType }
).safeAs<ConeKotlinType>() ?: return@forEach
intersection = declarationSiteSubstitutor.substituteOrSelf(intersection)
@@ -245,7 +245,7 @@ object FirUpperBoundViolatedChecker : FirQualifiedAccessChecker() {
typeCheckerContext: AbstractTypeCheckerContext
): Boolean {
var intersection = typeCheckerContext.intersectTypes(
prototypeSymbol.fir.bounds.filterIsInstance<FirResolvedTypeRef>().map { it.type }
prototypeSymbol.fir.bounds.map { it.coneType }
).safeAs<ConeKotlinType>() ?: return true
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.symbols.impl.FirNamedFunctionSymbol
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.coneType
@@ -37,9 +36,9 @@ object UselessCallOnNotNullChecker : FirQualifiedAccessChecker() {
((calleeReference as? FirResolvedNamedReference)?.resolvedSymbol as? FirNamedFunctionSymbol)?.callableId
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(