Forbid usages of super if in fact it accesses an abstract member
#KT-49017 Fixed
This commit is contained in:
+6
@@ -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,
|
||||
|
||||
+4
@@ -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
|
||||
|
||||
+5
@@ -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,
|
||||
|
||||
+12
@@ -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 {
|
||||
|
||||
+12
@@ -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 {
|
||||
|
||||
+12
@@ -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 {
|
||||
|
||||
+1
@@ -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
|
||||
|
||||
+19
-2
@@ -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)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+2
@@ -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);
|
||||
|
||||
+1
@@ -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);
|
||||
|
||||
+7
@@ -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))
|
||||
|
||||
+5
@@ -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,
|
||||
|
||||
+12
-2
@@ -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)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+6
@@ -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)
|
||||
|
||||
+26
@@ -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()
|
||||
}
|
||||
+52
@@ -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
|
||||
}
|
||||
Vendored
+26
@@ -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()
|
||||
}
|
||||
Vendored
+52
@@ -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
|
||||
}
|
||||
Generated
+12
@@ -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
|
||||
|
||||
|
||||
Reference in New Issue
Block a user