FIR checker: report expression of nullable type parameter as LHS of class literals

This commit is contained in:
Jinseong Jeon
2021-03-08 23:53:21 -08:00
committed by Mikhail Glukhikh
parent 26441ed64f
commit 4c08d10cce
4 changed files with 16 additions and 16 deletions
@@ -6,7 +6,9 @@
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
@@ -15,6 +17,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.scopes.impl.toConeType
import org.jetbrains.kotlin.fir.symbols.impl.FirTypeParameterSymbol
import org.jetbrains.kotlin.fir.types.*
import org.jetbrains.kotlin.lexer.KtTokens.QUEST
@@ -38,7 +41,8 @@ object FirGetClassCallChecker : FirBasicExpressionChecker() {
val argument = expression.argument
val isNullable = markedNullable ||
(argument as? FirResolvedQualifier)?.isNullableLHSForCallableReference == true ||
argument.typeRef.coneType.isMarkedNullable
argument.typeRef.coneType.isMarkedNullable ||
argument.typeRef.coneType.isNullableTypeParameter(context.session)
if (isNullable) {
if (argument.canBeDoubleColonLHSAsType) {
reporter.reportOn(source, FirErrors.NULLABLE_TYPE_IN_CLASS_LITERAL_LHS, context)
@@ -74,6 +78,14 @@ object FirGetClassCallChecker : FirBasicExpressionChecker() {
}
}
private fun ConeKotlinType.isNullableTypeParameter(session: FirSession): 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)
}
private val FirExpression.canBeDoubleColonLHSAsType: Boolean
get() {
return this is FirResolvedQualifier ||
@@ -1,15 +0,0 @@
// FILE: J.java
public interface J {
String platformString();
}
// FILE: test.kt
fun f1(x: Int?): Any = <!EXPRESSION_OF_NULLABLE_TYPE_IN_CLASS_LITERAL_LHS!>x<!>::class
fun <T> f2(t: T): Any = t::class
fun <S : String?> f3(s: S): Any = s::class
fun <U : Any> f4(u: U?): Any = <!EXPRESSION_OF_NULLABLE_TYPE_IN_CLASS_LITERAL_LHS!>u<!>::class
fun f5(c: List<*>): Any = <!EXPRESSION_OF_NULLABLE_TYPE_IN_CLASS_LITERAL_LHS!>c[0]<!>::class
fun f6(j: J): Any = j.platformString()::class
@@ -1,3 +1,4 @@
// FIR_IDENTICAL
// FILE: J.java
public interface J {
@@ -8,6 +9,7 @@ public interface J {
fun f1(x: Int?): Any = <!EXPRESSION_OF_NULLABLE_TYPE_IN_CLASS_LITERAL_LHS!>x<!>::class
fun <T> f2(t: T): Any = <!EXPRESSION_OF_NULLABLE_TYPE_IN_CLASS_LITERAL_LHS!>t<!>::class
fun <T> f21(t: T): Any where T : Any?, T : Comparable<T> = t::class
fun <S : String?> f3(s: S): Any = <!EXPRESSION_OF_NULLABLE_TYPE_IN_CLASS_LITERAL_LHS!>s<!>::class
fun <U : Any> f4(u: U?): Any = <!EXPRESSION_OF_NULLABLE_TYPE_IN_CLASS_LITERAL_LHS!>u<!>::class
fun f5(c: List<*>): Any = <!EXPRESSION_OF_NULLABLE_TYPE_IN_CLASS_LITERAL_LHS!>c[0]<!>::class
@@ -2,6 +2,7 @@ package
public fun f1(/*0*/ x: kotlin.Int?): kotlin.Any
public fun </*0*/ T> f2(/*0*/ t: T): kotlin.Any
public fun </*0*/ T> f21(/*0*/ t: T): kotlin.Any where T : kotlin.Comparable<T>
public fun </*0*/ S : kotlin.String?> f3(/*0*/ s: S): kotlin.Any
public fun </*0*/ U : kotlin.Any> f4(/*0*/ u: U?): kotlin.Any
public fun f5(/*0*/ c: kotlin.collections.List<*>): kotlin.Any