K1 JVM: simplify InlinePlatformCompatibilityChecker
This commit is contained in:
committed by
Space Team
parent
596aab1673
commit
bacb2f0d15
+20
-71
@@ -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
|
||||||
|
|||||||
Reference in New Issue
Block a user