FIR checkers: use isNullableType() instead of isSubtypeOfAny()

This commit is contained in:
Mikhail Glukhikh
2021-03-11 13:24:18 +03:00
parent 599a0d9c2b
commit 0e8f8362da
3 changed files with 18 additions and 32 deletions
@@ -40,7 +40,6 @@ import org.jetbrains.kotlin.psi.KtModifierList
import org.jetbrains.kotlin.psi.KtParameter
import org.jetbrains.kotlin.psi.KtParameter.VAL_VAR_TOKEN_SET
import org.jetbrains.kotlin.psi.psiUtil.visibilityModifierType
import org.jetbrains.kotlin.types.AbstractTypeChecker
import org.jetbrains.kotlin.utils.addToStdlib.safeAs
/**
@@ -128,7 +127,7 @@ fun ConeKotlinType.toRegularClass(session: FirSession): FirRegularClass? {
return safeAs<ConeClassLikeType>()?.fullyExpandedType(session)?.toRegularClass(session)
}
fun ConeKotlinType.isInline(session: FirSession) : Boolean = toRegularClass(session)?.isInline == true
fun ConeKotlinType.isInline(session: FirSession): Boolean = toRegularClass(session)?.isInline == true
/**
* Returns the FirRegularClass associated with this
@@ -144,7 +143,7 @@ fun FirTypeRef.toRegularClass(session: FirSession): FirRegularClass? {
inline fun <reified T : Any> FirQualifiedAccessExpression.getDeclaration(): T? {
return this.calleeReference.safeAs<FirResolvedNamedReference>()
?.resolvedSymbol
?.fir.safeAs<T>()
?.fir.safeAs()
}
/**
@@ -154,17 +153,6 @@ inline fun <reified T : Any> FirQualifiedAccessExpression.getDeclaration(): T? {
fun FirSymbolOwner<*>.getContainingClass(context: CheckerContext): FirClassLikeDeclaration<*>? =
this.safeAs<FirCallableMemberDeclaration<*>>()?.containingClass()?.toSymbol(context.session)?.fir
/**
* Returns the FirClassLikeDeclaration the type alias is pointing
* to provided `this` is a FirTypeAlias. Returns this otherwise.
*/
fun FirClassLikeDeclaration<*>.followAlias(session: FirSession): FirClassLikeDeclaration<*> {
return this.safeAs<FirTypeAlias>()
?.expandedTypeRef
?.firClassLike(session)
?: return this
}
/**
* Returns the FirClassLikeDeclaration that the
* sequence of FirTypeAlias'es points to starting
@@ -320,10 +308,6 @@ fun Modality.toToken(): KtModifierKeywordToken = when (this) {
val FirFunctionCall.isIterator
get() = this.calleeReference.name.asString() == "<iterator>"
fun ConeKotlinType.isSubtypeOfAny(session: FirSession): Boolean {
return AbstractTypeChecker.isSubtypeOf(session.typeContext, this.fullyExpandedType(session), session.builtinTypes.anyType.type)
}
internal fun throwableClassLikeType(session: FirSession) = session.builtinTypes.throwableType.type
fun ConeKotlinType.isSubtypeOfThrowable(session: FirSession) =
@@ -6,14 +6,13 @@
package org.jetbrains.kotlin.fir.analysis.checkers.declaration
import org.jetbrains.kotlin.fir.FirFakeSourceElementKind
import org.jetbrains.kotlin.fir.FirSession
import org.jetbrains.kotlin.fir.analysis.checkers.context.CheckerContext
import org.jetbrains.kotlin.fir.analysis.checkers.isSubtypeOfAny
import org.jetbrains.kotlin.fir.analysis.diagnostics.DiagnosticReporter
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.diagnostics.ConeTypeParameterInQualifiedAccess
import org.jetbrains.kotlin.fir.resolve.inference.inferenceComponents
import org.jetbrains.kotlin.fir.resolve.inference.isKClassType
import org.jetbrains.kotlin.fir.scopes.impl.toConeType
import org.jetbrains.kotlin.fir.types.*
@@ -40,7 +39,7 @@ object FirKClassWithIncorrectTypeArgumentChecker : FirFileChecker() {
if (source.kind is FirFakeSourceElementKind) return
val returnType = declaration.returnTypeRef.coneType
if (!returnType.isKClassTypeWithErrorOrNullableArgument(context.session)) return
if (!returnType.isKClassTypeWithErrorOrNullableArgument(context.session.inferenceComponents.ctx)) return
val typeArgument = (returnType.typeArguments[0] as ConeKotlinTypeProjection).type
typeArgument.typeParameterFromError?.let {
@@ -48,7 +47,7 @@ object FirKClassWithIncorrectTypeArgumentChecker : FirFileChecker() {
}
}
private fun ConeKotlinType.isKClassTypeWithErrorOrNullableArgument(session: FirSession): Boolean {
private fun ConeKotlinType.isKClassTypeWithErrorOrNullableArgument(context: ConeInferenceContext): Boolean {
if (!this.isKClassType()) return false
val argumentType = typeArguments.toList().singleOrNull()?.let {
when (it) {
@@ -56,10 +55,12 @@ object FirKClassWithIncorrectTypeArgumentChecker : FirFileChecker() {
is ConeKotlinTypeProjection -> it.type
}
} ?: return false
argumentType.typeParameterFromError?.let { typeParameter ->
return !typeParameter.toConeType().isSubtypeOfAny(session)
with(context) {
argumentType.typeParameterFromError?.let { typeParameter ->
return typeParameter.toConeType().isNullableType()
}
return argumentType is ConeKotlinErrorType || argumentType.isNullableType()
}
return argumentType is ConeKotlinErrorType || !argumentType.isSubtypeOfAny(session)
}
private val ConeKotlinType.typeParameterFromError: FirTypeParameter?
@@ -6,9 +6,7 @@
package org.jetbrains.kotlin.fir.analysis.checkers.expression
import org.jetbrains.kotlin.fir.FirFakeSourceElementKind
import org.jetbrains.kotlin.fir.FirSession
import org.jetbrains.kotlin.fir.analysis.checkers.context.CheckerContext
import org.jetbrains.kotlin.fir.analysis.checkers.isSubtypeOfAny
import org.jetbrains.kotlin.fir.analysis.diagnostics.DiagnosticReporter
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors
import org.jetbrains.kotlin.fir.analysis.diagnostics.reportOn
@@ -17,6 +15,7 @@ import org.jetbrains.kotlin.fir.declarations.FirTypeParameter
import org.jetbrains.kotlin.fir.declarations.FirTypeParameterRefsOwner
import org.jetbrains.kotlin.fir.expressions.*
import org.jetbrains.kotlin.fir.references.FirResolvedNamedReference
import org.jetbrains.kotlin.fir.resolve.inference.inferenceComponents
import org.jetbrains.kotlin.fir.scopes.impl.toConeType
import org.jetbrains.kotlin.fir.symbols.impl.FirTypeParameterSymbol
import org.jetbrains.kotlin.fir.types.*
@@ -42,7 +41,7 @@ object FirGetClassCallChecker : FirBasicExpressionChecker() {
val isNullable = markedNullable ||
(argument as? FirResolvedQualifier)?.isNullableLHSForCallableReference == true ||
argument.typeRef.coneType.isMarkedNullable ||
argument.typeRef.coneType.isNullableTypeParameter(context.session)
argument.typeRef.coneType.isNullableTypeParameter(context.session.inferenceComponents.ctx)
if (isNullable) {
if (argument.canBeDoubleColonLHSAsType) {
reporter.reportOn(source, FirErrors.NULLABLE_TYPE_IN_CLASS_LITERAL_LHS, context)
@@ -78,12 +77,14 @@ object FirGetClassCallChecker : FirBasicExpressionChecker() {
}
}
private fun ConeKotlinType.isNullableTypeParameter(session: FirSession): Boolean {
private fun ConeKotlinType.isNullableTypeParameter(context: ConeInferenceContext): Boolean {
if (this !is ConeTypeParameterType) return false
val typeParameter = lookupTag.typeParameterSymbol.fir
return !typeParameter.isReified &&
// E.g., fun <T> f2(t: T): Any = t::class
!typeParameter.toConeType().isSubtypeOfAny(session)
with(context) {
return !typeParameter.isReified &&
// E.g., fun <T> f2(t: T): Any = t::class
typeParameter.toConeType().isNullableType()
}
}
private val FirExpression.canBeDoubleColonLHSAsType: Boolean