FE: Make synchronized suspend functions and lambdas error in 1.8

#KT-27333 Fixed
This commit is contained in:
Ilmir Usmanov
2022-04-03 02:29:24 +02:00
committed by teamcity
parent f473998e8b
commit 6e30ce2763
19 changed files with 152 additions and 75 deletions
@@ -4018,6 +4018,18 @@ internal val KT_DIAGNOSTIC_CONVERTER = KtDiagnosticConverterBuilder.buildConvert
token,
)
}
add(FirJvmErrors.SYNCHRONIZED_ON_SUSPEND.errorFactory) { firDiagnostic ->
SynchronizedOnSuspendErrorImpl(
firDiagnostic as KtPsiDiagnostic,
token,
)
}
add(FirJvmErrors.SYNCHRONIZED_ON_SUSPEND.warningFactory) { firDiagnostic ->
SynchronizedOnSuspendWarningImpl(
firDiagnostic as KtPsiDiagnostic,
token,
)
}
add(FirJvmErrors.OVERLOADS_WITHOUT_DEFAULT_ARGUMENTS) { firDiagnostic ->
OverloadsWithoutDefaultArgumentsImpl(
firDiagnostic as KtPsiDiagnostic,
@@ -2797,6 +2797,14 @@ sealed class KtFirDiagnostic<PSI : PsiElement> : KtDiagnosticWithPsi<PSI> {
override val diagnosticClass get() = SynchronizedOnInline::class
}
abstract class SynchronizedOnSuspendError : KtFirDiagnostic<KtAnnotationEntry>() {
override val diagnosticClass get() = SynchronizedOnSuspendError::class
}
abstract class SynchronizedOnSuspendWarning : KtFirDiagnostic<KtAnnotationEntry>() {
override val diagnosticClass get() = SynchronizedOnSuspendWarning::class
}
abstract class OverloadsWithoutDefaultArguments : KtFirDiagnostic<KtAnnotationEntry>() {
override val diagnosticClass get() = OverloadsWithoutDefaultArguments::class
}
@@ -3378,6 +3378,16 @@ internal class SynchronizedOnInlineImpl(
override val token: ValidityToken,
) : KtFirDiagnostic.SynchronizedOnInline(), KtAbstractFirDiagnostic<KtAnnotationEntry>
internal class SynchronizedOnSuspendErrorImpl(
override val firDiagnostic: KtPsiDiagnostic,
override val token: ValidityToken,
) : KtFirDiagnostic.SynchronizedOnSuspendError(), KtAbstractFirDiagnostic<KtAnnotationEntry>
internal class SynchronizedOnSuspendWarningImpl(
override val firDiagnostic: KtPsiDiagnostic,
override val token: ValidityToken,
) : KtFirDiagnostic.SynchronizedOnSuspendWarning(), KtAbstractFirDiagnostic<KtAnnotationEntry>
internal class OverloadsWithoutDefaultArgumentsImpl(
override val firDiagnostic: KtPsiDiagnostic,
override val token: ValidityToken,
@@ -35750,6 +35750,18 @@ public class DiagnosisCompilerTestFE10TestdataTestGenerated extends AbstractDiag
runTest("compiler/testData/diagnostics/testsWithStdLib/coroutines/suspesionInDefaultValue.kt");
}
@Test
@TestMetadata("synchronizedOnSuspend.kt")
public void testSynchronizedOnSuspend() throws Exception {
runTest("compiler/testData/diagnostics/testsWithStdLib/coroutines/synchronizedOnSuspend.kt");
}
@Test
@TestMetadata("synchronizedOnSuspendError.kt")
public void testSynchronizedOnSuspendError() throws Exception {
runTest("compiler/testData/diagnostics/testsWithStdLib/coroutines/synchronizedOnSuspendError.kt");
}
@Test
@TestMetadata("tryCatchLambda.kt")
public void testTryCatchLambda() throws Exception {
@@ -37423,12 +37435,6 @@ public class DiagnosisCompilerTestFE10TestdataTestGenerated extends AbstractDiag
public void testSynchronizedOnInline() throws Exception {
runTest("compiler/testData/diagnostics/testsWithStdLib/inline/synchronizedOnInline.kt");
}
@Test
@TestMetadata("synchronizedOnSuspend.kt")
public void testSynchronizedOnSuspend() throws Exception {
runTest("compiler/testData/diagnostics/testsWithStdLib/inline/synchronizedOnSuspend.kt");
}
}
@Nested
@@ -35750,6 +35750,18 @@ public class FirOldFrontendDiagnosticsTestGenerated extends AbstractFirDiagnosti
runTest("compiler/testData/diagnostics/testsWithStdLib/coroutines/suspesionInDefaultValue.kt");
}
@Test
@TestMetadata("synchronizedOnSuspend.kt")
public void testSynchronizedOnSuspend() throws Exception {
runTest("compiler/testData/diagnostics/testsWithStdLib/coroutines/synchronizedOnSuspend.kt");
}
@Test
@TestMetadata("synchronizedOnSuspendError.kt")
public void testSynchronizedOnSuspendError() throws Exception {
runTest("compiler/testData/diagnostics/testsWithStdLib/coroutines/synchronizedOnSuspendError.kt");
}
@Test
@TestMetadata("tryCatchLambda.kt")
public void testTryCatchLambda() throws Exception {
@@ -37423,12 +37435,6 @@ public class FirOldFrontendDiagnosticsTestGenerated extends AbstractFirDiagnosti
public void testSynchronizedOnInline() throws Exception {
runTest("compiler/testData/diagnostics/testsWithStdLib/inline/synchronizedOnInline.kt");
}
@Test
@TestMetadata("synchronizedOnSuspend.kt")
public void testSynchronizedOnSuspend() throws Exception {
runTest("compiler/testData/diagnostics/testsWithStdLib/inline/synchronizedOnSuspend.kt");
}
}
@Nested
@@ -35750,6 +35750,18 @@ public class FirOldFrontendDiagnosticsWithLightTreeTestGenerated extends Abstrac
runTest("compiler/testData/diagnostics/testsWithStdLib/coroutines/suspesionInDefaultValue.kt");
}
@Test
@TestMetadata("synchronizedOnSuspend.kt")
public void testSynchronizedOnSuspend() throws Exception {
runTest("compiler/testData/diagnostics/testsWithStdLib/coroutines/synchronizedOnSuspend.kt");
}
@Test
@TestMetadata("synchronizedOnSuspendError.kt")
public void testSynchronizedOnSuspendError() throws Exception {
runTest("compiler/testData/diagnostics/testsWithStdLib/coroutines/synchronizedOnSuspendError.kt");
}
@Test
@TestMetadata("tryCatchLambda.kt")
public void testTryCatchLambda() throws Exception {
@@ -37423,12 +37435,6 @@ public class FirOldFrontendDiagnosticsWithLightTreeTestGenerated extends Abstrac
public void testSynchronizedOnInline() throws Exception {
runTest("compiler/testData/diagnostics/testsWithStdLib/inline/synchronizedOnInline.kt");
}
@Test
@TestMetadata("synchronizedOnSuspend.kt")
public void testSynchronizedOnSuspend() throws Exception {
runTest("compiler/testData/diagnostics/testsWithStdLib/inline/synchronizedOnSuspend.kt");
}
}
@Nested
@@ -6,6 +6,7 @@
package org.jetbrains.kotlin.fir.checkers.generator.diagnostics
import com.intellij.psi.PsiElement
import org.jetbrains.kotlin.config.LanguageFeature
import org.jetbrains.kotlin.config.LanguageFeature.*
import org.jetbrains.kotlin.fir.PrivateForInline
import org.jetbrains.kotlin.fir.checkers.generator.diagnostics.model.DiagnosticList
@@ -60,6 +61,7 @@ object JVM_DIAGNOSTICS_LIST : DiagnosticList("FirJvmErrors") {
val SYNCHRONIZED_ON_ABSTRACT by error<KtAnnotationEntry>()
val SYNCHRONIZED_IN_INTERFACE by error<KtAnnotationEntry>()
val SYNCHRONIZED_ON_INLINE by warning<KtAnnotationEntry>()
val SYNCHRONIZED_ON_SUSPEND by deprecationError<KtAnnotationEntry>(SynchronizedSuspendError)
val OVERLOADS_WITHOUT_DEFAULT_ARGUMENTS by warning<KtAnnotationEntry>()
val OVERLOADS_ABSTRACT by error<KtAnnotationEntry>()
val OVERLOADS_INTERFACE by error<KtAnnotationEntry>()
@@ -11,6 +11,7 @@ import org.jetbrains.kotlin.config.LanguageFeature.ProhibitConcurrentHashMapCont
import org.jetbrains.kotlin.config.LanguageFeature.ProhibitJvmOverloadsOnConstructorsOfAnnotationClasses
import org.jetbrains.kotlin.config.LanguageFeature.ProhibitSpreadOnSignaturePolymorphicCall
import org.jetbrains.kotlin.config.LanguageFeature.RepeatableAnnotationContainerConstraints
import org.jetbrains.kotlin.config.LanguageFeature.SynchronizedSuspendError
import org.jetbrains.kotlin.diagnostics.*
import org.jetbrains.kotlin.diagnostics.SourceElementPositioningStrategies
import org.jetbrains.kotlin.diagnostics.rendering.RootDiagnosticRendererFactory
@@ -58,6 +59,7 @@ object FirJvmErrors {
val SYNCHRONIZED_ON_ABSTRACT by error0<KtAnnotationEntry>()
val SYNCHRONIZED_IN_INTERFACE by error0<KtAnnotationEntry>()
val SYNCHRONIZED_ON_INLINE by warning0<KtAnnotationEntry>()
val SYNCHRONIZED_ON_SUSPEND by deprecationError0<KtAnnotationEntry>(SynchronizedSuspendError)
val OVERLOADS_WITHOUT_DEFAULT_ARGUMENTS by warning0<KtAnnotationEntry>()
val OVERLOADS_ABSTRACT by error0<KtAnnotationEntry>()
val OVERLOADS_INTERFACE by error0<KtAnnotationEntry>()
@@ -82,6 +82,7 @@ import org.jetbrains.kotlin.fir.analysis.diagnostics.jvm.FirJvmErrors.SUSPENSION
import org.jetbrains.kotlin.fir.analysis.diagnostics.jvm.FirJvmErrors.SYNCHRONIZED_IN_INTERFACE
import org.jetbrains.kotlin.fir.analysis.diagnostics.jvm.FirJvmErrors.SYNCHRONIZED_ON_ABSTRACT
import org.jetbrains.kotlin.fir.analysis.diagnostics.jvm.FirJvmErrors.SYNCHRONIZED_ON_INLINE
import org.jetbrains.kotlin.fir.analysis.diagnostics.jvm.FirJvmErrors.SYNCHRONIZED_ON_SUSPEND
import org.jetbrains.kotlin.fir.analysis.diagnostics.jvm.FirJvmErrors.UPPER_BOUND_CANNOT_BE_ARRAY
import org.jetbrains.kotlin.fir.analysis.diagnostics.jvm.FirJvmErrors.VALUE_CLASS_WITHOUT_JVM_INLINE_ANNOTATION
import org.jetbrains.kotlin.fir.analysis.diagnostics.jvm.FirJvmErrors.VOLATILE_ON_DELEGATE
@@ -98,6 +99,7 @@ object FirJvmErrorsDefaultMessages : BaseDiagnosticRendererFactory() {
map.put(VOLATILE_ON_DELEGATE, "'@Volatile' annotation cannot be used on delegated properties")
map.put(SYNCHRONIZED_ON_ABSTRACT, "'@Synchronized' annotation cannot be used on abstract functions")
map.put(SYNCHRONIZED_ON_INLINE, "'@Synchronized' annotation has no effect on inline functions")
map.put(SYNCHRONIZED_ON_SUSPEND, "@Synchronized annotation is not applicable to suspend functions and lambdas")
map.put(SYNCHRONIZED_IN_INTERFACE, "'@Synchronized' annotation cannot be used on interface members")
map.put(OVERLOADS_WITHOUT_DEFAULT_ARGUMENTS, "'@JvmOverloads' annotation has no effect for methods without default arguments")
map.put(OVERLOADS_ABSTRACT, "'@JvmOverloads' annotation cannot be used on abstract methods")
@@ -5,6 +5,7 @@
package org.jetbrains.kotlin.fir.analysis.jvm.checkers.declaration
import org.jetbrains.kotlin.config.LanguageFeature
import org.jetbrains.kotlin.descriptors.ClassKind
import org.jetbrains.kotlin.fir.analysis.checkers.classKind
import org.jetbrains.kotlin.fir.analysis.checkers.context.CheckerContext
@@ -13,10 +14,14 @@ import org.jetbrains.kotlin.fir.analysis.checkers.getContainingClassSymbol
import org.jetbrains.kotlin.diagnostics.DiagnosticReporter
import org.jetbrains.kotlin.fir.analysis.diagnostics.jvm.FirJvmErrors
import org.jetbrains.kotlin.diagnostics.reportOn
import org.jetbrains.kotlin.fir.declarations.FirAnonymousFunction
import org.jetbrains.kotlin.fir.declarations.FirFunction
import org.jetbrains.kotlin.fir.declarations.getAnnotationByClassId
import org.jetbrains.kotlin.fir.declarations.utils.isAbstract
import org.jetbrains.kotlin.fir.declarations.utils.isInline
import org.jetbrains.kotlin.fir.declarations.utils.isSuspend
import org.jetbrains.kotlin.fir.types.coneType
import org.jetbrains.kotlin.fir.types.isSuspendFunctionType
import org.jetbrains.kotlin.name.JvmNames.SYNCHRONIZED_ANNOTATION_CLASS_ID
object FirSynchronizedAnnotationChecker : FirFunctionChecker() {
@@ -27,6 +32,12 @@ object FirSynchronizedAnnotationChecker : FirFunctionChecker() {
reporter.reportOn(annotation.source, FirJvmErrors.SYNCHRONIZED_ON_INLINE, context)
return
}
if (declaration.isSuspend ||
(declaration as? FirAnonymousFunction)?.typeRef?.coneType?.isSuspendFunctionType(context.session) == true
) {
reporter.reportOn(annotation.source, FirJvmErrors.SYNCHRONIZED_ON_SUSPEND, context)
return
}
val containingClass = declaration.getContainingClassSymbol(context.session) ?: return
if (containingClass.classKind == ClassKind.INTERFACE) {
@@ -5,6 +5,7 @@
package org.jetbrains.kotlin.resolve.jvm.checkers
import org.jetbrains.kotlin.config.LanguageFeature
import org.jetbrains.kotlin.config.LanguageVersionSettings
import org.jetbrains.kotlin.descriptors.FunctionDescriptor
import org.jetbrains.kotlin.descriptors.annotations.KotlinTarget
@@ -33,7 +34,7 @@ object SynchronizedAnnotationOnLambdaChecker : AdditionalAnnotationChecker {
val literal = (annotated?.unwrapParenthesesLabelsAndAnnotations() as? KtLambdaExpression)?.functionLiteral ?: return
val descriptor = trace.bindingContext[BindingContext.DECLARATION_TO_DESCRIPTOR, literal]
if (descriptor is FunctionDescriptor && descriptor.isSuspend) {
trace.report(ErrorsJvm.SYNCHRONIZED_ON_SUSPEND.on(annotation))
trace.report(ErrorsJvm.SYNCHRONIZED_ON_SUSPEND.on(languageVersionSettings, annotation))
}
}
}
@@ -198,7 +198,7 @@ class SynchronizedAnnotationChecker : DeclarationChecker {
} else if (descriptor.isInline) {
context.trace.report(ErrorsJvm.SYNCHRONIZED_ON_INLINE.on(annotationEntry))
} else if (descriptor.isSuspend) {
context.trace.report(ErrorsJvm.SYNCHRONIZED_ON_SUSPEND.on(annotationEntry))
context.trace.report(ErrorsJvm.SYNCHRONIZED_ON_SUSPEND.on(context.languageVersionSettings, annotationEntry))
} else if (descriptor.containingDeclaration.let { it is ClassDescriptor && it.isValue }) {
context.trace.report(ErrorsJvm.SYNCHRONIZED_ON_VALUE_CLASS.on(annotationEntry))
}
@@ -49,7 +49,8 @@ public interface ErrorsJvm {
DiagnosticFactory0<KtAnnotationEntry> SYNCHRONIZED_ON_ABSTRACT = DiagnosticFactory0.create(ERROR);
DiagnosticFactory0<KtElement> SYNCHRONIZED_ON_INLINE = DiagnosticFactory0.create(WARNING);
DiagnosticFactory0<KtElement> SYNCHRONIZED_ON_VALUE_CLASS = DiagnosticFactory0.create(WARNING);
DiagnosticFactory0<PsiElement> SYNCHRONIZED_ON_SUSPEND = DiagnosticFactory0.create(WARNING);
DiagnosticFactoryForDeprecation0<PsiElement> SYNCHRONIZED_ON_SUSPEND =
DiagnosticFactoryForDeprecation0.create(LanguageFeature.SynchronizedSuspendError);
DiagnosticFactory0<KtAnnotationEntry> SYNCHRONIZED_IN_INTERFACE = DiagnosticFactory0.create(ERROR);
DiagnosticFactory0<KtAnnotationEntry> OVERLOADS_WITHOUT_DEFAULT_ARGUMENTS = DiagnosticFactory0.create(WARNING);
@@ -0,0 +1,25 @@
// FIR_IDENTICAL
// !DIAGNOSTICS: -UNUSED_PARAMETER
// SKIP_TXT
<!SYNCHRONIZED_ON_SUSPEND_WARNING!>@Synchronized<!>
suspend fun foo(f: () -> Unit): Unit = f()
fun builder(c: suspend () -> Unit) {}
val a: suspend () -> Unit
get() = <!SYNCHRONIZED_ON_SUSPEND_WARNING!>@Synchronized<!> {}
val b: suspend () -> Unit = <!SYNCHRONIZED_ON_SUSPEND_WARNING!>@Synchronized<!> {}
val c = builder (<!SYNCHRONIZED_ON_SUSPEND_WARNING!>@Synchronized<!> {})
val d = suspend <!SYNCHRONIZED_ON_SUSPEND_WARNING!>@Synchronized<!> {}
val e = <!WRONG_ANNOTATION_TARGET!>@Synchronized<!> suspend {}
fun test() {
<!SYNCHRONIZED_ON_SUSPEND_WARNING!>@Synchronized<!>
suspend fun foo(f: () -> Unit): Unit = f()
val b: suspend () -> Unit = <!SYNCHRONIZED_ON_SUSPEND_WARNING!>@Synchronized<!> {}
val c = builder (<!SYNCHRONIZED_ON_SUSPEND_WARNING!>@Synchronized<!> {})
val d = suspend <!SYNCHRONIZED_ON_SUSPEND_WARNING!>@Synchronized<!> {}
val e = <!WRONG_ANNOTATION_TARGET!>@Synchronized<!> suspend {}
}
@@ -0,0 +1,26 @@
// FIR_IDENTICAL
// LANGUAGE: +SynchronizedSuspendError
// !DIAGNOSTICS: -UNUSED_PARAMETER
// SKIP_TXT
<!SYNCHRONIZED_ON_SUSPEND_ERROR!>@Synchronized<!>
suspend fun foo(f: () -> Unit): Unit = f()
fun builder(c: suspend () -> Unit) {}
val a: suspend () -> Unit
get() = <!SYNCHRONIZED_ON_SUSPEND_ERROR!>@Synchronized<!> {}
val b: suspend () -> Unit = <!SYNCHRONIZED_ON_SUSPEND_ERROR!>@Synchronized<!> {}
val c = builder (<!SYNCHRONIZED_ON_SUSPEND_ERROR!>@Synchronized<!> {})
val d = suspend <!SYNCHRONIZED_ON_SUSPEND_ERROR!>@Synchronized<!> {}
val e = <!WRONG_ANNOTATION_TARGET!>@Synchronized<!> suspend {}
fun test() {
<!SYNCHRONIZED_ON_SUSPEND_ERROR!>@Synchronized<!>
suspend fun foo(f: () -> Unit): Unit = f()
val b: suspend () -> Unit = <!SYNCHRONIZED_ON_SUSPEND_ERROR!>@Synchronized<!> {}
val c = builder (<!SYNCHRONIZED_ON_SUSPEND_ERROR!>@Synchronized<!> {})
val d = suspend <!SYNCHRONIZED_ON_SUSPEND_ERROR!>@Synchronized<!> {}
val e = <!WRONG_ANNOTATION_TARGET!>@Synchronized<!> suspend {}
}
@@ -1,24 +0,0 @@
// !DIAGNOSTICS: -UNUSED_PARAMETER
// SKIP_TXT
@Synchronized
suspend fun foo(f: () -> Unit): Unit = f()
fun builder(c: suspend () -> Unit) {}
val a: suspend () -> Unit
get() = @Synchronized {}
val b: suspend () -> Unit = @Synchronized {}
val c = builder (@Synchronized {})
val d = suspend @Synchronized {}
val e = <!WRONG_ANNOTATION_TARGET!>@Synchronized<!> suspend {}
fun test() {
@Synchronized
suspend fun foo(f: () -> Unit): Unit = f()
val b: suspend () -> Unit = @Synchronized {}
val c = builder (@Synchronized {})
val d = suspend @Synchronized {}
val e = <!WRONG_ANNOTATION_TARGET!>@Synchronized<!> suspend {}
}
@@ -1,24 +0,0 @@
// !DIAGNOSTICS: -UNUSED_PARAMETER
// SKIP_TXT
<!SYNCHRONIZED_ON_SUSPEND!>@Synchronized<!>
suspend fun foo(f: () -> Unit): Unit = f()
fun builder(c: suspend () -> Unit) {}
val a: suspend () -> Unit
get() = <!SYNCHRONIZED_ON_SUSPEND!>@Synchronized<!> {}
val b: suspend () -> Unit = <!SYNCHRONIZED_ON_SUSPEND!>@Synchronized<!> {}
val c = builder (<!SYNCHRONIZED_ON_SUSPEND!>@Synchronized<!> {})
val d = suspend <!SYNCHRONIZED_ON_SUSPEND!>@Synchronized<!> {}
val e = <!WRONG_ANNOTATION_TARGET!>@Synchronized<!> suspend {}
fun test() {
<!SYNCHRONIZED_ON_SUSPEND!>@Synchronized<!>
suspend fun foo(f: () -> Unit): Unit = f()
val b: suspend () -> Unit = <!SYNCHRONIZED_ON_SUSPEND!>@Synchronized<!> {}
val c = builder (<!SYNCHRONIZED_ON_SUSPEND!>@Synchronized<!> {})
val d = suspend <!SYNCHRONIZED_ON_SUSPEND!>@Synchronized<!> {}
val e = <!WRONG_ANNOTATION_TARGET!>@Synchronized<!> suspend {}
}
@@ -35840,6 +35840,18 @@ public class DiagnosticTestGenerated extends AbstractDiagnosticTest {
runTest("compiler/testData/diagnostics/testsWithStdLib/coroutines/suspesionInDefaultValue.kt");
}
@Test
@TestMetadata("synchronizedOnSuspend.kt")
public void testSynchronizedOnSuspend() throws Exception {
runTest("compiler/testData/diagnostics/testsWithStdLib/coroutines/synchronizedOnSuspend.kt");
}
@Test
@TestMetadata("synchronizedOnSuspendError.kt")
public void testSynchronizedOnSuspendError() throws Exception {
runTest("compiler/testData/diagnostics/testsWithStdLib/coroutines/synchronizedOnSuspendError.kt");
}
@Test
@TestMetadata("tryCatchLambda.kt")
public void testTryCatchLambda() throws Exception {
@@ -37513,12 +37525,6 @@ public class DiagnosticTestGenerated extends AbstractDiagnosticTest {
public void testSynchronizedOnInline() throws Exception {
runTest("compiler/testData/diagnostics/testsWithStdLib/inline/synchronizedOnInline.kt");
}
@Test
@TestMetadata("synchronizedOnSuspend.kt")
public void testSynchronizedOnSuspend() throws Exception {
runTest("compiler/testData/diagnostics/testsWithStdLib/inline/synchronizedOnSuspend.kt");
}
}
@Nested
@@ -260,6 +260,7 @@ enum class LanguageFeature(
IgnoreNullabilityForErasedValueParameters(KOTLIN_1_8, kind = BUG_FIX),
ForbidUsingExtensionPropertyTypeParameterInDelegate(KOTLIN_1_8, kind = BUG_FIX),
ModifierNonBuiltinSuspendFunError(KOTLIN_1_8),
SynchronizedSuspendError(KOTLIN_1_8),
// 1.9