K1: introduce synthetic assignment checker with deprecation for KT-54305

#KT-54305 Fixed
Related to KT-54309
This commit is contained in:
Mikhail Glukhikh
2022-10-05 20:13:49 +02:00
committed by Space Team
parent 7bd512fbb3
commit 80fa765333
11 changed files with 114 additions and 4 deletions
@@ -0,0 +1,55 @@
/*
* Copyright 2010-2022 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.resolve.jvm.checkers
import com.intellij.psi.PsiElement
import org.jetbrains.kotlin.descriptors.TypeParameterDescriptor
import org.jetbrains.kotlin.psi.KtBinaryExpression
import org.jetbrains.kotlin.psi.KtNameReferenceExpression
import org.jetbrains.kotlin.psi.psiUtil.getParentOfType
import org.jetbrains.kotlin.resolve.calls.checkers.CallChecker
import org.jetbrains.kotlin.resolve.calls.checkers.CallCheckerContext
import org.jetbrains.kotlin.resolve.calls.model.ResolvedCall
import org.jetbrains.kotlin.resolve.calls.tower.isSynthesized
import org.jetbrains.kotlin.resolve.jvm.diagnostics.ErrorsJvm
import org.jetbrains.kotlin.synthetic.SyntheticJavaPropertyDescriptor
import org.jetbrains.kotlin.types.IndexedParametersSubstitution
import org.jetbrains.kotlin.types.TypeProjection
import org.jetbrains.kotlin.types.TypeSubstitutor
import org.jetbrains.kotlin.types.Variance
import org.jetbrains.kotlin.types.expressions.BasicExpressionTypingVisitor
import org.jetbrains.kotlin.types.typeUtil.isNothing
object JvmSyntheticAssignmentChecker : CallChecker {
override fun check(resolvedCall: ResolvedCall<*>, reportOn: PsiElement, context: CallCheckerContext) {
val resultingDescriptor = resolvedCall.resultingDescriptor
if (!resultingDescriptor.isSynthesized) return
if (resultingDescriptor !is SyntheticJavaPropertyDescriptor) return
if (reportOn !is KtNameReferenceExpression) return
val binaryExpression = reportOn.getParentOfType<KtBinaryExpression>(strict = true) ?: return
if (!BasicExpressionTypingVisitor.isLValue(reportOn, binaryExpression)) return
val receiverType = resolvedCall.extensionReceiver?.type ?: return
val unsubstitutedReceiverType = resolvedCall.candidateDescriptor.extensionReceiverParameter?.type ?: return
if (receiverType.constructor !== unsubstitutedReceiverType.constructor) return
val propertyType = resolvedCall.candidateDescriptor.returnType ?: return
val substitutionParameters = mutableListOf<TypeParameterDescriptor>()
val substitutionArguments = mutableListOf<TypeProjection>()
for ((unsubstitutedArgument, substitutedArgument) in unsubstitutedReceiverType.arguments.zip(receiverType.arguments)) {
val typeParameter = unsubstitutedArgument.type.constructor.declarationDescriptor as? TypeParameterDescriptor ?: continue
substitutionParameters += typeParameter
substitutionArguments += substitutedArgument
}
val substitutor = TypeSubstitutor.create(
IndexedParametersSubstitution(
substitutionParameters.toTypedArray(), substitutionArguments.toTypedArray(), approximateContravariantCapturedTypes = true
)
)
val substitutedPropertyType = substitutor.substitute(propertyType.unwrap(), Variance.IN_VARIANCE)
if (substitutedPropertyType == null || !substitutedPropertyType.isNothing()) return
context.trace.report(ErrorsJvm.SYNTHETIC_SETTER_PROJECTED_OUT.on(binaryExpression.left ?: reportOn, resultingDescriptor))
}
}
@@ -143,6 +143,8 @@ public class DefaultErrorMessagesJvm implements DefaultErrorMessages.Extension {
MAP.put(INAPPLICABLE_JVM_FIELD_WARNING, "{0}. This warning will become an error in further releases", STRING);
MAP.put(JVM_SYNTHETIC_ON_DELEGATE, "'@JvmSynthetic' annotation cannot be used on delegated properties");
MAP.put(SYNTHETIC_SETTER_PROJECTED_OUT, "Use of setter for ''{0}'' is unsafe due to the type projection in receiver." +
" Workaround: use explicit cast on receiver. See https://youtrack.jetbrains.com/issue/KT-54309", NAME);
MAP.put(STRICTFP_ON_CLASS, "'@Strictfp' annotation on classes is unsupported yet");
@@ -42,6 +42,8 @@ public interface ErrorsJvm {
DiagnosticFactory0<KtAnnotationEntry> JVM_SYNTHETIC_ON_DELEGATE = DiagnosticFactory0.create(ERROR);
DiagnosticFactory1<KtExpression, DeclarationDescriptor> SYNTHETIC_SETTER_PROJECTED_OUT = DiagnosticFactory1.create(WARNING);
DiagnosticFactory0<KtAnnotationEntry> STRICTFP_ON_CLASS = DiagnosticFactory0.create(WARNING);
DiagnosticFactory0<KtAnnotationEntry> VOLATILE_ON_VALUE = DiagnosticFactory0.create(ERROR);
@@ -62,6 +62,7 @@ object JvmPlatformConfigurator : PlatformConfiguratorBase(
SamInterfaceConstructorReferenceCallChecker,
EnumDeclaringClassDeprecationChecker,
UpperBoundViolatedInTypealiasConstructorChecker,
JvmSyntheticAssignmentChecker,
),
additionalTypeCheckers = listOf(