Forbid usages of super if in fact it accesses an abstract member

#KT-49017 Fixed
This commit is contained in:
Mikhail Glukhikh
2022-01-10 14:19:19 +03:00
parent d15270b9e5
commit b689bbf5c7
23 changed files with 279 additions and 4 deletions
@@ -392,6 +392,12 @@ internal val KT_DIAGNOSTIC_CONVERTER = KtDiagnosticConverterBuilder.buildConvert
token,
)
}
add(FirErrors.ABSTRACT_SUPER_CALL_WARNING) { firDiagnostic ->
AbstractSuperCallWarningImpl(
firDiagnostic as KtPsiDiagnostic,
token,
)
}
add(FirErrors.INSTANCE_ACCESS_BEFORE_SUPER_CALL) { firDiagnostic ->
InstanceAccessBeforeSuperCallImpl(
firDiagnostic.a,
@@ -307,6 +307,10 @@ sealed class KtFirDiagnostic<PSI : PsiElement> : KtDiagnosticWithPsi<PSI> {
override val diagnosticClass get() = AbstractSuperCall::class
}
abstract class AbstractSuperCallWarning : KtFirDiagnostic<PsiElement>() {
override val diagnosticClass get() = AbstractSuperCallWarning::class
}
abstract class InstanceAccessBeforeSuperCall : KtFirDiagnostic<PsiElement>() {
override val diagnosticClass get() = InstanceAccessBeforeSuperCall::class
abstract val target: String
@@ -356,6 +356,11 @@ internal class AbstractSuperCallImpl(
override val token: ValidityToken,
) : KtFirDiagnostic.AbstractSuperCall(), KtAbstractFirDiagnostic<PsiElement>
internal class AbstractSuperCallWarningImpl(
override val firDiagnostic: KtPsiDiagnostic,
override val token: ValidityToken,
) : KtFirDiagnostic.AbstractSuperCallWarning(), KtAbstractFirDiagnostic<PsiElement>
internal class InstanceAccessBeforeSuperCallImpl(
override val target: String,
override val firDiagnostic: KtPsiDiagnostic,
@@ -18587,6 +18587,18 @@ public class DiagnosisCompilerTestFE10TestdataTestGenerated extends AbstractDiag
runTest("compiler/testData/diagnostics/tests/java8Overrides/abstractBaseClassMemberNotImplemented_15.kt");
}
@Test
@TestMetadata("abstractFakeOverrideSuperCall.kt")
public void testAbstractFakeOverrideSuperCall() throws Exception {
runTest("compiler/testData/diagnostics/tests/java8Overrides/abstractFakeOverrideSuperCall.kt");
}
@Test
@TestMetadata("abstractFakeOverrideSuperCallForbidden.kt")
public void testAbstractFakeOverrideSuperCallForbidden() throws Exception {
runTest("compiler/testData/diagnostics/tests/java8Overrides/abstractFakeOverrideSuperCallForbidden.kt");
}
@Test
@TestMetadata("abstractVsAbstract.kt")
public void testAbstractVsAbstract() throws Exception {
@@ -18587,6 +18587,18 @@ public class FirOldFrontendDiagnosticsTestGenerated extends AbstractFirDiagnosti
runTest("compiler/testData/diagnostics/tests/java8Overrides/abstractBaseClassMemberNotImplemented_15.kt");
}
@Test
@TestMetadata("abstractFakeOverrideSuperCall.kt")
public void testAbstractFakeOverrideSuperCall() throws Exception {
runTest("compiler/testData/diagnostics/tests/java8Overrides/abstractFakeOverrideSuperCall.kt");
}
@Test
@TestMetadata("abstractFakeOverrideSuperCallForbidden.kt")
public void testAbstractFakeOverrideSuperCallForbidden() throws Exception {
runTest("compiler/testData/diagnostics/tests/java8Overrides/abstractFakeOverrideSuperCallForbidden.kt");
}
@Test
@TestMetadata("abstractVsAbstract.kt")
public void testAbstractVsAbstract() throws Exception {
@@ -18587,6 +18587,18 @@ public class FirOldFrontendDiagnosticsWithLightTreeTestGenerated extends Abstrac
runTest("compiler/testData/diagnostics/tests/java8Overrides/abstractBaseClassMemberNotImplemented_15.kt");
}
@Test
@TestMetadata("abstractFakeOverrideSuperCall.kt")
public void testAbstractFakeOverrideSuperCall() throws Exception {
runTest("compiler/testData/diagnostics/tests/java8Overrides/abstractFakeOverrideSuperCall.kt");
}
@Test
@TestMetadata("abstractFakeOverrideSuperCallForbidden.kt")
public void testAbstractFakeOverrideSuperCallForbidden() throws Exception {
runTest("compiler/testData/diagnostics/tests/java8Overrides/abstractFakeOverrideSuperCallForbidden.kt");
}
@Test
@TestMetadata("abstractVsAbstract.kt")
public void testAbstractVsAbstract() throws Exception {
@@ -149,6 +149,7 @@ object DIAGNOSTICS_LIST : DiagnosticList("FirErrors") {
val SUPER_IS_NOT_AN_EXPRESSION by error<PsiElement>(PositioningStrategy.REFERENCED_NAME_BY_QUALIFIED)
val SUPER_NOT_AVAILABLE by error<PsiElement>(PositioningStrategy.REFERENCED_NAME_BY_QUALIFIED)
val ABSTRACT_SUPER_CALL by error<PsiElement>(PositioningStrategy.REFERENCED_NAME_BY_QUALIFIED)
val ABSTRACT_SUPER_CALL_WARNING by warning<PsiElement>(PositioningStrategy.REFERENCED_NAME_BY_QUALIFIED)
val INSTANCE_ACCESS_BEFORE_SUPER_CALL by error<PsiElement> {
parameter<String>("target")
}
@@ -165,6 +165,7 @@ object FirErrors {
val SUPER_IS_NOT_AN_EXPRESSION by error0<PsiElement>(SourceElementPositioningStrategies.REFERENCED_NAME_BY_QUALIFIED)
val SUPER_NOT_AVAILABLE by error0<PsiElement>(SourceElementPositioningStrategies.REFERENCED_NAME_BY_QUALIFIED)
val ABSTRACT_SUPER_CALL by error0<PsiElement>(SourceElementPositioningStrategies.REFERENCED_NAME_BY_QUALIFIED)
val ABSTRACT_SUPER_CALL_WARNING by warning0<PsiElement>(SourceElementPositioningStrategies.REFERENCED_NAME_BY_QUALIFIED)
val INSTANCE_ACCESS_BEFORE_SUPER_CALL by error1<PsiElement, String>()
// Supertypes
@@ -5,12 +5,14 @@
package org.jetbrains.kotlin.fir.analysis.checkers.expression
import org.jetbrains.kotlin.config.LanguageFeature
import org.jetbrains.kotlin.descriptors.ClassKind
import org.jetbrains.kotlin.fir.analysis.checkers.context.CheckerContext
import org.jetbrains.kotlin.fir.analysis.checkers.context.findClosest
import org.jetbrains.kotlin.diagnostics.DiagnosticReporter
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors
import org.jetbrains.kotlin.diagnostics.reportOn
import org.jetbrains.kotlin.fir.analysis.checkers.classKind
import org.jetbrains.kotlin.fir.containingClass
import org.jetbrains.kotlin.fir.declarations.FirRegularClass
import org.jetbrains.kotlin.fir.declarations.utils.isAbstract
@@ -18,6 +20,7 @@ import org.jetbrains.kotlin.fir.expressions.FirQualifiedAccessExpression
import org.jetbrains.kotlin.fir.expressions.toResolvedCallableSymbol
import org.jetbrains.kotlin.fir.references.FirSuperReference
import org.jetbrains.kotlin.fir.resolve.toSymbol
import org.jetbrains.kotlin.fir.symbols.impl.FirIntersectionCallableSymbol
import org.jetbrains.kotlin.fir.symbols.impl.FirRegularClassSymbol
import org.jetbrains.kotlin.utils.addToStdlib.safeAs
@@ -37,8 +40,22 @@ object FirAbstractSuperCallChecker : FirQualifiedAccessExpressionChecker() {
val containingClassSymbol = declarationSymbol.containingClass()?.toSymbol(context.session) as? FirRegularClassSymbol ?: return
if (containingClassSymbol.isAbstract && declarationSymbol.isAbstract) {
reporter.reportOn(expression.calleeReference.source, FirErrors.ABSTRACT_SUPER_CALL, context)
if (containingClassSymbol.isAbstract) {
if (declarationSymbol.isAbstract) {
reporter.reportOn(expression.calleeReference.source, FirErrors.ABSTRACT_SUPER_CALL, context)
}
if (declarationSymbol is FirIntersectionCallableSymbol) {
val symbolFromBaseClass = declarationSymbol.intersections.firstOrNull {
it.containingClass()?.toSymbol(context.session)?.classKind != ClassKind.INTERFACE
}
if (symbolFromBaseClass?.isAbstract == true) {
if (context.languageVersionSettings.supportsFeature(LanguageFeature.ForbidSuperDelegationToAbstractFakeOverride)) {
reporter.reportOn(expression.calleeReference.source, FirErrors.ABSTRACT_SUPER_CALL, context)
} else {
reporter.reportOn(expression.calleeReference.source, FirErrors.ABSTRACT_SUPER_CALL_WARNING, context)
}
}
}
}
}
}
@@ -45,6 +45,7 @@ import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.ABSTRACT_PROPERTY
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.ABSTRACT_PROPERTY_WITH_INITIALIZER
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.ABSTRACT_PROPERTY_WITH_SETTER
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.ABSTRACT_SUPER_CALL
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.ABSTRACT_SUPER_CALL_WARNING
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.ACCESSOR_FOR_DELEGATED_PROPERTY
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.ACTUAL_ANNOTATION_CONFLICTING_DEFAULT_ARGUMENT_VALUE
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.ACTUAL_FUNCTION_WITH_DEFAULT_ARGUMENTS
@@ -642,6 +643,7 @@ object FirErrorsDefaultMessages : BaseDiagnosticRendererFactory() {
map.put(SUPER_IS_NOT_AN_EXPRESSION, "Super cannot be a callee")
map.put(SUPER_NOT_AVAILABLE, "No supertypes are accessible in this context")
map.put(ABSTRACT_SUPER_CALL, "Abstract member cannot be accessed directly")
map.put(ABSTRACT_SUPER_CALL_WARNING, "Abstract fake override member access is deprecated")
map.put(
INSTANCE_ACCESS_BEFORE_SUPER_CALL,
"Cannot access ''{0}'' before superclass constructor has been called",
@@ -933,6 +933,7 @@ public interface Errors {
DiagnosticFactory0<KtSuperExpression> SUPERCLASS_NOT_ACCESSIBLE_FROM_INTERFACE = DiagnosticFactory0.create(ERROR);
DiagnosticFactory0<KtSuperExpression> AMBIGUOUS_SUPER = DiagnosticFactory0.create(ERROR);
DiagnosticFactory0<KtExpression> ABSTRACT_SUPER_CALL = DiagnosticFactory0.create(ERROR);
DiagnosticFactory0<KtExpression> ABSTRACT_SUPER_CALL_WARNING = DiagnosticFactory0.create(WARNING);
DiagnosticFactory0<KtTypeReference> NOT_A_SUPERTYPE = DiagnosticFactory0.create(ERROR);
DiagnosticFactory0<PsiElement> TYPE_ARGUMENTS_REDUNDANT_IN_SUPER_QUALIFIER = DiagnosticFactory0.create(WARNING);
DiagnosticFactory1<KtTypeReference, KotlinType> QUALIFIED_SUPERTYPE_EXTENDED_BY_OTHER_SUPERTYPE = DiagnosticFactory1.create(ERROR);
@@ -491,6 +491,7 @@ public class DefaultErrorMessages {
MAP.put(SUPERCLASS_NOT_ACCESSIBLE_FROM_INTERFACE, "Superclass is not accessible from interface");
MAP.put(AMBIGUOUS_SUPER, "Many supertypes available, please specify the one you mean in angle brackets, e.g. 'super<Foo>'");
MAP.put(ABSTRACT_SUPER_CALL, "Abstract member cannot be accessed directly");
MAP.put(ABSTRACT_SUPER_CALL_WARNING, "Abstract fake override member access is deprecated");
MAP.put(NOT_A_SUPERTYPE, "Not an immediate supertype");
MAP.put(TYPE_ARGUMENTS_REDUNDANT_IN_SUPER_QUALIFIER, "Type arguments do not need to be specified in a 'super' qualifier");
MAP.put(QUALIFIED_SUPERTYPE_EXTENDED_BY_OTHER_SUPERTYPE, "Explicitly qualified supertype is extended by another supertype ''{0}''", RENDER_TYPE);
@@ -77,6 +77,13 @@ class DiagnosticReporterByTrackingStrategy(
)
InstantiationOfAbstractClass::class.java -> tracingStrategy.instantiationOfAbstractClass(trace)
AbstractSuperCall::class.java -> tracingStrategy.abstractSuperCall(trace)
AbstractFakeOverrideSuperCall::class.java -> {
if (context.languageVersionSettings.supportsFeature(LanguageFeature.ForbidSuperDelegationToAbstractFakeOverride)) {
tracingStrategy.abstractSuperCall(trace)
} else {
tracingStrategy.abstractFakeOverrideSuperCall(trace)
}
}
NonApplicableCallForBuilderInferenceDiagnostic::class.java -> {
val reportOn = (diagnostic as NonApplicableCallForBuilderInferenceDiagnostic).kotlinCall
trace.reportDiagnosticOnce(NON_APPLICABLE_CALL_FOR_BUILDER_INFERENCE.on(reportOn.psiKotlinCall.psiCall.callElement))
@@ -142,6 +142,11 @@ public abstract class AbstractTracingStrategy implements TracingStrategy {
trace.report(ABSTRACT_SUPER_CALL.on(reference));
}
@Override
public void abstractFakeOverrideSuperCall(@NotNull BindingTrace trace) {
trace.report(ABSTRACT_SUPER_CALL_WARNING.on(reference));
}
@Override
public void nestedClassAccessViaInstanceReference(
@NotNull BindingTrace trace,
@@ -148,6 +148,10 @@ public interface TracingStrategy {
void abstractSuperCall(@NotNull BindingTrace trace);
default void abstractFakeOverrideSuperCall(@NotNull BindingTrace trace) {
abstractSuperCall(trace);
}
void nestedClassAccessViaInstanceReference(
@NotNull BindingTrace trace,
@NotNull ClassDescriptor classDescriptor,
@@ -23,6 +23,7 @@ import org.jetbrains.kotlin.resolve.calls.tower.ContextReceiverAmbiguity
import org.jetbrains.kotlin.resolve.calls.tower.InfixCallNoInfixModifier
import org.jetbrains.kotlin.resolve.calls.tower.InvokeConventionCallNoOperatorModifier
import org.jetbrains.kotlin.resolve.calls.tower.VisibilityError
import org.jetbrains.kotlin.resolve.descriptorUtil.isInsideInterface
import org.jetbrains.kotlin.resolve.scopes.LexicalScope
import org.jetbrains.kotlin.resolve.scopes.receivers.ReceiverValueWithSmartCastInfo
import org.jetbrains.kotlin.resolve.scopes.utils.parentsWithSelf
@@ -809,8 +810,17 @@ internal object CheckSuperExpressionCallPart : ResolutionPart() {
val candidateDescriptor = resolvedCall.candidateDescriptor
if (callComponents.statelessCallbacks.isSuperExpression(resolvedCall.dispatchReceiverArgument)) {
if (candidateDescriptor is MemberDescriptor && candidateDescriptor.modality == Modality.ABSTRACT) {
addDiagnostic(AbstractSuperCall)
if (candidateDescriptor is CallableMemberDescriptor) {
if (candidateDescriptor.modality == Modality.ABSTRACT) {
addDiagnostic(AbstractSuperCall)
}
if (candidateDescriptor.kind == CallableMemberDescriptor.Kind.FAKE_OVERRIDE &&
candidateDescriptor.overriddenDescriptors.size > 1
) {
if (candidateDescriptor.overriddenDescriptors.firstOrNull { !it.isInsideInterface }?.modality == Modality.ABSTRACT) {
addDiagnostic(AbstractFakeOverrideSuperCall)
}
}
}
}
@@ -208,6 +208,12 @@ object AbstractSuperCall : KotlinCallDiagnostic(RUNTIME_ERROR) {
}
}
object AbstractFakeOverrideSuperCall : KotlinCallDiagnostic(RUNTIME_ERROR) {
override fun report(reporter: DiagnosticReporter) {
reporter.onCall(this)
}
}
class SuperAsExtensionReceiver(val receiver: SimpleKotlinCallArgument) : KotlinCallDiagnostic(RUNTIME_ERROR) {
override fun report(reporter: DiagnosticReporter) {
reporter.onCallReceiver(receiver, this)
@@ -0,0 +1,26 @@
// FIR_IDENTICAL
// !LANGUAGE: -ForbidSuperDelegationToAbstractFakeOverride
interface Foo {
fun check(): String = "OK"
}
abstract class Base {
abstract fun check(): String
}
abstract class Derived : Base(), Foo
class Derived2 : Derived() {
override fun check(): String {
super<Derived>.<!ABSTRACT_SUPER_CALL_WARNING!>check<!>()
return super.<!ABSTRACT_SUPER_CALL_WARNING!>check<!>()
}
}
abstract class A {
abstract override fun hashCode(): Int
}
interface I
class B : A(), I { // I is necessary here
override fun hashCode() = super.hashCode()
}
@@ -0,0 +1,52 @@
package
public abstract class A {
public constructor A()
public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean
public abstract override /*1*/ fun hashCode(): kotlin.Int
public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String
}
public final class B : A, I {
public constructor B()
public open override /*2*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean
public open override /*2*/ fun hashCode(): kotlin.Int
public open override /*2*/ /*fake_override*/ fun toString(): kotlin.String
}
public abstract class Base {
public constructor Base()
public abstract fun check(): kotlin.String
public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean
public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int
public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String
}
public abstract class Derived : Base, Foo {
public constructor Derived()
public open override /*2*/ /*fake_override*/ fun check(): kotlin.String
public open override /*2*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean
public open override /*2*/ /*fake_override*/ fun hashCode(): kotlin.Int
public open override /*2*/ /*fake_override*/ fun toString(): kotlin.String
}
public final class Derived2 : Derived {
public constructor Derived2()
public open override /*1*/ fun check(): kotlin.String
public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean
public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int
public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String
}
public interface Foo {
public open fun check(): kotlin.String
public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean
public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int
public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String
}
public interface I {
public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean
public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int
public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String
}
@@ -0,0 +1,26 @@
// FIR_IDENTICAL
// !LANGUAGE: +ForbidSuperDelegationToAbstractFakeOverride
interface Foo {
fun check(): String = "OK"
}
abstract class Base {
abstract fun check(): String
}
abstract class Derived : Base(), Foo
class Derived2 : Derived() {
override fun check(): String {
super<Derived>.<!ABSTRACT_SUPER_CALL!>check<!>()
return super.<!ABSTRACT_SUPER_CALL!>check<!>()
}
}
abstract class A {
abstract override fun hashCode(): Int
}
interface I
class B : A(), I { // I is necessary here
override fun hashCode() = super.hashCode()
}
@@ -0,0 +1,52 @@
package
public abstract class A {
public constructor A()
public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean
public abstract override /*1*/ fun hashCode(): kotlin.Int
public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String
}
public final class B : A, I {
public constructor B()
public open override /*2*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean
public open override /*2*/ fun hashCode(): kotlin.Int
public open override /*2*/ /*fake_override*/ fun toString(): kotlin.String
}
public abstract class Base {
public constructor Base()
public abstract fun check(): kotlin.String
public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean
public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int
public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String
}
public abstract class Derived : Base, Foo {
public constructor Derived()
public open override /*2*/ /*fake_override*/ fun check(): kotlin.String
public open override /*2*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean
public open override /*2*/ /*fake_override*/ fun hashCode(): kotlin.Int
public open override /*2*/ /*fake_override*/ fun toString(): kotlin.String
}
public final class Derived2 : Derived {
public constructor Derived2()
public open override /*1*/ fun check(): kotlin.String
public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean
public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int
public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String
}
public interface Foo {
public open fun check(): kotlin.String
public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean
public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int
public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String
}
public interface I {
public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean
public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int
public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String
}
@@ -18593,6 +18593,18 @@ public class DiagnosticTestGenerated extends AbstractDiagnosticTest {
runTest("compiler/testData/diagnostics/tests/java8Overrides/abstractBaseClassMemberNotImplemented_15.kt");
}
@Test
@TestMetadata("abstractFakeOverrideSuperCall.kt")
public void testAbstractFakeOverrideSuperCall() throws Exception {
runTest("compiler/testData/diagnostics/tests/java8Overrides/abstractFakeOverrideSuperCall.kt");
}
@Test
@TestMetadata("abstractFakeOverrideSuperCallForbidden.kt")
public void testAbstractFakeOverrideSuperCallForbidden() throws Exception {
runTest("compiler/testData/diagnostics/tests/java8Overrides/abstractFakeOverrideSuperCallForbidden.kt");
}
@Test
@TestMetadata("abstractVsAbstract.kt")
public void testAbstractVsAbstract() throws Exception {
@@ -253,6 +253,7 @@ enum class LanguageFeature(
ProhibitConfusingSyntaxInWhenBranches(KOTLIN_1_8, kind = BUG_FIX), // KT-48385
UseConsistentRulesForPrivateConstructorsOfSealedClasses(sinceVersion = KOTLIN_1_8, kind = BUG_FIX), // KT-44866
ProgressionsChangingResolve(KOTLIN_1_8), // KT-49276
ForbidSuperDelegationToAbstractFakeOverride(KOTLIN_1_8), // KT-49017 (+ KT-38078)
// 1.9