[FIR] Report MIXING_SUSPEND_AND_NON_SUSPEND_SUPERTYPES

^KT-59367 Fixed
This commit is contained in:
Nikolay Lunyak
2023-08-16 14:14:08 +03:00
committed by Space Team
parent b3e4099703
commit f674529558
33 changed files with 63 additions and 435 deletions
@@ -4665,6 +4665,12 @@ internal val KT_DIAGNOSTIC_CONVERTER = KtDiagnosticConverterBuilder.buildConvert
token,
)
}
add(FirErrors.MIXING_SUSPEND_AND_NON_SUSPEND_SUPERTYPES) { firDiagnostic ->
MixingSuspendAndNonSuspendSupertypesImpl(
firDiagnostic as KtPsiDiagnostic,
token,
)
}
add(FirErrors.REDUNDANT_LABEL_WARNING) { firDiagnostic ->
RedundantLabelWarningImpl(
firDiagnostic as KtPsiDiagnostic,
@@ -3256,6 +3256,10 @@ sealed interface KtFirDiagnostic<PSI : PsiElement> : KtDiagnosticWithPsi<PSI> {
override val diagnosticClass get() = ReturnForBuiltInSuspend::class
}
interface MixingSuspendAndNonSuspendSupertypes : KtFirDiagnostic<PsiElement> {
override val diagnosticClass get() = MixingSuspendAndNonSuspendSupertypes::class
}
interface RedundantLabelWarning : KtFirDiagnostic<KtLabelReferenceExpression> {
override val diagnosticClass get() = RedundantLabelWarning::class
}
@@ -3928,6 +3928,11 @@ internal class ReturnForBuiltInSuspendImpl(
token: KtLifetimeToken,
) : KtAbstractFirDiagnostic<KtReturnExpression>(firDiagnostic, token), KtFirDiagnostic.ReturnForBuiltInSuspend
internal class MixingSuspendAndNonSuspendSupertypesImpl(
firDiagnostic: KtPsiDiagnostic,
token: KtLifetimeToken,
) : KtAbstractFirDiagnostic<PsiElement>(firDiagnostic, token), KtFirDiagnostic.MixingSuspendAndNonSuspendSupertypes
internal class RedundantLabelWarningImpl(
firDiagnostic: KtPsiDiagnostic,
token: KtLifetimeToken,
@@ -1649,6 +1649,7 @@ object DIAGNOSTICS_LIST : DiagnosticList("FirErrors") {
LanguageFeature.ModifierNonBuiltinSuspendFunError, PositioningStrategy.REFERENCED_NAME_BY_QUALIFIED
)
val RETURN_FOR_BUILT_IN_SUSPEND by error<KtReturnExpression>()
val MIXING_SUSPEND_AND_NON_SUSPEND_SUPERTYPES by error<PsiElement>(PositioningStrategy.SUPERTYPES_LIST)
}
val LABEL by object : DiagnosticGroup("label") {
@@ -826,6 +826,7 @@ object FirErrors {
val MODIFIER_FORM_FOR_NON_BUILT_IN_SUSPEND by error0<PsiElement>(SourceElementPositioningStrategies.REFERENCED_NAME_BY_QUALIFIED)
val MODIFIER_FORM_FOR_NON_BUILT_IN_SUSPEND_FUN by deprecationError0<PsiElement>(ModifierNonBuiltinSuspendFunError, SourceElementPositioningStrategies.REFERENCED_NAME_BY_QUALIFIED)
val RETURN_FOR_BUILT_IN_SUSPEND by error0<KtReturnExpression>()
val MIXING_SUSPEND_AND_NON_SUSPEND_SUPERTYPES by error0<PsiElement>(SourceElementPositioningStrategies.SUPERTYPES_LIST)
// label
val REDUNDANT_LABEL_WARNING by warning0<KtLabelReferenceExpression>(SourceElementPositioningStrategies.LABEL)
@@ -109,6 +109,7 @@ object CommonDeclarationCheckers : DeclarationCheckers() {
FirEnumCompanionInEnumConstructorCallChecker,
FirBadInheritedJavaSignaturesChecker,
FirSealedInterfaceAllowedChecker,
FirSuspendFunctionAsSupertypeChecker,
)
override val regularClassCheckers: Set<FirRegularClassChecker>
@@ -0,0 +1,30 @@
/*
* Copyright 2010-2020 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.checkers.declaration
import org.jetbrains.kotlin.builtins.functions.isBasicFunctionOrKFunction
import org.jetbrains.kotlin.builtins.functions.isSuspendOrKSuspendFunction
import org.jetbrains.kotlin.diagnostics.DiagnosticReporter
import org.jetbrains.kotlin.diagnostics.reportOn
import org.jetbrains.kotlin.fir.analysis.checkers.context.CheckerContext
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors
import org.jetbrains.kotlin.fir.declarations.FirClass
import org.jetbrains.kotlin.fir.resolve.lookupSuperTypes
import org.jetbrains.kotlin.fir.types.functionTypeKind
object FirSuspendFunctionAsSupertypeChecker : FirClassChecker() {
override fun check(declaration: FirClass, context: CheckerContext, reporter: DiagnosticReporter) {
val supertypes = lookupSuperTypes(declaration.symbol, lookupInterfaces = true, deep = true, context.session)
.mapNotNull { it.functionTypeKind(context.session) }
if (
supertypes.any { it.isSuspendOrKSuspendFunction } &&
supertypes.any { it.isBasicFunctionOrKFunction }
) {
reporter.reportOn(declaration.source, FirErrors.MIXING_SUSPEND_AND_NON_SUSPEND_SUPERTYPES, context)
}
}
}
@@ -356,6 +356,7 @@ import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.METHOD_OF_ANY_IMP
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.MISPLACED_TYPE_PARAMETER_CONSTRAINTS
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.MISSING_STDLIB_CLASS
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.MISSING_VAL_ON_ANNOTATION_PARAMETER
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.MIXING_SUSPEND_AND_NON_SUSPEND_SUPERTYPES
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.MODIFIER_FORM_FOR_NON_BUILT_IN_SUSPEND
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.MODIFIER_FORM_FOR_NON_BUILT_IN_SUSPEND_FUN
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.MULTIPLE_ARGUMENTS_APPLICABLE_FOR_CONTEXT_RECEIVER
@@ -2347,6 +2348,7 @@ object FirErrorsDefaultMessages : BaseDiagnosticRendererFactory() {
" See https://youtrack.jetbrains.com/issue/KT-49264"
)
map.put(RETURN_FOR_BUILT_IN_SUSPEND, "Using implicit label for this lambda is prohibited")
map.put(MIXING_SUSPEND_AND_NON_SUSPEND_SUPERTYPES, "Mixing suspend and non-suspend supertypes is not allowed")
// Label
map.put(
@@ -65,7 +65,7 @@ object PositioningStrategies {
val SUPERTYPES_LIST: PositioningStrategy<PsiElement> = object : PositioningStrategy<PsiElement>() {
override fun mark(element: PsiElement): List<TextRange> {
val supertypes = ((
element as? KtClass
element as? KtClassOrObject
) ?: return markElement(element)
).superTypeListEntries
return if (supertypes.isEmpty())
@@ -1,18 +0,0 @@
// !LANGUAGE: +SuspendFunctionAsSupertype
// SKIP_TXT
// DIAGNOSTICS: -CONFLICTING_INHERITED_MEMBERS, -CONFLICTING_OVERLOADS, -ABSTRACT_MEMBER_NOT_IMPLEMENTED, -ABSTRACT_CLASS_MEMBER_NOT_IMPLEMENTED
import kotlin.reflect.*
class C: KSuspendFunction0<Unit>, () -> Unit {
override suspend fun invoke() {
}
}
interface I: KSuspendFunction0<Unit>, () -> Unit {
}
object O: KSuspendFunction0<Unit>, () -> Unit {
override suspend fun invoke() {
}
}
@@ -1,3 +1,4 @@
// FIR_IDENTICAL
// !LANGUAGE: +SuspendFunctionAsSupertype
// SKIP_TXT
// DIAGNOSTICS: -CONFLICTING_INHERITED_MEMBERS, -CONFLICTING_OVERLOADS, -ABSTRACT_MEMBER_NOT_IMPLEMENTED, -ABSTRACT_CLASS_MEMBER_NOT_IMPLEMENTED
@@ -1,29 +0,0 @@
// !LANGUAGE: +SuspendFunctionAsSupertype
// SKIP_TXT
// DIAGNOSTICS: -CONFLICTING_INHERITED_MEMBERS, -CONFLICTING_OVERLOADS, -ABSTRACT_MEMBER_NOT_IMPLEMENTED, -ABSTRACT_CLASS_MEMBER_NOT_IMPLEMENTED
import kotlin.reflect.*
abstract class CSuper: () -> Unit
class C: CSuper(), KSuspendFunction0<Unit> {
override suspend fun invoke() {
}
}
object O: CSuper(), KSuspendFunction0<Unit> {
override suspend fun invoke() {
}
}
abstract class SCSuper: KSuspendFunction0<Unit>
class C1: SCSuper(), () -> Unit {
override suspend fun invoke() {
}
}
object O1: SCSuper(), () -> Unit {
override suspend fun invoke() {
}
}
@@ -1,3 +1,4 @@
// FIR_IDENTICAL
// !LANGUAGE: +SuspendFunctionAsSupertype
// SKIP_TXT
// DIAGNOSTICS: -CONFLICTING_INHERITED_MEMBERS, -CONFLICTING_OVERLOADS, -ABSTRACT_MEMBER_NOT_IMPLEMENTED, -ABSTRACT_CLASS_MEMBER_NOT_IMPLEMENTED
@@ -1,20 +0,0 @@
// !LANGUAGE: +SuspendFunctionAsSupertype
// SKIP_TXT
// DIAGNOSTICS: -CONFLICTING_INHERITED_MEMBERS, -CONFLICTING_OVERLOADS, -ABSTRACT_MEMBER_NOT_IMPLEMENTED, -ABSTRACT_CLASS_MEMBER_NOT_IMPLEMENTED
import kotlin.reflect.*
fun interface FISuper: () -> Unit
class C: KSuspendFunction0<Unit>, FISuper {
override suspend fun invoke() {
}
}
interface I: KSuspendFunction0<Unit>, FISuper {
}
object O: KSuspendFunction0<Unit>, FISuper {
override suspend fun invoke() {
}
}
@@ -1,3 +1,4 @@
// FIR_IDENTICAL
// !LANGUAGE: +SuspendFunctionAsSupertype
// SKIP_TXT
// DIAGNOSTICS: -CONFLICTING_INHERITED_MEMBERS, -CONFLICTING_OVERLOADS, -ABSTRACT_MEMBER_NOT_IMPLEMENTED, -ABSTRACT_CLASS_MEMBER_NOT_IMPLEMENTED
@@ -1,48 +0,0 @@
// !LANGUAGE: +SuspendFunctionAsSupertype
// SKIP_TXT
// DIAGNOSTICS: -CONFLICTING_INHERITED_MEMBERS, -CONFLICTING_OVERLOADS, -ABSTRACT_MEMBER_NOT_IMPLEMENTED, -ABSTRACT_CLASS_MEMBER_NOT_IMPLEMENTED
import kotlin.reflect.*
interface ISuper: () -> Unit
class C: KSuspendFunction0<Unit>, ISuper {
override suspend fun invoke() {
}
}
interface I: KSuspendFunction0<Unit>, ISuper {
}
object O: KSuspendFunction0<Unit>, ISuper {
override suspend fun invoke() {
}
}
interface SISuper: KSuspendFunction0<Unit>
class C1: SISuper, () -> Unit {
override suspend fun invoke() {
}
}
interface I1: SISuper, () -> Unit {
}
object O1: SISuper, () -> Unit {
override suspend fun invoke() {
}
}
class C2: SISuper, ISuper {
override suspend fun invoke() {
}
}
interface I2: SISuper, ISuper {
}
object O2: SISuper, ISuper {
override suspend fun invoke() {
}
}
@@ -1,3 +1,4 @@
// FIR_IDENTICAL
// !LANGUAGE: +SuspendFunctionAsSupertype
// SKIP_TXT
// DIAGNOSTICS: -CONFLICTING_INHERITED_MEMBERS, -CONFLICTING_OVERLOADS, -ABSTRACT_MEMBER_NOT_IMPLEMENTED, -ABSTRACT_CLASS_MEMBER_NOT_IMPLEMENTED
@@ -1,19 +0,0 @@
// !LANGUAGE: +SuspendFunctionAsSupertype
// SKIP_TXT
// DIAGNOSTICS: -CONFLICTING_INHERITED_MEMBERS, -CONFLICTING_OVERLOADS
class C: suspend () -> Unit, () -> Unit {
override suspend fun invoke() {
}
}
fun interface FI: suspend () -> Unit, () -> Unit {
}
interface I: suspend () -> Unit, () -> Unit {
}
object O: suspend () -> Unit, () -> Unit {
override suspend fun invoke() {
}
}
@@ -1,3 +1,4 @@
// FIR_IDENTICAL
// !LANGUAGE: +SuspendFunctionAsSupertype
// SKIP_TXT
// DIAGNOSTICS: -CONFLICTING_INHERITED_MEMBERS, -CONFLICTING_OVERLOADS
@@ -1,27 +0,0 @@
// !LANGUAGE: +SuspendFunctionAsSupertype
// SKIP_TXT
// DIAGNOSTICS: -CONFLICTING_INHERITED_MEMBERS, -CONFLICTING_OVERLOADS
abstract class CSuper: () -> Unit
class C: CSuper(), suspend () -> Unit {
override suspend fun invoke() {
}
}
object O: CSuper(), suspend () -> Unit {
override suspend fun invoke() {
}
}
abstract class SCSuper: suspend () -> Unit
class C1: SCSuper(), () -> Unit {
override suspend fun invoke() {
}
}
object O1: SCSuper(), () -> Unit {
override suspend fun invoke() {
}
}
@@ -1,3 +1,4 @@
// FIR_IDENTICAL
// !LANGUAGE: +SuspendFunctionAsSupertype
// SKIP_TXT
// DIAGNOSTICS: -CONFLICTING_INHERITED_MEMBERS, -CONFLICTING_OVERLOADS
@@ -1,55 +0,0 @@
// !LANGUAGE: +SuspendFunctionAsSupertype
// SKIP_TXT
// DIAGNOSTICS: -CONFLICTING_INHERITED_MEMBERS, -CONFLICTING_OVERLOADS
fun interface FISuper: () -> Unit
class C: suspend () -> Unit, FISuper {
override suspend fun invoke() {
}
}
fun interface FI: suspend () -> Unit, FISuper {
}
interface I: suspend () -> Unit, FISuper {
}
object O: suspend () -> Unit, FISuper {
override suspend fun invoke() {
}
}
fun interface SFISuper: suspend () -> Unit
class C1: SFISuper, () -> Unit {
override suspend fun invoke() {
}
}
fun interface FI1: SFISuper, () -> Unit {
}
interface I1: SFISuper, () -> Unit {
}
object O1: SFISuper, () -> Unit {
override suspend fun invoke() {
}
}
class C2: SFISuper, FISuper {
override suspend fun invoke() {
}
}
fun interface FI2: SFISuper, FISuper {
}
interface I2: SFISuper, FISuper {
}
object O2: SFISuper, FISuper {
override suspend fun invoke() {
}
}
@@ -1,3 +1,4 @@
// FIR_IDENTICAL
// !LANGUAGE: +SuspendFunctionAsSupertype
// SKIP_TXT
// DIAGNOSTICS: -CONFLICTING_INHERITED_MEMBERS, -CONFLICTING_OVERLOADS
@@ -1,55 +0,0 @@
// !LANGUAGE: +SuspendFunctionAsSupertype
// SKIP_TXT
// DIAGNOSTICS: -CONFLICTING_INHERITED_MEMBERS, -CONFLICTING_OVERLOADS
interface ISuper: () -> Unit
class C: suspend () -> Unit, ISuper {
override suspend fun invoke() {
}
}
fun interface FI: suspend () -> Unit, ISuper {
}
interface I: suspend () -> Unit, ISuper {
}
object O: suspend () -> Unit, ISuper {
override suspend fun invoke() {
}
}
interface SISuper: suspend () -> Unit
class C1: SISuper, () -> Unit {
override suspend fun invoke() {
}
}
fun interface FI1: SISuper, () -> Unit {
}
interface I1: SISuper, () -> Unit {
}
object O1: SISuper, () -> Unit {
override suspend fun invoke() {
}
}
class C2: SISuper, ISuper {
override suspend fun invoke() {
}
}
fun interface FI2: SISuper, ISuper {
}
interface I2: SISuper, ISuper {
}
object O2: SISuper, ISuper {
override suspend fun invoke() {
}
}
@@ -1,3 +1,4 @@
// FIR_IDENTICAL
// !LANGUAGE: +SuspendFunctionAsSupertype
// SKIP_TXT
// DIAGNOSTICS: -CONFLICTING_INHERITED_MEMBERS, -CONFLICTING_OVERLOADS
@@ -1,20 +0,0 @@
// !LANGUAGE: +SuspendFunctionAsSupertype
// SKIP_TXT
// DIAGNOSTICS: -CONFLICTING_INHERITED_MEMBERS, -CONFLICTING_OVERLOADS
import kotlin.coroutines.*
class C: SuspendFunction0<Unit>, () -> Unit {
override suspend fun invoke() {
}
}
fun interface FI: SuspendFunction0<Unit>, () -> Unit {
}
interface I: SuspendFunction0<Unit>, () -> Unit {
}
object O: SuspendFunction0<Unit>, () -> Unit {
override suspend fun invoke() {
}
}
@@ -1,3 +1,4 @@
// FIR_IDENTICAL
// !LANGUAGE: +SuspendFunctionAsSupertype
// SKIP_TXT
// DIAGNOSTICS: -CONFLICTING_INHERITED_MEMBERS, -CONFLICTING_OVERLOADS
@@ -1,29 +0,0 @@
// !LANGUAGE: +SuspendFunctionAsSupertype
// SKIP_TXT
// DIAGNOSTICS: -CONFLICTING_INHERITED_MEMBERS, -CONFLICTING_OVERLOADS
import kotlin.coroutines.*
abstract class CSuper: () -> Unit
class C: CSuper(), SuspendFunction0<Unit> {
override suspend fun invoke() {
}
}
object O: CSuper(), SuspendFunction0<Unit> {
override suspend fun invoke() {
}
}
abstract class SCSuper: SuspendFunction0<Unit>
class C1: SCSuper(), () -> Unit {
override suspend fun invoke() {
}
}
object O1: SCSuper(), () -> Unit {
override suspend fun invoke() {
}
}
@@ -1,3 +1,4 @@
// FIR_IDENTICAL
// !LANGUAGE: +SuspendFunctionAsSupertype
// SKIP_TXT
// DIAGNOSTICS: -CONFLICTING_INHERITED_MEMBERS, -CONFLICTING_OVERLOADS
@@ -1,57 +0,0 @@
// !LANGUAGE: +SuspendFunctionAsSupertype
// SKIP_TXT
// DIAGNOSTICS: -CONFLICTING_INHERITED_MEMBERS, -CONFLICTING_OVERLOADS
import kotlin.coroutines.*
fun interface FISuper: () -> Unit
class C: SuspendFunction0<Unit>, FISuper {
override suspend fun invoke() {
}
}
fun interface FI: SuspendFunction0<Unit>, FISuper {
}
interface I: SuspendFunction0<Unit>, FISuper {
}
object O: SuspendFunction0<Unit>, FISuper {
override suspend fun invoke() {
}
}
fun interface SFISuper: SuspendFunction0<Unit>
class C1: SFISuper, () -> Unit {
override suspend fun invoke() {
}
}
fun interface FI1: SFISuper, () -> Unit {
}
interface I1: SFISuper, () -> Unit {
}
object O1: SFISuper, () -> Unit {
override suspend fun invoke() {
}
}
class C2: SFISuper, FISuper {
override suspend fun invoke() {
}
}
fun interface FI2: SFISuper, FISuper {
}
interface I2: SFISuper, FISuper {
}
object O2: SFISuper, FISuper {
override suspend fun invoke() {
}
}
@@ -1,3 +1,4 @@
// FIR_IDENTICAL
// !LANGUAGE: +SuspendFunctionAsSupertype
// SKIP_TXT
// DIAGNOSTICS: -CONFLICTING_INHERITED_MEMBERS, -CONFLICTING_OVERLOADS
@@ -1,57 +0,0 @@
// !LANGUAGE: +SuspendFunctionAsSupertype
// SKIP_TXT
// DIAGNOSTICS: -CONFLICTING_INHERITED_MEMBERS, -CONFLICTING_OVERLOADS
import kotlin.coroutines.*
interface ISuper: () -> Unit
class C: SuspendFunction0<Unit>, ISuper {
override suspend fun invoke() {
}
}
fun interface FI: SuspendFunction0<Unit>, ISuper {
}
interface I: SuspendFunction0<Unit>, ISuper {
}
object O: SuspendFunction0<Unit>, ISuper {
override suspend fun invoke() {
}
}
interface SISuper: SuspendFunction0<Unit>
class C1: SISuper, () -> Unit {
override suspend fun invoke() {
}
}
fun interface FI1: SISuper, () -> Unit {
}
interface I1: SISuper, () -> Unit {
}
object O1: SISuper, () -> Unit {
override suspend fun invoke() {
}
}
class C2: SISuper, ISuper {
override suspend fun invoke() {
}
}
fun interface FI2: SISuper, ISuper {
}
interface I2: SISuper, ISuper {
}
object O2: SISuper, ISuper {
override suspend fun invoke() {
}
}
@@ -1,3 +1,4 @@
// FIR_IDENTICAL
// !LANGUAGE: +SuspendFunctionAsSupertype
// SKIP_TXT
// DIAGNOSTICS: -CONFLICTING_INHERITED_MEMBERS, -CONFLICTING_OVERLOADS