K1 JVM: simplify InlinePlatformCompatibilityChecker

This commit is contained in:
Alexander Udalov
2023-08-05 00:49:48 +02:00
committed by Space Team
parent 596aab1673
commit bacb2f0d15
@@ -18,8 +18,6 @@ package org.jetbrains.kotlin.resolve.jvm.checkers
import com.intellij.psi.PsiElement import com.intellij.psi.PsiElement
import org.jetbrains.kotlin.config.JvmTarget import org.jetbrains.kotlin.config.JvmTarget
import org.jetbrains.kotlin.config.LanguageFeature
import org.jetbrains.kotlin.config.LanguageVersionSettings
import org.jetbrains.kotlin.descriptors.CallableMemberDescriptor import org.jetbrains.kotlin.descriptors.CallableMemberDescriptor
import org.jetbrains.kotlin.descriptors.ClassOrPackageFragmentDescriptor import org.jetbrains.kotlin.descriptors.ClassOrPackageFragmentDescriptor
import org.jetbrains.kotlin.descriptors.DeclarationDescriptor import org.jetbrains.kotlin.descriptors.DeclarationDescriptor
@@ -35,85 +33,37 @@ import org.jetbrains.kotlin.resolve.inline.InlineUtil
import org.jetbrains.kotlin.resolve.jvm.diagnostics.ErrorsJvm import org.jetbrains.kotlin.resolve.jvm.diagnostics.ErrorsJvm
import org.jetbrains.kotlin.serialization.deserialization.descriptors.DeserializedCallableMemberDescriptor import org.jetbrains.kotlin.serialization.deserialization.descriptors.DeserializedCallableMemberDescriptor
class InlinePlatformCompatibilityChecker(val jvmTarget: JvmTarget, languageVersionSettings: LanguageVersionSettings) : CallChecker { class InlinePlatformCompatibilityChecker(val jvmTarget: JvmTarget) : CallChecker {
private val properError = languageVersionSettings.supportsFeature(LanguageFeature.ProperInlineFromHigherPlatformDiagnostic)
private val doCheck = doCheck()
override fun check(resolvedCall: ResolvedCall<*>, reportOn: PsiElement, context: CallCheckerContext) { override fun check(resolvedCall: ResolvedCall<*>, reportOn: PsiElement, context: CallCheckerContext) {
if (!doCheck) return
val resultingDescriptor = resolvedCall.resultingDescriptor as? CallableMemberDescriptor ?: return val resultingDescriptor = resolvedCall.resultingDescriptor as? CallableMemberDescriptor ?: return
if (!InlineUtil.isInline(resultingDescriptor)) { // TODO (KT-60971): distinguish the case when one property accessor is inline and the other isn't.
if (resultingDescriptor is PropertyDescriptor && InlineUtil.isInline(resultingDescriptor.getter)) { if (!InlineUtil.isInline(resultingDescriptor) &&
//TODO: we should distinguish setter usage from getter one, now we could report wrong diagnostic on non-inline setter (resultingDescriptor !is PropertyDescriptor || !InlineUtil.isInline(resultingDescriptor.getter))
//var prop: Int ) {
// inline get return
// set
//
// prop - resolved call with property descriptor and we should report error
// prop = 1 - resolved call with setter for whole expression and property descriptor for left part,
// so we couldn't distinguish is this expression for setter or for getter and will report wrong diagnostic
} else {
return
}
} }
val propertyOrFun = DescriptorUtils.getDirectMember(resultingDescriptor) val propertyOrFun = DescriptorUtils.getDirectMember(resultingDescriptor)
val compilingBytecodeVersion = jvmTarget.majorVersion val inliningBytecodeVersion = getBytecodeVersionIfDeserializedDescriptor(propertyOrFun) ?: return
if (!properError) {
val inliningBytecodeVersion = getBytecodeVersionIfDeserializedDescriptor(propertyOrFun, false) if (jvmTarget.majorVersion < inliningBytecodeVersion) {
if (inliningBytecodeVersion != null && compilingBytecodeVersion < inliningBytecodeVersion) { context.trace.report(
context.trace.report( ErrorsJvm.INLINE_FROM_HIGHER_PLATFORM.on(
ErrorsJvm.INLINE_FROM_HIGHER_PLATFORM.on( reportOn,
reportOn, JvmTarget.getDescription(inliningBytecodeVersion),
JvmTarget.getDescription(inliningBytecodeVersion), JvmTarget.getDescription(jvmTarget.majorVersion)
JvmTarget.getDescription(compilingBytecodeVersion)
)
) )
return )
}
} }
val inliningBytecodeVersionProper = getBytecodeVersionIfDeserializedDescriptor(propertyOrFun, true) ?: return
if (compilingBytecodeVersion < inliningBytecodeVersionProper) {
if (properError) {
context.trace.report(
ErrorsJvm.INLINE_FROM_HIGHER_PLATFORM.on(
reportOn,
JvmTarget.getDescription(inliningBytecodeVersionProper),
JvmTarget.getDescription(compilingBytecodeVersion)
)
)
} else {
//INLINE_FROM_HIGHER_PLATFORM was checked in `if (!properError)`
context.trace.report(
ErrorsJvm.INLINE_FROM_HIGHER_PLATFORM_WARNING.on(
reportOn,
JvmTarget.getDescription(inliningBytecodeVersionProper),
JvmTarget.getDescription(compilingBytecodeVersion)
)
)
}
}
} }
companion object { companion object {
fun doCheck() = "true" != System.getProperty("kotlin.skip.bytecode.version.check") private fun getBytecodeVersionIfDeserializedDescriptor(funOrProperty: DeclarationDescriptor): Int? {
fun getBytecodeVersionIfDeserializedDescriptor(
funOrProperty: DeclarationDescriptor,
useConcreteSuperImplementation: Boolean
): Int? {
if (funOrProperty !is DeserializedCallableMemberDescriptor) return null if (funOrProperty !is DeserializedCallableMemberDescriptor) return null
val realDeclarationIfFound = val containingDeclaration =
if (useConcreteSuperImplementation) funOrProperty.getConcreteDeclarationForInline() else funOrProperty funOrProperty.getConcreteDeclarationForInline().containingDeclaration as ClassOrPackageFragmentDescriptor
val containingDeclaration = realDeclarationIfFound.containingDeclaration as ClassOrPackageFragmentDescriptor
val source = containingDeclaration.source val source = containingDeclaration.source
val binaryClass = val binaryClass =
@@ -131,10 +81,9 @@ class InlinePlatformCompatibilityChecker(val jvmTarget: JvmTarget, languageVersi
val superImplementation = overriddenDescriptors.firstOrNull { val superImplementation = overriddenDescriptors.firstOrNull {
val containingDeclaration = it.containingDeclaration val containingDeclaration = it.containingDeclaration
!DescriptorUtils.isInterface(containingDeclaration) && !DescriptorUtils.isAnnotationClass(containingDeclaration) !DescriptorUtils.isInterface(containingDeclaration) && !DescriptorUtils.isAnnotationClass(containingDeclaration)
} }
superImplementation?.let { if (superImplementation != null) {
return it.getConcreteDeclarationForInline() return superImplementation.getConcreteDeclarationForInline()
} }
} }
return this return this