[FIR] Properly check constructor call in FirConstCheckVisitor
This commit is contained in:
+1
-1
@@ -1,5 +1,5 @@
|
||||
// Should be something like TYPE_MISMATCH here
|
||||
<!WRONG_ANNOTATION_TARGET_WITH_USE_SITE_TARGET!>@file:Some(return x)<!>
|
||||
<!WRONG_ANNOTATION_TARGET_WITH_USE_SITE_TARGET!>@file:Some(<!ANNOTATION_ARGUMENT_MUST_BE_CONST!>return x<!>)<!>
|
||||
|
||||
const val x = 42
|
||||
|
||||
|
||||
+32
-33
@@ -44,36 +44,7 @@ internal fun checkConstantArguments(
|
||||
session: FirSession,
|
||||
): ConstantArgumentKind {
|
||||
if (expression == null) return ConstantArgumentKind.VALID_CONST
|
||||
|
||||
val firConstCheckVisitor = FirConstCheckVisitor(session)
|
||||
|
||||
val expressionSymbol = expression.toReference()?.toResolvedCallableSymbol(discardErrorReference = true)
|
||||
val classKindOfParent = with(firConstCheckVisitor) {
|
||||
(expressionSymbol?.getReferencedClassSymbol() as? FirRegularClassSymbol)?.classKind
|
||||
}
|
||||
|
||||
fun FirExpression.getExpandedType() = resolvedType.fullyExpandedType(session)
|
||||
|
||||
when {
|
||||
expressionSymbol is FirConstructorSymbol && classKindOfParent == ClassKind.ANNOTATION_CLASS -> {
|
||||
return ConstantArgumentKind.VALID_CONST
|
||||
}
|
||||
expressionSymbol == null -> {
|
||||
return ConstantArgumentKind.VALID_CONST
|
||||
}
|
||||
expressionSymbol is FirConstructorSymbol -> {
|
||||
if (expression is FirCallableReferenceAccess) return ConstantArgumentKind.VALID_CONST
|
||||
if (expression.getExpandedType().isUnsignedType) {
|
||||
(expression as FirFunctionCall).arguments.forEach { argumentExpression ->
|
||||
checkConstantArguments(argumentExpression, session).ifNotValidConst { return it }
|
||||
}
|
||||
} else {
|
||||
return ConstantArgumentKind.NOT_CONST
|
||||
}
|
||||
}
|
||||
else -> return expression.accept(firConstCheckVisitor, null)
|
||||
}
|
||||
return ConstantArgumentKind.VALID_CONST
|
||||
return expression.accept(FirConstCheckVisitor(session), null)
|
||||
}
|
||||
|
||||
internal enum class ConstantArgumentKind {
|
||||
@@ -276,8 +247,14 @@ private class FirConstCheckVisitor(private val session: FirSession) : FirVisitor
|
||||
}
|
||||
|
||||
if (calleeReference !is FirResolvedNamedReference) return ConstantArgumentKind.NOT_CONST
|
||||
val symbol = calleeReference.resolvedSymbol as? FirNamedFunctionSymbol ?: return ConstantArgumentKind.NOT_CONST
|
||||
return when (val symbol = calleeReference.resolvedSymbol) {
|
||||
is FirNamedFunctionSymbol -> visitNamedFunction(functionCall, symbol)
|
||||
is FirConstructorSymbol -> visitConstructorCall(functionCall, symbol)
|
||||
else -> ConstantArgumentKind.NOT_CONST
|
||||
}
|
||||
}
|
||||
|
||||
private fun visitNamedFunction(functionCall: FirFunctionCall, symbol: FirNamedFunctionSymbol): ConstantArgumentKind {
|
||||
if (!symbol.canBeEvaluated() && !functionCall.isCompileTimeBuiltinCall()) {
|
||||
return ConstantArgumentKind.NOT_CONST
|
||||
}
|
||||
@@ -290,12 +267,26 @@ private class FirConstCheckVisitor(private val session: FirSession) : FirVisitor
|
||||
return ConstantArgumentKind.NOT_CONST
|
||||
}
|
||||
|
||||
exp.accept(this, data).ifNotValidConst { return it }
|
||||
exp.accept(this, null).ifNotValidConst { return it }
|
||||
}
|
||||
|
||||
return ConstantArgumentKind.VALID_CONST
|
||||
}
|
||||
|
||||
private fun visitConstructorCall(constructorCall: FirFunctionCall, symbol: FirConstructorSymbol): ConstantArgumentKind {
|
||||
val classKindOfParent = (symbol.getReferencedClassSymbol() as? FirRegularClassSymbol)?.classKind
|
||||
return when {
|
||||
classKindOfParent == ClassKind.ANNOTATION_CLASS -> ConstantArgumentKind.VALID_CONST
|
||||
constructorCall.getExpandedType().isUnsignedType -> {
|
||||
constructorCall.arguments.forEach { argumentExpression ->
|
||||
argumentExpression.accept(this, null).ifNotValidConst { return it }
|
||||
}
|
||||
ConstantArgumentKind.VALID_CONST
|
||||
}
|
||||
else -> ConstantArgumentKind.NOT_CONST
|
||||
}
|
||||
}
|
||||
|
||||
override fun visitQualifiedAccessExpression(
|
||||
qualifiedAccessExpression: FirQualifiedAccessExpression, data: Nothing?
|
||||
): ConstantArgumentKind {
|
||||
@@ -307,6 +298,14 @@ private class FirConstCheckVisitor(private val session: FirSession) : FirVisitor
|
||||
return ConstantArgumentKind.VALID_CONST
|
||||
}
|
||||
|
||||
override fun visitResolvedQualifier(resolvedQualifier: FirResolvedQualifier, data: Nothing?): ConstantArgumentKind {
|
||||
return ConstantArgumentKind.VALID_CONST
|
||||
}
|
||||
|
||||
override fun visitCallableReferenceAccess(callableReferenceAccess: FirCallableReferenceAccess, data: Nothing?): ConstantArgumentKind {
|
||||
return visitQualifiedAccessExpression(callableReferenceAccess, data)
|
||||
}
|
||||
|
||||
// --- Utils ---
|
||||
private fun FirBasedSymbol<*>.canBeEvaluated(): Boolean {
|
||||
return intrinsicConstEvaluation && this.hasAnnotation(StandardClassIds.Annotations.IntrinsicConstEvaluation, session)
|
||||
@@ -352,7 +351,7 @@ private class FirConstCheckVisitor(private val session: FirSession) : FirVisitor
|
||||
return this?.callableId?.packageName?.asString() == "kotlin"
|
||||
}
|
||||
|
||||
fun FirCallableSymbol<*>?.getReferencedClassSymbol(): FirBasedSymbol<*>? =
|
||||
private fun FirCallableSymbol<*>?.getReferencedClassSymbol(): FirBasedSymbol<*>? =
|
||||
this?.resolvedReturnTypeRef
|
||||
?.coneTypeSafe<ConeLookupTagBasedType>()
|
||||
?.lookupTag
|
||||
|
||||
+2
-2
@@ -3,14 +3,14 @@
|
||||
@Target(AnnotationTarget.TYPE)
|
||||
annotation class Ann(val x: Int)
|
||||
|
||||
class A<T: @Ann(<!ARGUMENT_TYPE_MISMATCH!>{
|
||||
class A<T: @Ann(<!ANNOTATION_ARGUMENT_MUST_BE_CONST, ARGUMENT_TYPE_MISMATCH!>{
|
||||
fun local() = 1
|
||||
var result = local()
|
||||
result += 1
|
||||
result
|
||||
}<!>) Any>
|
||||
|
||||
fun f(x: @Ann(<!ARGUMENT_TYPE_MISMATCH!>{
|
||||
fun f(x: @Ann(<!ANNOTATION_ARGUMENT_MUST_BE_CONST, ARGUMENT_TYPE_MISMATCH!>{
|
||||
fun local() = 1
|
||||
var result = local()
|
||||
result += 1
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
// ISSUE: KT-59110
|
||||
|
||||
<!WRONG_ANNOTATION_TARGET!>@Target(<!ARGUMENT_TYPE_MISMATCH!>{}<!>)<!>
|
||||
<!WRONG_ANNOTATION_TARGET!>@Target(<!ANNOTATION_ARGUMENT_MUST_BE_CONST, ARGUMENT_TYPE_MISMATCH!>{}<!>)<!>
|
||||
interface SomeInterface {
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user