[FIR JS] Implement FirJsInheritanceChecker

This commit is contained in:
Nikolay Lunyak
2023-01-04 15:37:15 +02:00
committed by Space Team
parent 9e1c6f2f61
commit 4cf8d9ffb9
17 changed files with 235 additions and 29 deletions
@@ -4648,6 +4648,25 @@ internal val KT_DIAGNOSTIC_CONVERTER = KtDiagnosticConverterBuilder.buildConvert
token,
)
}
add(FirJsErrors.IMPLEMENTING_FUNCTION_INTERFACE) { firDiagnostic ->
ImplementingFunctionInterfaceImpl(
firDiagnostic as KtPsiDiagnostic,
token,
)
}
add(FirJsErrors.OVERRIDING_EXTERNAL_FUN_WITH_OPTIONAL_PARAMS) { firDiagnostic ->
OverridingExternalFunWithOptionalParamsImpl(
firDiagnostic as KtPsiDiagnostic,
token,
)
}
add(FirJsErrors.OVERRIDING_EXTERNAL_FUN_WITH_OPTIONAL_PARAMS_WITH_FAKE) { firDiagnostic ->
OverridingExternalFunWithOptionalParamsWithFakeImpl(
firSymbolBuilder.functionLikeBuilder.buildFunctionSymbol(firDiagnostic.a),
firDiagnostic as KtPsiDiagnostic,
token,
)
}
add(FirJsErrors.DELEGATION_BY_DYNAMIC) { firDiagnostic ->
DelegationByDynamicImpl(
firDiagnostic as KtPsiDiagnostic,
@@ -3233,6 +3233,19 @@ sealed class KtFirDiagnostic<PSI : PsiElement> : KtDiagnosticWithPsi<PSI> {
override val diagnosticClass get() = JavaSamInterfaceConstructorReference::class
}
abstract class ImplementingFunctionInterface : KtFirDiagnostic<KtClassOrObject>() {
override val diagnosticClass get() = ImplementingFunctionInterface::class
}
abstract class OverridingExternalFunWithOptionalParams : KtFirDiagnostic<KtElement>() {
override val diagnosticClass get() = OverridingExternalFunWithOptionalParams::class
}
abstract class OverridingExternalFunWithOptionalParamsWithFake : KtFirDiagnostic<KtElement>() {
override val diagnosticClass get() = OverridingExternalFunWithOptionalParamsWithFake::class
abstract val function: KtFunctionLikeSymbol
}
abstract class DelegationByDynamic : KtFirDiagnostic<KtElement>() {
override val diagnosticClass get() = DelegationByDynamic::class
}
@@ -3911,6 +3911,22 @@ internal class JavaSamInterfaceConstructorReferenceImpl(
override val token: KtLifetimeToken,
) : KtFirDiagnostic.JavaSamInterfaceConstructorReference(), KtAbstractFirDiagnostic<PsiElement>
internal class ImplementingFunctionInterfaceImpl(
override val firDiagnostic: KtPsiDiagnostic,
override val token: KtLifetimeToken,
) : KtFirDiagnostic.ImplementingFunctionInterface(), KtAbstractFirDiagnostic<KtClassOrObject>
internal class OverridingExternalFunWithOptionalParamsImpl(
override val firDiagnostic: KtPsiDiagnostic,
override val token: KtLifetimeToken,
) : KtFirDiagnostic.OverridingExternalFunWithOptionalParams(), KtAbstractFirDiagnostic<KtElement>
internal class OverridingExternalFunWithOptionalParamsWithFakeImpl(
override val function: KtFunctionLikeSymbol,
override val firDiagnostic: KtPsiDiagnostic,
override val token: KtLifetimeToken,
) : KtFirDiagnostic.OverridingExternalFunWithOptionalParamsWithFake(), KtAbstractFirDiagnostic<KtElement>
internal class DelegationByDynamicImpl(
override val firDiagnostic: KtPsiDiagnostic,
override val token: KtLifetimeToken,
@@ -9,6 +9,8 @@ import org.jetbrains.kotlin.fir.PrivateForInline
import org.jetbrains.kotlin.fir.checkers.generator.diagnostics.model.DiagnosticList
import org.jetbrains.kotlin.fir.checkers.generator.diagnostics.model.PositioningStrategy
import org.jetbrains.kotlin.fir.symbols.impl.FirCallableSymbol
import org.jetbrains.kotlin.fir.symbols.impl.FirNamedFunctionSymbol
import org.jetbrains.kotlin.psi.KtClassOrObject
import org.jetbrains.kotlin.psi.KtElement
@Suppress("UNUSED_VARIABLE", "LocalVariableName", "ClassName", "unused")
@@ -27,6 +29,17 @@ object JS_DIAGNOSTICS_LIST : DiagnosticList("FirJsErrors") {
}
}
val FUN_INTERFACES by object : DiagnosticGroup("Fun Interfaces") {
val IMPLEMENTING_FUNCTION_INTERFACE by error<KtClassOrObject>(PositioningStrategy.DECLARATION_SIGNATURE_OR_DEFAULT)
}
val EXTERNAL by object : DiagnosticGroup("External") {
val OVERRIDING_EXTERNAL_FUN_WITH_OPTIONAL_PARAMS by error<KtElement>(PositioningStrategy.DECLARATION_SIGNATURE_OR_DEFAULT)
val OVERRIDING_EXTERNAL_FUN_WITH_OPTIONAL_PARAMS_WITH_FAKE by error<KtElement>(PositioningStrategy.DECLARATION_SIGNATURE_OR_DEFAULT) {
parameter<FirNamedFunctionSymbol>("function")
}
}
val DYNAMICS by object : DiagnosticGroup("Dynamics") {
val DELEGATION_BY_DYNAMIC by error<KtElement>()
}
@@ -10,6 +10,8 @@ import org.jetbrains.kotlin.diagnostics.SourceElementPositioningStrategies
import org.jetbrains.kotlin.diagnostics.rendering.RootDiagnosticRendererFactory
import org.jetbrains.kotlin.fir.analysis.diagnostics.*
import org.jetbrains.kotlin.fir.symbols.impl.FirCallableSymbol
import org.jetbrains.kotlin.fir.symbols.impl.FirNamedFunctionSymbol
import org.jetbrains.kotlin.psi.KtClassOrObject
import org.jetbrains.kotlin.psi.KtElement
/*
@@ -27,6 +29,13 @@ object FirJsErrors {
// Supertypes
val WRONG_MULTIPLE_INHERITANCE by error1<KtElement, FirCallableSymbol<*>>(SourceElementPositioningStrategies.DECLARATION_SIGNATURE_OR_DEFAULT)
// Fun Interfaces
val IMPLEMENTING_FUNCTION_INTERFACE by error0<KtClassOrObject>(SourceElementPositioningStrategies.DECLARATION_SIGNATURE_OR_DEFAULT)
// External
val OVERRIDING_EXTERNAL_FUN_WITH_OPTIONAL_PARAMS by error0<KtElement>(SourceElementPositioningStrategies.DECLARATION_SIGNATURE_OR_DEFAULT)
val OVERRIDING_EXTERNAL_FUN_WITH_OPTIONAL_PARAMS_WITH_FAKE by error1<KtElement, FirNamedFunctionSymbol>(SourceElementPositioningStrategies.DECLARATION_SIGNATURE_OR_DEFAULT)
// Dynamics
val DELEGATION_BY_DYNAMIC by error0<KtElement>()
@@ -10,9 +10,12 @@ import org.jetbrains.kotlin.diagnostics.rendering.BaseDiagnosticRendererFactory
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirDiagnosticRenderers
import org.jetbrains.kotlin.fir.analysis.diagnostics.checkMissingMessages
import org.jetbrains.kotlin.fir.analysis.diagnostics.js.FirJsErrors.DELEGATION_BY_DYNAMIC
import org.jetbrains.kotlin.fir.analysis.diagnostics.js.FirJsErrors.IMPLEMENTING_FUNCTION_INTERFACE
import org.jetbrains.kotlin.fir.analysis.diagnostics.js.FirJsErrors.JS_MODULE_PROHIBITED_ON_NON_NATIVE
import org.jetbrains.kotlin.fir.analysis.diagnostics.js.FirJsErrors.JS_MODULE_PROHIBITED_ON_VAR
import org.jetbrains.kotlin.fir.analysis.diagnostics.js.FirJsErrors.NESTED_JS_MODULE_PROHIBITED
import org.jetbrains.kotlin.fir.analysis.diagnostics.js.FirJsErrors.OVERRIDING_EXTERNAL_FUN_WITH_OPTIONAL_PARAMS
import org.jetbrains.kotlin.fir.analysis.diagnostics.js.FirJsErrors.OVERRIDING_EXTERNAL_FUN_WITH_OPTIONAL_PARAMS_WITH_FAKE
import org.jetbrains.kotlin.fir.analysis.diagnostics.js.FirJsErrors.WRONG_JS_QUALIFIER
import org.jetbrains.kotlin.fir.analysis.diagnostics.js.FirJsErrors.WRONG_MULTIPLE_INHERITANCE
@@ -32,6 +35,13 @@ object FirJsErrorsDefaultMessages : BaseDiagnosticRendererFactory() {
FirDiagnosticRenderers.SYMBOL
)
map.put(DELEGATION_BY_DYNAMIC, "Can't delegate to dynamic value")
map.put(IMPLEMENTING_FUNCTION_INTERFACE, "Implementing function interface is prohibited in JavaScript")
map.put(OVERRIDING_EXTERNAL_FUN_WITH_OPTIONAL_PARAMS, "Overriding `external` function with optional parameters")
map.put(
OVERRIDING_EXTERNAL_FUN_WITH_OPTIONAL_PARAMS_WITH_FAKE,
"Overriding `external` function with optional parameters by declaration from superclass: {0}",
FirDiagnosticRenderers.SYMBOL
)
map.checkMissingMessages(FirJsErrors)
}
@@ -7,12 +7,16 @@
package org.jetbrains.kotlin.fir.analysis.js.checkers
import org.jetbrains.kotlin.descriptors.Modality
import org.jetbrains.kotlin.fir.FirSession
import org.jetbrains.kotlin.fir.analysis.checkers.context.CheckerContext
import org.jetbrains.kotlin.fir.analysis.checkers.directOverriddenFunctions
import org.jetbrains.kotlin.fir.analysis.checkers.getContainingClassSymbol
import org.jetbrains.kotlin.fir.analysis.checkers.hasAnnotationOrInsideAnnotatedClass
import org.jetbrains.kotlin.fir.declarations.*
import org.jetbrains.kotlin.fir.declarations.utils.isExternal
import org.jetbrains.kotlin.fir.declarations.utils.modality
import org.jetbrains.kotlin.fir.isSubstitutionOrIntersectionOverride
import org.jetbrains.kotlin.fir.symbols.FirBasedSymbol
import org.jetbrains.kotlin.fir.symbols.SymbolInternals
import org.jetbrains.kotlin.fir.symbols.impl.*
@@ -42,6 +46,20 @@ fun FirBasedSymbol<*>.isEffectivelyExternal(session: FirSession): Boolean {
return getContainingClassSymbol(session)?.isEffectivelyExternal(session) == true
}
fun FirBasedSymbol<*>.isEffectivelyExternal(context: CheckerContext) = isEffectivelyExternal(context.session)
fun FirFunctionSymbol<*>.isOverridingExternalWithOptionalParams(context: CheckerContext): Boolean {
if (!isSubstitutionOrIntersectionOverride && modality == Modality.ABSTRACT) return false
val overridden = (this as? FirNamedFunctionSymbol)?.directOverriddenFunctions(context) ?: return false
for (overriddenFunction in overridden.filter { it.isEffectivelyExternal(context) }) {
if (overriddenFunction.valueParameterSymbols.any { it.hasDefaultValue }) return true
}
return false
}
fun FirBasedSymbol<*>.isNativeObject(session: FirSession): Boolean {
if (hasAnnotationOrInsideAnnotatedClass(JsStandardClassIds.Annotations.JsNative, session) || isEffectivelyExternal(session)) {
return true
@@ -12,6 +12,7 @@ object JsDeclarationCheckers : DeclarationCheckers() {
override val functionCheckers: Set<FirFunctionChecker>
get() = setOf(
FirJsInlineDeclarationChecker,
FirJsInheritanceFunctionChecker,
)
override val propertyCheckers: Set<FirPropertyChecker>
@@ -28,5 +29,6 @@ object JsDeclarationCheckers : DeclarationCheckers() {
get() = setOf(
FirJsMultipleInheritanceChecker,
FirJsDynamicDeclarationChecker,
FirJsInheritanceClassChecker,
)
}
@@ -0,0 +1,72 @@
/*
* Copyright 2010-2023 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.js.checkers.declaration
import org.jetbrains.kotlin.config.LanguageFeature
import org.jetbrains.kotlin.diagnostics.DiagnosticReporter
import org.jetbrains.kotlin.diagnostics.reportOn
import org.jetbrains.kotlin.fir.FirSession
import org.jetbrains.kotlin.fir.analysis.checkers.context.CheckerContext
import org.jetbrains.kotlin.fir.analysis.checkers.declaration.FirClassChecker
import org.jetbrains.kotlin.fir.analysis.checkers.getContainingClassSymbol
import org.jetbrains.kotlin.fir.analysis.checkers.unsubstitutedScope
import org.jetbrains.kotlin.fir.analysis.diagnostics.js.FirJsErrors
import org.jetbrains.kotlin.fir.analysis.js.checkers.isEffectivelyExternal
import org.jetbrains.kotlin.fir.analysis.js.checkers.isOverridingExternalWithOptionalParams
import org.jetbrains.kotlin.fir.declarations.FirClass
import org.jetbrains.kotlin.fir.declarations.utils.superConeTypes
import org.jetbrains.kotlin.fir.scopes.collectAllFunctions
import org.jetbrains.kotlin.fir.symbols.impl.FirIntersectionOverrideFunctionSymbol
import org.jetbrains.kotlin.fir.symbols.impl.FirNamedFunctionSymbol
import org.jetbrains.kotlin.fir.types.ConeClassLikeType
import org.jetbrains.kotlin.fir.types.typeContext
object FirJsInheritanceClassChecker : FirClassChecker() {
override fun check(declaration: FirClass, context: CheckerContext, reporter: DiagnosticReporter) {
if (!declaration.symbol.isEffectivelyExternal(context)) {
val fakeOverriddenMethod = declaration.findFakeMethodOverridingExternalWithOptionalParams(context)
if (fakeOverriddenMethod != null) {
reporter.reportOn(
declaration.source, FirJsErrors.OVERRIDING_EXTERNAL_FUN_WITH_OPTIONAL_PARAMS_WITH_FAKE,
fakeOverriddenMethod, context
)
}
}
if (
!context.languageVersionSettings.supportsFeature(LanguageFeature.JsAllowImplementingFunctionInterface) &&
declaration.superConeTypes.any {
it.isBuiltinFunctionalTypeOrSubtype(context.session) && !it.isSuspendFunctionTypeOrSubtype(context.session)
}
) {
reporter.reportOn(declaration.source, FirJsErrors.IMPLEMENTING_FUNCTION_INTERFACE, context)
}
}
private fun ConeClassLikeType.isBuiltinFunctionalTypeOrSubtype(session: FirSession): Boolean {
return with(session.typeContext) { isBuiltinFunctionalTypeOrSubtype() }
}
private fun ConeClassLikeType.isSuspendFunctionTypeOrSubtype(session: FirSession): Boolean {
return with(session.typeContext) { isSuspendFunctionTypeOrSubtype() }
}
private fun FirClass.findFakeMethodOverridingExternalWithOptionalParams(context: CheckerContext): FirNamedFunctionSymbol? {
val scope = symbol.unsubstitutedScope(context)
val members = scope.collectAllFunctions()
.filterIsInstance<FirIntersectionOverrideFunctionSymbol>()
.filter {
val container = it.getContainingClassSymbol(context.session)
container == symbol && it.intersections.isNotEmpty()
}
return members.firstOrNull {
it.isOverridingExternalWithOptionalParams(context)
}
}
}
@@ -0,0 +1,29 @@
/*
* Copyright 2010-2023 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.js.checkers.declaration
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.checkers.declaration.FirFunctionChecker
import org.jetbrains.kotlin.fir.analysis.js.checkers.isEffectivelyExternal
import org.jetbrains.kotlin.fir.analysis.js.checkers.isOverridingExternalWithOptionalParams
import org.jetbrains.kotlin.fir.analysis.diagnostics.js.FirJsErrors
import org.jetbrains.kotlin.fir.declarations.FirDeclaration
import org.jetbrains.kotlin.fir.declarations.FirFunction
object FirJsInheritanceFunctionChecker : FirFunctionChecker() {
override fun check(declaration: FirFunction, context: CheckerContext, reporter: DiagnosticReporter) {
if (declaration.isNotEffectivelyExternalFunctionButOverridesExternal(context)) {
reporter.reportOn(declaration.source, FirJsErrors.OVERRIDING_EXTERNAL_FUN_WITH_OPTIONAL_PARAMS, context)
}
}
private fun FirDeclaration.isNotEffectivelyExternalFunctionButOverridesExternal(context: CheckerContext): Boolean {
if (this !is FirFunction || symbol.isEffectivelyExternal(context)) return false
return symbol.isOverridingExternalWithOptionalParams(context)
}
}
@@ -14,34 +14,26 @@ import org.jetbrains.kotlin.descriptors.Modality
import org.jetbrains.kotlin.descriptors.Visibilities
import org.jetbrains.kotlin.descriptors.annotations.KotlinTarget
import org.jetbrains.kotlin.diagnostics.*
import org.jetbrains.kotlin.fir.FirSession
import org.jetbrains.kotlin.fir.*
import org.jetbrains.kotlin.fir.analysis.checkers.context.CheckerContext
import org.jetbrains.kotlin.fir.analysis.checkers.declaration.primaryConstructorSymbol
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors
import org.jetbrains.kotlin.fir.analysis.getChild
import org.jetbrains.kotlin.fir.containingClassForLocalAttr
import org.jetbrains.kotlin.fir.containingClassLookupTag
import org.jetbrains.kotlin.fir.declarations.*
import org.jetbrains.kotlin.fir.declarations.utils.*
import org.jetbrains.kotlin.fir.expressions.*
import org.jetbrains.kotlin.fir.expressions.impl.FirEmptyExpressionBlock
import org.jetbrains.kotlin.fir.references.FirSuperReference
import org.jetbrains.kotlin.fir.references.toResolvedCallableSymbol
import org.jetbrains.kotlin.fir.resolve.SessionHolder
import org.jetbrains.kotlin.fir.resolve.fullyExpandedType
import org.jetbrains.kotlin.fir.declarations.fullyExpandedClass
import org.jetbrains.kotlin.fir.resolve.*
import org.jetbrains.kotlin.fir.resolve.providers.symbolProvider
import org.jetbrains.kotlin.fir.resolve.toFirRegularClassSymbol
import org.jetbrains.kotlin.fir.resolve.toSymbol
import org.jetbrains.kotlin.fir.scopes.FirTypeScope
import org.jetbrains.kotlin.fir.scopes.ProcessorAction
import org.jetbrains.kotlin.fir.scopes.*
import org.jetbrains.kotlin.fir.scopes.impl.multipleDelegatesWithTheSameSignature
import org.jetbrains.kotlin.fir.scopes.processOverriddenFunctions
import org.jetbrains.kotlin.fir.scopes.unsubstitutedScope
import org.jetbrains.kotlin.fir.symbols.FirBasedSymbol
import org.jetbrains.kotlin.fir.symbols.SymbolInternals
import org.jetbrains.kotlin.fir.symbols.impl.*
import org.jetbrains.kotlin.fir.types.*
import org.jetbrains.kotlin.fir.unwrapFakeOverrides
import org.jetbrains.kotlin.lexer.KtTokens
import org.jetbrains.kotlin.name.*
import org.jetbrains.kotlin.psi.KtParameter
@@ -138,11 +130,13 @@ fun FirTypeRef.toRegularClassSymbol(session: FirSession): FirRegularClassSymbol?
* Returns the ClassLikeDeclaration where the Fir object has been defined
* or null if no proper declaration has been found.
*/
fun FirDeclaration.getContainingClassSymbol(session: FirSession): FirClassLikeSymbol<*>? =
(this as? FirCallableDeclaration)?.containingClassLookupTag()?.toSymbol(session)
fun FirBasedSymbol<*>.getContainingClassSymbol(session: FirSession): FirClassLikeSymbol<*>? = when (this) {
is FirCallableSymbol<*> -> containingClassLookupTag()?.toSymbol(session)
is FirClassLikeSymbol<*> -> getContainingClassLookupTag()?.toSymbol(session)
else -> null
}
@OptIn(SymbolInternals::class)
fun FirBasedSymbol<*>.getContainingClassSymbol(session: FirSession): FirClassLikeSymbol<*>? = fir.getContainingClassSymbol(session)
fun FirDeclaration.getContainingClassSymbol(session: FirSession) = symbol.getContainingClassSymbol(session)
fun FirClassLikeSymbol<*>.outerClassSymbol(context: CheckerContext): FirClassLikeSymbol<*>? {
if (this !is FirClassSymbol<*>) return null
@@ -708,6 +702,17 @@ fun ConeKotlinType.getInlineClassUnderlyingType(session: FirSession): ConeKotlin
return toRegularClassSymbol(session)!!.primaryConstructorSymbol()!!.valueParameterSymbols[0].resolvedReturnTypeRef.coneType
}
fun FirNamedFunctionSymbol.directOverriddenFunctions(session: FirSession, scopeSession: ScopeSession): List<FirNamedFunctionSymbol> {
val classSymbol = getContainingClassSymbol(session) as? FirClassSymbol ?: return emptyList()
val scope = classSymbol.unsubstitutedScope(session, scopeSession, withForcedTypeCalculator = false)
scope.processFunctionsByName(name) { }
return scope.getDirectOverriddenFunctions(this, true)
}
fun FirNamedFunctionSymbol.directOverriddenFunctions(context: CheckerContext) =
directOverriddenFunctions(context.session, context.sessionHolder.scopeSession)
fun CheckerContext.closestNonLocalWith(declaration: FirDeclaration) =
(containingDeclarations + declaration).takeWhile { it.isNonLocal }.lastOrNull()
@@ -32,3 +32,9 @@ fun FirContainingNamesAwareScope.collectAllProperties(): Collection<FirVariableS
processAllProperties(this::add)
}
}
fun FirContainingNamesAwareScope.collectAllFunctions(): Collection<FirNamedFunctionSymbol> {
return mutableListOf<FirNamedFunctionSymbol>().apply {
processAllFunctions(this::add)
}
}
@@ -1,4 +1,5 @@
// IGNORE_BACKEND_K1: JS, JS_IR
// IGNORE_BACKEND_K2: JS_IR
fun interface Foo : () -> Int
@@ -1,4 +1,5 @@
// IGNORE_BACKEND_K1: JS_IR
// IGNORE_BACKEND_K2: JS_IR
// IGNORE_BACKEND: JS_IR_ES6
//KT-3822 Compiler crashes when use invoke convention with `this` in class which extends Function0<T>
// IGNORE_BACKEND: JS
@@ -1,9 +0,0 @@
abstract class A : () -> Unit
object B : (String, Int) -> Long {
override fun invoke(a: String, B: Int) = 23L
}
abstract class C : kotlin.Function1<Any, Int>
abstract class D : C()
@@ -1,3 +1,4 @@
// FIR_IDENTICAL
abstract class <!IMPLEMENTING_FUNCTION_INTERFACE!>A<!> : () -> Unit
<!IMPLEMENTING_FUNCTION_INTERFACE!>object B<!> : (String, Int) -> Long {
@@ -3,7 +3,7 @@ open external class A {
}
class B : A() {
override fun f(x: Int) {}
<!OVERRIDING_EXTERNAL_FUN_WITH_OPTIONAL_PARAMS!>override fun f(x: Int)<!> {}
}
class BB : A()
@@ -36,7 +36,7 @@ class E : D() {
}
class F : D(), I {
override fun f(x: Int) {}
<!OVERRIDING_EXTERNAL_FUN_WITH_OPTIONAL_PARAMS!>override fun f(x: Int)<!> {}
}
external class G : D, I {
@@ -51,9 +51,9 @@ open external class XE {
fun f(x: Int)
}
class Y : X(), I
class <!OVERRIDING_EXTERNAL_FUN_WITH_OPTIONAL_PARAMS_WITH_FAKE!>Y<!> : X(), I
class YY : A(), II
class <!OVERRIDING_EXTERNAL_FUN_WITH_OPTIONAL_PARAMS_WITH_FAKE!>YY<!> : A(), II
external class YE: XE, I