Provide migration of Any functions via super in abstract case
Related to KT-38078
This commit is contained in:
@@ -120,6 +120,7 @@ public interface BindingContext {
|
|||||||
WritableSlice<KtExpression, DoubleColonLHS> DOUBLE_COLON_LHS = new BasicWritableSlice<>(DO_NOTHING);
|
WritableSlice<KtExpression, DoubleColonLHS> DOUBLE_COLON_LHS = new BasicWritableSlice<>(DO_NOTHING);
|
||||||
|
|
||||||
WritableSlice<KtSuperExpression, KotlinType> THIS_TYPE_FOR_SUPER_EXPRESSION = new BasicWritableSlice<>(DO_NOTHING);
|
WritableSlice<KtSuperExpression, KotlinType> THIS_TYPE_FOR_SUPER_EXPRESSION = new BasicWritableSlice<>(DO_NOTHING);
|
||||||
|
WritableSlice<KtSuperExpression, Boolean> SUPER_EXPRESSION_FROM_ANY_MIGRATION = Slices.createSimpleSlice();
|
||||||
|
|
||||||
WritableSlice<KtReferenceExpression, DeclarationDescriptor> REFERENCE_TARGET = new BasicWritableSlice<>(DO_NOTHING);
|
WritableSlice<KtReferenceExpression, DeclarationDescriptor> REFERENCE_TARGET = new BasicWritableSlice<>(DO_NOTHING);
|
||||||
// if 'A' really means 'A.Companion' then this slice stores class descriptor for A, REFERENCE_TARGET stores descriptor Companion in this case
|
// if 'A' really means 'A.Companion' then this slice stores class descriptor for A, REFERENCE_TARGET stores descriptor Companion in this case
|
||||||
|
|||||||
+12
-2
@@ -76,12 +76,22 @@ class DiagnosticReporterByTrackingStrategy(
|
|||||||
(diagnostic as NoValueForParameter).parameterDescriptor
|
(diagnostic as NoValueForParameter).parameterDescriptor
|
||||||
)
|
)
|
||||||
InstantiationOfAbstractClass::class.java -> tracingStrategy.instantiationOfAbstractClass(trace)
|
InstantiationOfAbstractClass::class.java -> tracingStrategy.instantiationOfAbstractClass(trace)
|
||||||
AbstractSuperCall::class.java -> tracingStrategy.abstractSuperCall(trace)
|
AbstractSuperCall::class.java -> {
|
||||||
|
val superExpression = (diagnostic as AbstractSuperCall).receiver.psiExpression as? KtSuperExpression
|
||||||
|
if (context.languageVersionSettings.supportsFeature(LanguageFeature.ForbidSuperDelegationToAbstractAnyMethod) ||
|
||||||
|
superExpression == null ||
|
||||||
|
trace[BindingContext.SUPER_EXPRESSION_FROM_ANY_MIGRATION, superExpression] != true
|
||||||
|
) {
|
||||||
|
tracingStrategy.abstractSuperCall(trace)
|
||||||
|
} else {
|
||||||
|
tracingStrategy.abstractSuperCallWarning(trace)
|
||||||
|
}
|
||||||
|
}
|
||||||
AbstractFakeOverrideSuperCall::class.java -> {
|
AbstractFakeOverrideSuperCall::class.java -> {
|
||||||
if (context.languageVersionSettings.supportsFeature(LanguageFeature.ForbidSuperDelegationToAbstractFakeOverride)) {
|
if (context.languageVersionSettings.supportsFeature(LanguageFeature.ForbidSuperDelegationToAbstractFakeOverride)) {
|
||||||
tracingStrategy.abstractSuperCall(trace)
|
tracingStrategy.abstractSuperCall(trace)
|
||||||
} else {
|
} else {
|
||||||
tracingStrategy.abstractFakeOverrideSuperCall(trace)
|
tracingStrategy.abstractSuperCallWarning(trace)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
NonApplicableCallForBuilderInferenceDiagnostic::class.java -> {
|
NonApplicableCallForBuilderInferenceDiagnostic::class.java -> {
|
||||||
|
|||||||
+1
-1
@@ -143,7 +143,7 @@ public abstract class AbstractTracingStrategy implements TracingStrategy {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void abstractFakeOverrideSuperCall(@NotNull BindingTrace trace) {
|
public void abstractSuperCallWarning(@NotNull BindingTrace trace) {
|
||||||
trace.report(ABSTRACT_SUPER_CALL_WARNING.on(reference));
|
trace.report(ABSTRACT_SUPER_CALL_WARNING.on(reference));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -148,7 +148,7 @@ public interface TracingStrategy {
|
|||||||
|
|
||||||
void abstractSuperCall(@NotNull BindingTrace trace);
|
void abstractSuperCall(@NotNull BindingTrace trace);
|
||||||
|
|
||||||
default void abstractFakeOverrideSuperCall(@NotNull BindingTrace trace) {
|
default void abstractSuperCallWarning(@NotNull BindingTrace trace) {
|
||||||
abstractSuperCall(trace);
|
abstractSuperCall(trace);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+7
-3
@@ -22,6 +22,7 @@ import com.intellij.psi.StubBasedPsiElement;
|
|||||||
import com.intellij.psi.tree.IElementType;
|
import com.intellij.psi.tree.IElementType;
|
||||||
import com.intellij.psi.tree.TokenSet;
|
import com.intellij.psi.tree.TokenSet;
|
||||||
import com.intellij.psi.util.PsiTreeUtil;
|
import com.intellij.psi.util.PsiTreeUtil;
|
||||||
|
import kotlin.Pair;
|
||||||
import kotlin.TuplesKt;
|
import kotlin.TuplesKt;
|
||||||
import kotlin.collections.CollectionsKt;
|
import kotlin.collections.CollectionsKt;
|
||||||
import org.jetbrains.annotations.NotNull;
|
import org.jetbrains.annotations.NotNull;
|
||||||
@@ -46,7 +47,6 @@ import org.jetbrains.kotlin.resolve.*;
|
|||||||
import org.jetbrains.kotlin.resolve.bindingContextUtil.BindingContextUtilsKt;
|
import org.jetbrains.kotlin.resolve.bindingContextUtil.BindingContextUtilsKt;
|
||||||
import org.jetbrains.kotlin.resolve.calls.ArgumentTypeResolver;
|
import org.jetbrains.kotlin.resolve.calls.ArgumentTypeResolver;
|
||||||
import org.jetbrains.kotlin.resolve.calls.CallExpressionResolver;
|
import org.jetbrains.kotlin.resolve.calls.CallExpressionResolver;
|
||||||
import org.jetbrains.kotlin.resolve.calls.util.CallUtilKt;
|
|
||||||
import org.jetbrains.kotlin.resolve.calls.checkers.*;
|
import org.jetbrains.kotlin.resolve.calls.checkers.*;
|
||||||
import org.jetbrains.kotlin.resolve.calls.model.DataFlowInfoForArgumentsImpl;
|
import org.jetbrains.kotlin.resolve.calls.model.DataFlowInfoForArgumentsImpl;
|
||||||
import org.jetbrains.kotlin.resolve.calls.model.ResolvedCall;
|
import org.jetbrains.kotlin.resolve.calls.model.ResolvedCall;
|
||||||
@@ -62,13 +62,13 @@ import org.jetbrains.kotlin.resolve.calls.tasks.OldResolutionCandidate;
|
|||||||
import org.jetbrains.kotlin.resolve.calls.tasks.TracingStrategy;
|
import org.jetbrains.kotlin.resolve.calls.tasks.TracingStrategy;
|
||||||
import org.jetbrains.kotlin.resolve.calls.tower.NewAbstractResolvedCall;
|
import org.jetbrains.kotlin.resolve.calls.tower.NewAbstractResolvedCall;
|
||||||
import org.jetbrains.kotlin.resolve.calls.util.CallMaker;
|
import org.jetbrains.kotlin.resolve.calls.util.CallMaker;
|
||||||
|
import org.jetbrains.kotlin.resolve.calls.util.CallUtilKt;
|
||||||
import org.jetbrains.kotlin.resolve.checkers.UnderscoreChecker;
|
import org.jetbrains.kotlin.resolve.checkers.UnderscoreChecker;
|
||||||
import org.jetbrains.kotlin.resolve.constants.*;
|
import org.jetbrains.kotlin.resolve.constants.*;
|
||||||
import org.jetbrains.kotlin.resolve.scopes.LexicalScopeKind;
|
import org.jetbrains.kotlin.resolve.scopes.LexicalScopeKind;
|
||||||
import org.jetbrains.kotlin.resolve.scopes.LexicalWritableScope;
|
import org.jetbrains.kotlin.resolve.scopes.LexicalWritableScope;
|
||||||
import org.jetbrains.kotlin.resolve.scopes.receivers.ContextReceiver;
|
import org.jetbrains.kotlin.resolve.scopes.receivers.ContextReceiver;
|
||||||
import org.jetbrains.kotlin.resolve.scopes.receivers.ExpressionReceiver;
|
import org.jetbrains.kotlin.resolve.scopes.receivers.ExpressionReceiver;
|
||||||
import org.jetbrains.kotlin.resolve.scopes.receivers.ExtensionReceiver;
|
|
||||||
import org.jetbrains.kotlin.resolve.scopes.receivers.ReceiverValue;
|
import org.jetbrains.kotlin.resolve.scopes.receivers.ReceiverValue;
|
||||||
import org.jetbrains.kotlin.resolve.scopes.utils.ScopeUtilsKt;
|
import org.jetbrains.kotlin.resolve.scopes.utils.ScopeUtilsKt;
|
||||||
import org.jetbrains.kotlin.types.*;
|
import org.jetbrains.kotlin.types.*;
|
||||||
@@ -512,9 +512,13 @@ public class BasicExpressionTypingVisitor extends ExpressionTypingVisitor {
|
|||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
if (UnqualifiedSuperKt.isPossiblyAmbiguousUnqualifiedSuper(expression, supertypes)) {
|
if (UnqualifiedSuperKt.isPossiblyAmbiguousUnqualifiedSuper(expression, supertypes)) {
|
||||||
Collection<KotlinType> supertypesResolvedFromContext =
|
Pair<Collection<KotlinType>, Boolean> supertypesResolvedFromContextWithEqualsMigration =
|
||||||
UnqualifiedSuperKt.resolveUnqualifiedSuperFromExpressionContext(
|
UnqualifiedSuperKt.resolveUnqualifiedSuperFromExpressionContext(
|
||||||
expression, supertypes, components.builtIns.getAnyType());
|
expression, supertypes, components.builtIns.getAnyType());
|
||||||
|
Collection<KotlinType> supertypesResolvedFromContext = supertypesResolvedFromContextWithEqualsMigration.getFirst();
|
||||||
|
if (supertypesResolvedFromContextWithEqualsMigration.getSecond()) {
|
||||||
|
context.trace.record(SUPER_EXPRESSION_FROM_ANY_MIGRATION, expression, true);
|
||||||
|
}
|
||||||
if (supertypesResolvedFromContext.size() == 1) {
|
if (supertypesResolvedFromContext.size() == 1) {
|
||||||
KotlinType singleResolvedType = supertypesResolvedFromContext.iterator().next();
|
KotlinType singleResolvedType = supertypesResolvedFromContext.iterator().next();
|
||||||
result = substitutor.substitute(singleResolvedType, Variance.INVARIANT);
|
result = substitutor.substitute(singleResolvedType, Variance.INVARIANT);
|
||||||
|
|||||||
+13
-13
@@ -37,7 +37,7 @@ fun resolveUnqualifiedSuperFromExpressionContext(
|
|||||||
superExpression: KtSuperExpression,
|
superExpression: KtSuperExpression,
|
||||||
supertypes: Collection<KotlinType>,
|
supertypes: Collection<KotlinType>,
|
||||||
anyType: KotlinType
|
anyType: KotlinType
|
||||||
): Collection<KotlinType> {
|
): Pair<Collection<KotlinType>, Boolean> {
|
||||||
val parentElement = superExpression.parent
|
val parentElement = superExpression.parent
|
||||||
|
|
||||||
if (parentElement is KtDotQualifiedExpression) {
|
if (parentElement is KtDotQualifiedExpression) {
|
||||||
@@ -50,19 +50,19 @@ fun resolveUnqualifiedSuperFromExpressionContext(
|
|||||||
return if (isCallingMethodOfAny(selectorExpression, calleeName)) {
|
return if (isCallingMethodOfAny(selectorExpression, calleeName)) {
|
||||||
resolveSupertypesForMethodOfAny(supertypes, calleeName, anyType)
|
resolveSupertypesForMethodOfAny(supertypes, calleeName, anyType)
|
||||||
} else {
|
} else {
|
||||||
resolveSupertypesByCalleeName(supertypes, calleeName)
|
resolveSupertypesByCalleeName(supertypes, calleeName) to false
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
is KtSimpleNameExpression -> {
|
is KtSimpleNameExpression -> {
|
||||||
// super.x: x can be a property only
|
// super.x: x can be a property only
|
||||||
// NB there are no properties in kotlin.Any
|
// NB there are no properties in kotlin.Any
|
||||||
return resolveSupertypesByPropertyName(supertypes, selectorExpression.getReferencedNameAsName())
|
return resolveSupertypesByPropertyName(supertypes, selectorExpression.getReferencedNameAsName()) to false
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return emptyList()
|
return emptyList<KotlinType>() to false
|
||||||
}
|
}
|
||||||
|
|
||||||
private val ARITY_OF_METHODS_OF_ANY = hashMapOf("hashCode" to 0, "equals" to 1, "toString" to 0)
|
private val ARITY_OF_METHODS_OF_ANY = hashMapOf("hashCode" to 0, "equals" to 1, "toString" to 0)
|
||||||
@@ -99,29 +99,29 @@ private fun resolveSupertypesForMethodOfAny(
|
|||||||
supertypes: Collection<KotlinType>,
|
supertypes: Collection<KotlinType>,
|
||||||
calleeName: Name,
|
calleeName: Name,
|
||||||
anyType: KotlinType
|
anyType: KotlinType
|
||||||
): Collection<KotlinType> {
|
): Pair<Collection<KotlinType>, Boolean> {
|
||||||
val typesWithConcreteOverride = resolveSupertypesByMembers(supertypes, allowNonConcreteInterfaceMembers = false) {
|
val (typesWithConcreteOverride, isEqualsMigration) = resolveSupertypesByMembers(supertypes, allowNonConcreteInterfaceMembers = false) {
|
||||||
getFunctionMembers(it, calleeName)
|
getFunctionMembers(it, calleeName)
|
||||||
}
|
}
|
||||||
return typesWithConcreteOverride.ifEmpty { listOf(anyType) }
|
return typesWithConcreteOverride.ifEmpty { listOf(anyType) } to isEqualsMigration
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun resolveSupertypesByCalleeName(supertypes: Collection<KotlinType>, calleeName: Name): Collection<KotlinType> =
|
private fun resolveSupertypesByCalleeName(supertypes: Collection<KotlinType>, calleeName: Name): Collection<KotlinType> =
|
||||||
resolveSupertypesByMembers(supertypes, allowNonConcreteInterfaceMembers = true) {
|
resolveSupertypesByMembers(supertypes, allowNonConcreteInterfaceMembers = true) {
|
||||||
getFunctionMembers(it, calleeName) +
|
getFunctionMembers(it, calleeName) +
|
||||||
getPropertyMembers(it, calleeName)
|
getPropertyMembers(it, calleeName)
|
||||||
}
|
}.first
|
||||||
|
|
||||||
private fun resolveSupertypesByPropertyName(supertypes: Collection<KotlinType>, propertyName: Name): Collection<KotlinType> =
|
private fun resolveSupertypesByPropertyName(supertypes: Collection<KotlinType>, propertyName: Name): Collection<KotlinType> =
|
||||||
resolveSupertypesByMembers(supertypes, allowNonConcreteInterfaceMembers = true) {
|
resolveSupertypesByMembers(supertypes, allowNonConcreteInterfaceMembers = true) {
|
||||||
getPropertyMembers(it, propertyName)
|
getPropertyMembers(it, propertyName)
|
||||||
}
|
}.first
|
||||||
|
|
||||||
private inline fun resolveSupertypesByMembers(
|
private inline fun resolveSupertypesByMembers(
|
||||||
supertypes: Collection<KotlinType>,
|
supertypes: Collection<KotlinType>,
|
||||||
allowNonConcreteInterfaceMembers: Boolean,
|
allowNonConcreteInterfaceMembers: Boolean,
|
||||||
getMembers: (KotlinType) -> Collection<CallableMemberDescriptor>
|
getMembers: (KotlinType) -> Collection<CallableMemberDescriptor>
|
||||||
): Collection<KotlinType> {
|
): Pair<Collection<KotlinType>, Boolean> {
|
||||||
val typesWithConcreteMembers = SmartList<KotlinType>()
|
val typesWithConcreteMembers = SmartList<KotlinType>()
|
||||||
val typesWithNonConcreteMembers = SmartList<KotlinType>()
|
val typesWithNonConcreteMembers = SmartList<KotlinType>()
|
||||||
|
|
||||||
@@ -143,13 +143,13 @@ private inline fun resolveSupertypesByMembers(
|
|||||||
|
|
||||||
return when {
|
return when {
|
||||||
typesWithConcreteMembers.isNotEmpty() ->
|
typesWithConcreteMembers.isNotEmpty() ->
|
||||||
typesWithConcreteMembers
|
typesWithConcreteMembers to false
|
||||||
allowNonConcreteInterfaceMembers ->
|
allowNonConcreteInterfaceMembers ->
|
||||||
typesWithNonConcreteMembers
|
typesWithNonConcreteMembers to false
|
||||||
else ->
|
else ->
|
||||||
typesWithNonConcreteMembers.filter {
|
typesWithNonConcreteMembers.filter {
|
||||||
TypeUtils.getClassDescriptor(it)?.kind == ClassKind.CLASS
|
TypeUtils.getClassDescriptor(it)?.kind == ClassKind.CLASS
|
||||||
}
|
} to true
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+2
-3
@@ -812,9 +812,8 @@ internal object CheckSuperExpressionCallPart : ResolutionPart() {
|
|||||||
if (callComponents.statelessCallbacks.isSuperExpression(resolvedCall.dispatchReceiverArgument)) {
|
if (callComponents.statelessCallbacks.isSuperExpression(resolvedCall.dispatchReceiverArgument)) {
|
||||||
if (candidateDescriptor is CallableMemberDescriptor) {
|
if (candidateDescriptor is CallableMemberDescriptor) {
|
||||||
if (candidateDescriptor.modality == Modality.ABSTRACT) {
|
if (candidateDescriptor.modality == Modality.ABSTRACT) {
|
||||||
addDiagnostic(AbstractSuperCall)
|
addDiagnostic(AbstractSuperCall(resolvedCall.dispatchReceiverArgument!!))
|
||||||
}
|
} else if (candidateDescriptor.kind == CallableMemberDescriptor.Kind.FAKE_OVERRIDE &&
|
||||||
if (candidateDescriptor.kind == CallableMemberDescriptor.Kind.FAKE_OVERRIDE &&
|
|
||||||
candidateDescriptor.overriddenDescriptors.size > 1
|
candidateDescriptor.overriddenDescriptors.size > 1
|
||||||
) {
|
) {
|
||||||
if (candidateDescriptor.overriddenDescriptors.firstOrNull { !it.isInsideInterface }?.modality == Modality.ABSTRACT) {
|
if (candidateDescriptor.overriddenDescriptors.firstOrNull { !it.isInsideInterface }?.modality == Modality.ABSTRACT) {
|
||||||
|
|||||||
+1
-1
@@ -202,7 +202,7 @@ object InstantiationOfAbstractClass : KotlinCallDiagnostic(RUNTIME_ERROR) {
|
|||||||
override fun report(reporter: DiagnosticReporter) = reporter.onCall(this)
|
override fun report(reporter: DiagnosticReporter) = reporter.onCall(this)
|
||||||
}
|
}
|
||||||
|
|
||||||
object AbstractSuperCall : KotlinCallDiagnostic(RUNTIME_ERROR) {
|
class AbstractSuperCall(val receiver: SimpleKotlinCallArgument) : KotlinCallDiagnostic(RUNTIME_ERROR) {
|
||||||
override fun report(reporter: DiagnosticReporter) {
|
override fun report(reporter: DiagnosticReporter) {
|
||||||
reporter.onCall(this)
|
reporter.onCall(this)
|
||||||
}
|
}
|
||||||
|
|||||||
+25
@@ -0,0 +1,25 @@
|
|||||||
|
// !LANGUAGE: -ForbidSuperDelegationToAbstractFakeOverride -ForbidSuperDelegationToAbstractAnyMethod
|
||||||
|
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.<!ABSTRACT_SUPER_CALL!>hashCode<!>()
|
||||||
|
}
|
||||||
+2
-3
@@ -1,5 +1,4 @@
|
|||||||
// FIR_IDENTICAL
|
// !LANGUAGE: -ForbidSuperDelegationToAbstractFakeOverride -ForbidSuperDelegationToAbstractAnyMethod
|
||||||
// !LANGUAGE: -ForbidSuperDelegationToAbstractFakeOverride
|
|
||||||
interface Foo {
|
interface Foo {
|
||||||
fun check(): String = "OK"
|
fun check(): String = "OK"
|
||||||
}
|
}
|
||||||
@@ -22,5 +21,5 @@ abstract class A {
|
|||||||
interface I
|
interface I
|
||||||
|
|
||||||
class B : A(), I { // I is necessary here
|
class B : A(), I { // I is necessary here
|
||||||
override fun hashCode() = super.<!ABSTRACT_SUPER_CALL!>hashCode<!>()
|
override fun hashCode() = super.<!ABSTRACT_SUPER_CALL_WARNING!>hashCode<!>()
|
||||||
}
|
}
|
||||||
|
|||||||
Vendored
+1
-1
@@ -1,5 +1,5 @@
|
|||||||
// FIR_IDENTICAL
|
// FIR_IDENTICAL
|
||||||
// !LANGUAGE: +ForbidSuperDelegationToAbstractFakeOverride
|
// !LANGUAGE: +ForbidSuperDelegationToAbstractFakeOverride +ForbidSuperDelegationToAbstractAnyMethod
|
||||||
interface Foo {
|
interface Foo {
|
||||||
fun check(): String = "OK"
|
fun check(): String = "OK"
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -253,7 +253,8 @@ enum class LanguageFeature(
|
|||||||
ProhibitConfusingSyntaxInWhenBranches(KOTLIN_1_8, kind = BUG_FIX), // KT-48385
|
ProhibitConfusingSyntaxInWhenBranches(KOTLIN_1_8, kind = BUG_FIX), // KT-48385
|
||||||
UseConsistentRulesForPrivateConstructorsOfSealedClasses(sinceVersion = KOTLIN_1_8, kind = BUG_FIX), // KT-44866
|
UseConsistentRulesForPrivateConstructorsOfSealedClasses(sinceVersion = KOTLIN_1_8, kind = BUG_FIX), // KT-44866
|
||||||
ProgressionsChangingResolve(KOTLIN_1_8), // KT-49276
|
ProgressionsChangingResolve(KOTLIN_1_8), // KT-49276
|
||||||
ForbidSuperDelegationToAbstractFakeOverride(KOTLIN_1_8), // KT-49017 (+ KT-38078)
|
ForbidSuperDelegationToAbstractFakeOverride(KOTLIN_1_8), // KT-49017
|
||||||
|
ForbidSuperDelegationToAbstractAnyMethod(KOTLIN_1_8), // KT-38078
|
||||||
|
|
||||||
// 1.9
|
// 1.9
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user