K2: add inline JVM target version checker
#KT-60777 Fixed
This commit is contained in:
committed by
Space Team
parent
d475371394
commit
3bb2ea10b6
+7
@@ -193,6 +193,13 @@ object JVM_DIAGNOSTICS_LIST : DiagnosticList("FirJvmErrors") {
|
||||
}
|
||||
}
|
||||
|
||||
val INLINE by object : DiagnosticGroup("Inline") {
|
||||
val INLINE_FROM_HIGHER_PLATFORM by error<PsiElement> {
|
||||
parameter<String>("inlinedBytecodeVersion")
|
||||
parameter<String>("currentModuleBytecodeVersion")
|
||||
}
|
||||
}
|
||||
|
||||
val MISC by object : DiagnosticGroup("Misc") {
|
||||
val INAPPLICABLE_JVM_FIELD by error<KtAnnotationEntry> {
|
||||
parameter<String>("message")
|
||||
|
||||
+3
@@ -127,6 +127,9 @@ object FirJvmErrors {
|
||||
// Suspension Point
|
||||
val SUSPENSION_POINT_INSIDE_CRITICAL_SECTION: KtDiagnosticFactory1<FirCallableSymbol<*>> by error1<PsiElement, FirCallableSymbol<*>>(SourceElementPositioningStrategies.REFERENCE_BY_QUALIFIED)
|
||||
|
||||
// Inline
|
||||
val INLINE_FROM_HIGHER_PLATFORM: KtDiagnosticFactory2<String, String> by error2<PsiElement, String, String>()
|
||||
|
||||
// Misc
|
||||
val INAPPLICABLE_JVM_FIELD: KtDiagnosticFactory1<String> by error1<KtAnnotationEntry, String>()
|
||||
val INAPPLICABLE_JVM_FIELD_WARNING: KtDiagnosticFactory1<String> by warning1<KtAnnotationEntry, String>()
|
||||
|
||||
+7
@@ -32,6 +32,7 @@ import org.jetbrains.kotlin.fir.analysis.diagnostics.jvm.FirJvmErrors.ILLEGAL_JV
|
||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.jvm.FirJvmErrors.INAPPLICABLE_JVM_FIELD
|
||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.jvm.FirJvmErrors.INAPPLICABLE_JVM_FIELD_WARNING
|
||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.jvm.FirJvmErrors.INAPPLICABLE_JVM_NAME
|
||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.jvm.FirJvmErrors.INLINE_FROM_HIGHER_PLATFORM
|
||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.jvm.FirJvmErrors.INNER_JVM_RECORD
|
||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.jvm.FirJvmErrors.INTERFACE_CANT_CALL_DEFAULT_METHOD_VIA_SUPER
|
||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.jvm.FirJvmErrors.JAVA_MODULE_DOES_NOT_DEPEND_ON_MODULE
|
||||
@@ -303,6 +304,12 @@ object FirJvmErrorsDefaultMessages : BaseDiagnosticRendererFactory() {
|
||||
"The ''{0}'' suspension point is inside a critical section.",
|
||||
DECLARATION_NAME
|
||||
)
|
||||
map.put(
|
||||
INLINE_FROM_HIGHER_PLATFORM,
|
||||
"Cannot inline bytecode built with {0} into bytecode that is being built with {1}. Please specify proper ''-jvm-target'' option.",
|
||||
STRING,
|
||||
STRING
|
||||
)
|
||||
map.put(
|
||||
CONCURRENT_HASH_MAP_CONTAINS_OPERATOR,
|
||||
"Method 'contains' from ConcurrentHashMap might have unexpected semantics: it calls 'containsValue' instead of 'containsKey'. " +
|
||||
|
||||
+1
@@ -21,6 +21,7 @@ object JvmExpressionCheckers : ExpressionCheckers() {
|
||||
FirJavaSamInterfaceConstructorReferenceChecker,
|
||||
FirQualifiedAccessJavaNullabilityWarningChecker,
|
||||
FirJvmModuleAccessibilityQualifiedAccessChecker,
|
||||
FirJvmInlineTargetQualifiedAccessChecker,
|
||||
)
|
||||
|
||||
override val propertyAccessExpressionCheckers: Set<FirPropertyAccessExpressionChecker>
|
||||
|
||||
+85
@@ -0,0 +1,85 @@
|
||||
/*
|
||||
* Copyright 2010-2024 JetBrains s.r.o. and Kotlin Programming Language contributors.
|
||||
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
|
||||
*/
|
||||
|
||||
package org.jetbrains.kotlin.fir.analysis.jvm.checkers.expression
|
||||
|
||||
import org.jetbrains.kotlin.config.JvmTarget
|
||||
import org.jetbrains.kotlin.diagnostics.DiagnosticReporter
|
||||
import org.jetbrains.kotlin.diagnostics.reportOn
|
||||
import org.jetbrains.kotlin.fir.FirElement
|
||||
import org.jetbrains.kotlin.fir.analysis.checkers.MppCheckerKind
|
||||
import org.jetbrains.kotlin.fir.analysis.checkers.context.CheckerContext
|
||||
import org.jetbrains.kotlin.fir.analysis.checkers.expression.FirQualifiedAccessExpressionChecker
|
||||
import org.jetbrains.kotlin.fir.analysis.checkers.isLhsOfAssignment
|
||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.jvm.FirJvmErrors
|
||||
import org.jetbrains.kotlin.fir.containingClassLookupTag
|
||||
import org.jetbrains.kotlin.fir.declarations.utils.isInline
|
||||
import org.jetbrains.kotlin.fir.declarations.utils.sourceElement
|
||||
import org.jetbrains.kotlin.fir.expressions.FirQualifiedAccessExpression
|
||||
import org.jetbrains.kotlin.fir.expressions.toReference
|
||||
import org.jetbrains.kotlin.fir.java.jvmTargetProvider
|
||||
import org.jetbrains.kotlin.fir.references.toResolvedCallableSymbol
|
||||
import org.jetbrains.kotlin.fir.resolve.toFirRegularClassSymbol
|
||||
import org.jetbrains.kotlin.fir.symbols.SymbolInternals
|
||||
import org.jetbrains.kotlin.fir.symbols.impl.FirCallableSymbol
|
||||
import org.jetbrains.kotlin.fir.symbols.impl.FirFunctionSymbol
|
||||
import org.jetbrains.kotlin.fir.symbols.impl.FirPropertySymbol
|
||||
import org.jetbrains.kotlin.load.kotlin.FileBasedKotlinClass
|
||||
import org.jetbrains.kotlin.load.kotlin.JvmPackagePartSource
|
||||
import org.jetbrains.kotlin.load.kotlin.KotlinJvmBinarySourceElement
|
||||
|
||||
object FirJvmInlineTargetQualifiedAccessChecker : FirQualifiedAccessExpressionChecker(MppCheckerKind.Common) {
|
||||
override fun check(expression: FirQualifiedAccessExpression, context: CheckerContext, reporter: DiagnosticReporter) {
|
||||
val callableSymbol = expression.calleeReference.toResolvedCallableSymbol() ?: return
|
||||
if (callableSymbol.origin.fromSource) return
|
||||
|
||||
val isInline = when (callableSymbol) {
|
||||
is FirFunctionSymbol<*> -> callableSymbol.isInline
|
||||
is FirPropertySymbol -> {
|
||||
val accessor = if (expression.isLhsOfAssignment(context)) callableSymbol.setterSymbol else callableSymbol.getterSymbol
|
||||
accessor != null && accessor.isInline
|
||||
}
|
||||
else -> false
|
||||
}
|
||||
|
||||
if (isInline) {
|
||||
checkInlineTargetVersion(callableSymbol, context, reporter, expression)
|
||||
}
|
||||
}
|
||||
|
||||
private fun checkInlineTargetVersion(
|
||||
callableSymbol: FirCallableSymbol<*>,
|
||||
context: CheckerContext,
|
||||
reporter: DiagnosticReporter,
|
||||
element: FirElement,
|
||||
) {
|
||||
val currentJvmTarget = context.session.jvmTargetProvider?.jvmTarget ?: return
|
||||
|
||||
val containingClass = callableSymbol.containingClassLookupTag()
|
||||
val binaryClass = if (containingClass != null) {
|
||||
val containingClassSymbol = containingClass.toFirRegularClassSymbol(context.session) ?: return
|
||||
|
||||
@OptIn(SymbolInternals::class)
|
||||
val sourceElement = containingClassSymbol.fir.sourceElement as? KotlinJvmBinarySourceElement ?: return
|
||||
sourceElement.binaryClass
|
||||
} else {
|
||||
val containerSource = callableSymbol.containerSource as? JvmPackagePartSource ?: return
|
||||
containerSource.knownJvmBinaryClass
|
||||
}
|
||||
|
||||
val inlinedVersion = (binaryClass as? FileBasedKotlinClass)?.classVersion ?: return
|
||||
val currentVersion = currentJvmTarget.majorVersion
|
||||
|
||||
if (currentVersion < inlinedVersion) {
|
||||
reporter.reportOn(
|
||||
element.toReference(context.session)?.source ?: element.source,
|
||||
FirJvmErrors.INLINE_FROM_HIGHER_PLATFORM,
|
||||
JvmTarget.getDescription(inlinedVersion),
|
||||
JvmTarget.getDescription(currentVersion),
|
||||
context,
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
+1
@@ -561,6 +561,7 @@ val FIR_NON_SUPPRESSIBLE_ERROR_NAMES: Set<String> = setOf(
|
||||
"INLINE_PROPERTY_WITH_BACKING_FIELD",
|
||||
"ILLEGAL_INLINE_PARAMETER_MODIFIER",
|
||||
"INLINE_SUSPEND_FUNCTION_TYPE_UNSUPPORTED",
|
||||
"INLINE_FROM_HIGHER_PLATFORM",
|
||||
"CANNOT_ALL_UNDER_IMPORT_FROM_SINGLETON",
|
||||
"PACKAGE_CANNOT_BE_IMPORTED",
|
||||
"CANNOT_BE_IMPORTED",
|
||||
|
||||
Reference in New Issue
Block a user