[FIR, IR] Convert FirDefaultArgumentsInExpectActualizedByFakeOverrideChecker into ExpectActualCheckingCompatibility

FirDefaultArgumentsInExpectActualizedByFakeOverrideChecker is an adhoc
checker which can be converted to ExpectActualCheckingCompatibility to
reuse common expect-actual checking infrastructure.

^KT-62913 Fixed
Review: https://jetbrains.team/p/kt/reviews/13094/timeline

Tests that were broken by one of my previous commits are now fixed:
- actualFakeOverride_paramsAreCompatibleViaSharedMethodWithDefaultParams.kt
- inheritedJavaMembers.kt

DEFAULT_ARGUMENTS_IN_EXPECT_ACTUALIZED_BY_FAKE_OVERRIDE diagnostic
disappeared in delegation.fir.kt because only one
AbstractExpectActualChecker incompatibility can be reported at a time
(DEFAULT_ARGUMENTS_IN_EXPECT_ACTUALIZED_BY_FAKE_OVERRIDE is now reported
not by adhoc checker but by common AbstractExpectActualChecker). It
would be nice to report both of them, but it's a separate issue KT-62631

delegation2 test makes sure that
DEFAULT_ARGUMENTS_IN_EXPECT_ACTUALIZED_BY_FAKE_OVERRIDE is reported when
NO_ACTUAL_CLASS_MEMBER_FOR_EXPECTED_CLASS is fixed
This commit is contained in:
Nikita Bobko
2023-11-17 11:39:24 +01:00
committed by teamcity
parent c8a9928624
commit 7166adb179
20 changed files with 156 additions and 152 deletions
@@ -24882,6 +24882,12 @@ public class DiagnosticCompilerTestFE10TestdataTestGenerated extends AbstractDia
runTest("compiler/testData/diagnostics/tests/multiplatform/defaultArguments/methodDefaultArgsViaActualFakeOverride/delegation.kt");
}
@Test
@TestMetadata("delegation2.kt")
public void testDelegation2() throws Exception {
runTest("compiler/testData/diagnostics/tests/multiplatform/defaultArguments/methodDefaultArgsViaActualFakeOverride/delegation2.kt");
}
@Test
@TestMetadata("disabledFeature.kt")
public void testDisabledFeature() throws Exception {
@@ -24882,6 +24882,12 @@ public class LLFirPreresolvedReversedDiagnosticCompilerFE10TestDataTestGenerated
runTest("compiler/testData/diagnostics/tests/multiplatform/defaultArguments/methodDefaultArgsViaActualFakeOverride/delegation.kt");
}
@Test
@TestMetadata("delegation2.kt")
public void testDelegation2() throws Exception {
runTest("compiler/testData/diagnostics/tests/multiplatform/defaultArguments/methodDefaultArgsViaActualFakeOverride/delegation2.kt");
}
@Test
@TestMetadata("disabledFeature.kt")
public void testDisabledFeature() throws Exception {
@@ -1243,6 +1243,12 @@ public class FirOldFrontendMPPDiagnosticsWithLightTreeTestGenerated extends Abst
runTest("compiler/testData/diagnostics/tests/multiplatform/defaultArguments/methodDefaultArgsViaActualFakeOverride/delegation.kt");
}
@Test
@TestMetadata("delegation2.kt")
public void testDelegation2() throws Exception {
runTest("compiler/testData/diagnostics/tests/multiplatform/defaultArguments/methodDefaultArgsViaActualFakeOverride/delegation2.kt");
}
@Test
@TestMetadata("disabledFeature.kt")
public void testDisabledFeature() throws Exception {
@@ -1243,6 +1243,12 @@ public class FirOldFrontendMPPDiagnosticsWithPsiTestGenerated extends AbstractFi
runTest("compiler/testData/diagnostics/tests/multiplatform/defaultArguments/methodDefaultArgsViaActualFakeOverride/delegation.kt");
}
@Test
@TestMetadata("delegation2.kt")
public void testDelegation2() throws Exception {
runTest("compiler/testData/diagnostics/tests/multiplatform/defaultArguments/methodDefaultArgsViaActualFakeOverride/delegation2.kt");
}
@Test
@TestMetadata("disabledFeature.kt")
public void testDisabledFeature() throws Exception {
@@ -142,7 +142,6 @@ object CommonDeclarationCheckers : DeclarationCheckers() {
FirMultipleDefaultsInheritedFromSupertypesChecker,
FirFiniteBoundRestrictionChecker,
FirNonExpansiveInheritanceRestrictionChecker,
FirDefaultArgumentsInExpectActualizedByFakeOverrideChecker,
)
override val constructorCheckers: Set<FirConstructorChecker>
@@ -1,89 +0,0 @@
/*
* 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.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.FirExpectActualMatchingContext
import org.jetbrains.kotlin.fir.analysis.checkers.context.CheckerContext
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors
import org.jetbrains.kotlin.fir.declarations.FirRegularClass
import org.jetbrains.kotlin.fir.declarations.getSingleMatchedExpectForActualOrNull
import org.jetbrains.kotlin.fir.declarations.utils.isActual
import org.jetbrains.kotlin.fir.expectActualMatchingContextFactory
import org.jetbrains.kotlin.fir.isDelegated
import org.jetbrains.kotlin.fir.isSubstitutionOrIntersectionOverride
import org.jetbrains.kotlin.fir.symbols.impl.FirFunctionSymbol
import org.jetbrains.kotlin.fir.symbols.impl.FirNamedFunctionSymbol
import org.jetbrains.kotlin.fir.symbols.impl.FirRegularClassSymbol
import org.jetbrains.kotlin.fir.types.classId
import org.jetbrains.kotlin.mpp.DeclarationSymbolMarker
import org.jetbrains.kotlin.resolve.calls.mpp.AbstractExpectActualMatcher
import org.jetbrains.kotlin.resolve.multiplatform.ExpectActualMatchingCompatibility
// TODO KT-62913 create one more ExpectActualCheckingCompatibility incompatibility, and replace this checker with this incompatibility
internal object FirDefaultArgumentsInExpectActualizedByFakeOverrideChecker : FirRegularClassChecker() {
override fun check(declaration: FirRegularClass, context: CheckerContext, reporter: DiagnosticReporter) {
if (!context.languageVersionSettings.supportsFeature(LanguageFeature.MultiPlatformProjects) ||
!context.languageVersionSettings.supportsFeature(LanguageFeature.ProhibitDefaultArgumentsInExpectActualizedByFakeOverride)) {
return
}
if (!declaration.isActual) {
return
}
val actualClassSymbol = declaration.symbol
// We want to report errors even if a candidate is incompatible, but it's single
val expectedSingleCandidate = actualClassSymbol.getSingleMatchedExpectForActualOrNull() ?: return
val expectClassSymbol = expectedSingleCandidate as FirRegularClassSymbol
val expectActualMatchingContext = context.session.expectActualMatchingContextFactory.create(
context.session, context.scopeSession,
allowedWritingMemberExpectForActualMapping = true,
)
AbstractExpectActualMatcher.recursivelyMatchClassScopes(expectClassSymbol, actualClassSymbol, expectActualMatchingContext)
val matchingContext = context.session.expectActualMatchingContextFactory.create(context.session, context.scopeSession)
val problematicExpectMembers = with(matchingContext) { findProblematicExpectMembers(expectClassSymbol, actualClassSymbol) }
if (problematicExpectMembers.isNotEmpty()) {
reporter.reportOn(
declaration.source, FirErrors.DEFAULT_ARGUMENTS_IN_EXPECT_ACTUALIZED_BY_FAKE_OVERRIDE,
expectClassSymbol, problematicExpectMembers, context
)
}
}
private fun FirExpectActualMatchingContext.findProblematicExpectMembers(
expectClassSymbol: FirRegularClassSymbol, actualClassSymbol: FirRegularClassSymbol,
): List<FirNamedFunctionSymbol> {
val actualFakeOverrideMembers = actualClassSymbol.collectAllMembers(isActualDeclaration = true)
.filterIsInstance<FirNamedFunctionSymbol>()
.filter { it.isFakeOverride(actualClassSymbol) || it.isDelegated }
return actualFakeOverrideMembers
.mapNotNull { getSingleMatchingExpect(it, expectClassSymbol, actualClassSymbol) }
.filter(::hasDefaultArgumentValues)
}
private fun FirExpectActualMatchingContext.getSingleMatchingExpect(
actualMember: FirNamedFunctionSymbol,
expectSymbol: FirRegularClassSymbol,
actualSymbol: FirRegularClassSymbol
): FirNamedFunctionSymbol? {
val potentialExpects = findPotentialExpectClassMembersForActual(
expectSymbol, actualSymbol, actualMember,
)
val expectMember: DeclarationSymbolMarker = potentialExpects.entries
.singleOrNull { it.value == ExpectActualMatchingCompatibility.MatchedSuccessfully }?.key
?: potentialExpects.keys.singleOrNull()
?: return null
return expectMember as FirNamedFunctionSymbol
}
private fun hasDefaultArgumentValues(function: FirFunctionSymbol<*>): Boolean {
return function.valueParameterSymbols.any { it.hasDefaultValue }
}
}
@@ -6,6 +6,7 @@
package org.jetbrains.kotlin.fir.analysis.checkers.declaration
import org.jetbrains.kotlin.KtFakeSourceElementKind
import org.jetbrains.kotlin.KtSourceElement
import org.jetbrains.kotlin.config.LanguageFeature
import org.jetbrains.kotlin.descriptors.ClassKind
import org.jetbrains.kotlin.diagnostics.DiagnosticReporter
@@ -25,10 +26,7 @@ import org.jetbrains.kotlin.fir.expectActualMatchingContextFactory
import org.jetbrains.kotlin.fir.languageVersionSettings
import org.jetbrains.kotlin.fir.symbols.FirBasedSymbol
import org.jetbrains.kotlin.fir.symbols.SymbolInternals
import org.jetbrains.kotlin.fir.symbols.impl.FirCallableSymbol
import org.jetbrains.kotlin.fir.symbols.impl.FirClassLikeSymbol
import org.jetbrains.kotlin.fir.symbols.impl.FirRegularClassSymbol
import org.jetbrains.kotlin.fir.symbols.impl.FirTypeAliasSymbol
import org.jetbrains.kotlin.fir.symbols.impl.*
import org.jetbrains.kotlin.lexer.KtTokens
import org.jetbrains.kotlin.mpp.RegularClassSymbolMarker
import org.jetbrains.kotlin.name.StandardClassIds
@@ -157,7 +155,7 @@ object FirExpectActualDeclarationChecker : FirBasicDeclarationChecker() {
when {
checkingCompatibility is ExpectActualCheckingCompatibility.ClassScopes -> {
require(symbol is FirRegularClassSymbol || symbol is FirTypeAliasSymbol) {
require((symbol is FirRegularClassSymbol || symbol is FirTypeAliasSymbol) && expectedSingleCandidate is FirRegularClassSymbol) {
"Incompatible.ClassScopes is only possible for a class or a typealias: $declaration"
}
@@ -178,10 +176,35 @@ object FirExpectActualDeclarationChecker : FirBasicDeclarationChecker() {
val nonTrivialIncompatibleMembers = checkingCompatibility.incompatibleMembers.filterNot(::hasSingleActualSuspect)
if (nonTrivialIncompatibleMembers.isNotEmpty()) {
reporter.reportOn(source, FirErrors.NO_ACTUAL_CLASS_MEMBER_FOR_EXPECTED_CLASS, symbol, nonTrivialIncompatibleMembers, context)
val (defaultArgsIncompatibleMembers, otherIncompatibleMembers) =
nonTrivialIncompatibleMembers.partition { it.second.contains(ExpectActualCheckingCompatibility.DefaultArgumentsInExpectActualizedByFakeOverride) }
if (defaultArgsIncompatibleMembers.isNotEmpty()) { // report a nicer diagnostic for DefaultArgumentsInExpectActualizedByFakeOverride
val problematicExpectMembers = defaultArgsIncompatibleMembers
.map {
it.first as? FirNamedFunctionSymbol
?: error("${ExpectActualCheckingCompatibility.DefaultArgumentsInExpectActualizedByFakeOverride} can be reported only for ${FirNamedFunctionSymbol::class}")
}
reporter.reportOn(
source,
FirErrors.DEFAULT_ARGUMENTS_IN_EXPECT_ACTUALIZED_BY_FAKE_OVERRIDE,
expectedSingleCandidate,
problematicExpectMembers,
context
)
}
if (otherIncompatibleMembers.isNotEmpty()) {
reporter.reportOn(source, FirErrors.NO_ACTUAL_CLASS_MEMBER_FOR_EXPECTED_CLASS, symbol, otherIncompatibleMembers, context)
}
}
if (checkingCompatibility.mismatchedMembers.isNotEmpty()) {
reporter.reportOn(source, FirErrors.NO_ACTUAL_CLASS_MEMBER_FOR_EXPECTED_CLASS, symbol, checkingCompatibility.mismatchedMembers, context)
reporter.reportOn(
source,
FirErrors.NO_ACTUAL_CLASS_MEMBER_FOR_EXPECTED_CLASS,
symbol,
checkingCompatibility.mismatchedMembers,
context
)
}
}
@@ -43,7 +43,7 @@ class FirExpectActualMatchingContextImpl private constructor(
private val actualScopeSession: ScopeSession,
private val allowedWritingMemberExpectForActualMapping: Boolean,
) : FirExpectActualMatchingContext, TypeSystemContext by actualSession.typeContext {
override val shouldCheckAbsenceOfDefaultParamsInActual: Boolean
override val shouldCheckDefaultParams: Boolean
get() = true
override val allowClassActualizationWithWiderVisibility: Boolean
@@ -257,7 +257,7 @@ class FirExpectActualMatchingContextImpl private constructor(
override val CallableSymbolMarker.typeParameters: List<TypeParameterSymbolMarker>
get() = asSymbol().typeParameterSymbols
override fun FunctionSymbolMarker.allOverriddenDeclarationsRecursive(): Sequence<CallableSymbolMarker> {
override fun FunctionSymbolMarker.allRecursivelyOverriddenDeclarationsIncludingSelf(): Sequence<CallableSymbolMarker> {
return when (val symbol = asSymbol()) {
is FirConstructorSymbol, is FirFunctionWithoutNameSymbol -> sequenceOf(this)
is FirNamedFunctionSymbol -> {
@@ -285,6 +285,9 @@ class FirExpectActualMatchingContextImpl private constructor(
override val ValueParameterSymbolMarker.hasDefaultValue: Boolean
get() = asSymbol().hasDefaultValue
override val ValueParameterSymbolMarker.hasDefaultValueNonRecursive: Boolean
get() = asSymbol().hasDefaultValue
override fun CallableSymbolMarker.isAnnotationConstructor(): Boolean {
val symbol = asSymbol()
return symbol.isAnnotationConstructor(symbol.moduleData.session)
@@ -375,6 +378,9 @@ class FirExpectActualMatchingContextImpl private constructor(
return symbol.isSubstitutionOrIntersectionOverride
}
override val CallableSymbolMarker.isDelegatedMember: Boolean
get() = asSymbol().isDelegated
override val CallableSymbolMarker.hasStableParameterNames: Boolean
get() = asSymbol().rawStatus.hasStableParameterNames
@@ -50,7 +50,7 @@ internal abstract class IrExpectActualMatchingContext(
// This incompatibility is often suppressed in the source code (e.g. in kotlin-stdlib).
// The backend must be able to do expect-actual matching to emit bytecode
// That's why we disable the checker here. Probably, this checker can be enabled once KT-60426 is fixed
override val shouldCheckAbsenceOfDefaultParamsInActual: Boolean
override val shouldCheckDefaultParams: Boolean
get() = false
private inline fun <R> CallableSymbolMarker.processIr(
@@ -298,8 +298,16 @@ internal abstract class IrExpectActualMatchingContext(
onEnumEntry = { emptyList() }
)
override fun FunctionSymbolMarker.allOverriddenDeclarationsRecursive(): Sequence<CallableSymbolMarker> =
throw NotImplementedError("Not implemented because it's unused")
override fun FunctionSymbolMarker.allRecursivelyOverriddenDeclarationsIncludingSelf(): Sequence<CallableSymbolMarker> =
when (val node = asIr()) {
is IrConstructor -> sequenceOf(this)
is IrSimpleFunction -> (sequenceOf(this) + node.overriddenSymbols)
// Tests work even if you don't filter out fake-overrides. Filtering fake-overrides is needed because
// the returned descriptors are compared by `equals`. And `equals` for fake-overrides is weird.
// I didn't manage to invent a test that would check this condition
.filter { !it.asIr().isFakeOverride }
else -> error("Unknown IR node: $node")
}
override val FunctionSymbolMarker.valueParameters: List<ValueParameterSymbolMarker>
get() = asIr().valueParameters.map { it.symbol }
@@ -313,6 +321,9 @@ internal abstract class IrExpectActualMatchingContext(
override val ValueParameterSymbolMarker.hasDefaultValue: Boolean
get() = asIr().hasDefaultValue()
override val ValueParameterSymbolMarker.hasDefaultValueNonRecursive: Boolean
get() = asIr().defaultValue != null
override fun CallableSymbolMarker.isAnnotationConstructor(): Boolean {
val irConstructor = safeAsIr<IrConstructor>() ?: return false
return irConstructor.constructedClass.isAnnotationClass
@@ -458,6 +469,9 @@ internal abstract class IrExpectActualMatchingContext(
return asIr().isFakeOverride
}
override val CallableSymbolMarker.isDelegatedMember: Boolean
get() = asIr().origin == IrDeclarationOrigin.DELEGATED_MEMBER
override val CallableSymbolMarker.hasStableParameterNames: Boolean
get() {
var ir = asIr()
@@ -369,19 +369,31 @@ object AbstractExpectActualChecker {
getTypeParametersVarianceOrReifiedIncompatibility(expectedTypeParameters, actualTypeParameters)?.let { return it }
if (shouldCheckAbsenceOfDefaultParamsInActual) {
// "Default parameters in actual" check is required only for functions, because only functions can have parameters
if (actualDeclaration is FunctionSymbolMarker && expectDeclaration is FunctionSymbolMarker) {
// Actual annotation constructors can have default argument values; their consistency with arguments in the expected annotation
// is checked in ExpectedActualDeclarationChecker.checkAnnotationConstructors
if (!actualDeclaration.isAnnotationConstructor() &&
// If default params came from common supertypes of actual class and expect class then it's a valid code.
// Here we filter out such default params.
(actualDeclaration.allOverriddenDeclarationsRecursive() - expectDeclaration.allOverriddenDeclarationsRecursive().toSet())
.flatMap { it.valueParameters }.any { it.hasDefaultValue }
) {
return ExpectActualCheckingCompatibility.ActualFunctionWithDefaultParameters
}
if (shouldCheckDefaultParams &&
// "parameters" checks are required only for functions, because only functions can have parameters
actualDeclaration is FunctionSymbolMarker && expectDeclaration is FunctionSymbolMarker
) {
if (languageVersionSettings.supportsFeature(LanguageFeature.ProhibitDefaultArgumentsInExpectActualizedByFakeOverride) &&
(actualDeclaration.isFakeOverride(actualContainingClass) || actualDeclaration.isDelegatedMember) &&
// If default params came from common supertypes of actual class and expect class then it's a valid code.
// Here we filter out such default params.
(expectDeclaration.allRecursivelyOverriddenDeclarationsIncludingSelf() -
actualDeclaration.allRecursivelyOverriddenDeclarationsIncludingSelf().toSet())
.flatMap { it.valueParameters }.any { it.hasDefaultValueNonRecursive }
) {
return ExpectActualCheckingCompatibility.DefaultArgumentsInExpectActualizedByFakeOverride
}
// Actual annotation constructors can have default argument values; their consistency with arguments in the expected annotation
// is checked in ExpectedActualDeclarationChecker.checkAnnotationConstructors
if (!actualDeclaration.isAnnotationConstructor() &&
// If default params came from common supertypes of actual class and expect class then it's a valid code.
// Here we filter out such default params.
(actualDeclaration.allRecursivelyOverriddenDeclarationsIncludingSelf() -
expectDeclaration.allRecursivelyOverriddenDeclarationsIncludingSelf().toSet())
.flatMap { it.valueParameters }.any { it.hasDefaultValue }
) {
return ExpectActualCheckingCompatibility.ActualFunctionWithDefaultParameters
}
}
@@ -74,36 +74,6 @@ object AbstractExpectActualMatcher {
ExpectActualMatchingCompatibility.MatchedSuccessfully
}
fun recursivelyMatchClassScopes( // todo drop KT-62913
expectClassSymbol: RegularClassSymbolMarker,
actualClassSymbol: RegularClassSymbolMarker,
context: ExpectActualMatchingContext<*>,
): Unit = with(context) {
val expectTypeParameterSymbols = expectClassSymbol.typeParameters
val actualTypeParameterSymbols = actualClassSymbol.typeParameters
val substitutor = createExpectActualTypeParameterSubstitutor(
(expectTypeParameterSymbols zipIfSizesAreEqual actualTypeParameterSymbols) ?: return,
parentSubstitutor = null,
)
val actualMembersByName = actualClassSymbol.collectAllMembers(isActualDeclaration = true).groupBy { it.name }
outer@ for (expectMember in expectClassSymbol.collectAllMembers(isActualDeclaration = false)) {
val actualMembers = getPossibleActualsByExpectName(expectMember, actualMembersByName)
matchSingleExpectAgainstPotentialActuals(
expectMember,
actualMembers,
substitutor,
expectClassSymbol,
actualClassSymbol,
mismatchedMembers = null,
)
}
// TODO: check static scope?
}
/**
* Besides returning the matched declaration
*
@@ -40,7 +40,7 @@ interface ExpectActualMatchingContext<T : DeclarationSymbolMarker> : TypeSystemC
// Known clients that do suppress:
// - stdlib
// - coroutines
val shouldCheckAbsenceOfDefaultParamsInActual: Boolean
val shouldCheckDefaultParams: Boolean
/**
* This flag determines, how visibilities for classes/typealiases will be matched
@@ -123,9 +123,9 @@ interface ExpectActualMatchingContext<T : DeclarationSymbolMarker> : TypeSystemC
val FunctionSymbolMarker.valueParameters: List<ValueParameterSymbolMarker>
/**
* Returns all symbols that are overridden by [this] symbol
* Returns all symbols that are overridden by [this] symbol, including self
*/
fun FunctionSymbolMarker.allOverriddenDeclarationsRecursive(): Sequence<CallableSymbolMarker>
fun FunctionSymbolMarker.allRecursivelyOverriddenDeclarationsIncludingSelf(): Sequence<CallableSymbolMarker>
val CallableSymbolMarker.valueParameters: List<ValueParameterSymbolMarker>
get() = (this as? FunctionSymbolMarker)?.valueParameters ?: emptyList()
@@ -134,6 +134,7 @@ interface ExpectActualMatchingContext<T : DeclarationSymbolMarker> : TypeSystemC
val ValueParameterSymbolMarker.isNoinline: Boolean
val ValueParameterSymbolMarker.isCrossinline: Boolean
val ValueParameterSymbolMarker.hasDefaultValue: Boolean
val ValueParameterSymbolMarker.hasDefaultValueNonRecursive: Boolean
fun CallableSymbolMarker.isAnnotationConstructor(): Boolean
@@ -158,6 +159,8 @@ interface ExpectActualMatchingContext<T : DeclarationSymbolMarker> : TypeSystemC
fun CallableSymbolMarker.isFakeOverride(containingExpectClass: RegularClassSymbolMarker?): Boolean
val CallableSymbolMarker.isDelegatedMember: Boolean
val CallableSymbolMarker.hasStableParameterNames: Boolean
fun onMatchedMembers(
@@ -9,4 +9,4 @@ expect class Foo : Shared
// MODULE: m2-jvm()()(m1-common)
// FILE: jvm.kt
actual class Foo : <!DEFAULT_ARGUMENTS_IN_EXPECT_ACTUALIZED_BY_FAKE_OVERRIDE!>Shared<!>
actual class Foo : Shared
@@ -14,4 +14,4 @@ object BaseImpl : Base {
override fun foo(p: Int) {}
}
actual class <!NO_ACTUAL_CLASS_MEMBER_FOR_EXPECTED_CLASS!>Foo<!> : <!DEFAULT_ARGUMENTS_IN_EXPECT_ACTUALIZED_BY_FAKE_OVERRIDE!>Base by BaseImpl<!>
actual class <!NO_ACTUAL_CLASS_MEMBER_FOR_EXPECTED_CLASS!>Foo<!> : Base by BaseImpl
@@ -14,4 +14,4 @@ object BaseImpl : Base {
override fun foo(p: Int) {}
}
actual class <!NO_ACTUAL_CLASS_MEMBER_FOR_EXPECTED_CLASS!>Foo<!> : <!DEFAULT_ARGUMENTS_IN_EXPECT_ACTUALIZED_BY_FAKE_OVERRIDE!>Base by BaseImpl<!>
actual class <!NO_ACTUAL_CLASS_MEMBER_FOR_EXPECTED_CLASS!>Foo<!> : Base by BaseImpl
@@ -0,0 +1,17 @@
// MODULE: m1-common
// FILE: common.kt
expect class Foo {
fun foo(p: Int = 1)
}
// MODULE: m2-jvm()()(m1-common)
// FILE: jvm.kt
interface Base {
fun foo(p: Int)
}
object BaseImpl : Base {
override fun foo(p: Int) {}
}
actual class Foo : <!DEFAULT_ARGUMENTS_IN_EXPECT_ACTUALIZED_BY_FAKE_OVERRIDE!>Base by BaseImpl<!>
@@ -0,0 +1,17 @@
// MODULE: m1-common
// FILE: common.kt
expect class Foo {
fun foo(p: Int = 1)
}
// MODULE: m2-jvm()()(m1-common)
// FILE: jvm.kt
interface Base {
fun foo(p: Int)
}
object BaseImpl : Base {
override fun foo(p: Int) {}
}
actual class Foo : Base by BaseImpl
@@ -51,7 +51,7 @@ public actual open class FastArrayList<E> internal constructor(
var array: Array<Any?>,
var _size: Int = array.size,
var arrayCapacity: Int = array.size,
) : <!DEFAULT_ARGUMENTS_IN_EXPECT_ACTUALIZED_BY_FAKE_OVERRIDE!>AbstractMutableList<E>(), MutableListEx<E>, RandomAccess<!> {
) : AbstractMutableList<E>(), MutableListEx<E>, RandomAccess {
public actual constructor() : this(arrayOfNulls(16), 0) {}
public actual constructor(initialCapacity: Int) : this(arrayOfNulls(initialCapacity), 0) {}
public actual constructor(elements: Collection<E>) : this(elements.toTypedArray<Any?>()) {}
@@ -24882,6 +24882,12 @@ public class DiagnosticTestGenerated extends AbstractDiagnosticTest {
runTest("compiler/testData/diagnostics/tests/multiplatform/defaultArguments/methodDefaultArgsViaActualFakeOverride/delegation.kt");
}
@Test
@TestMetadata("delegation2.kt")
public void testDelegation2() throws Exception {
runTest("compiler/testData/diagnostics/tests/multiplatform/defaultArguments/methodDefaultArgsViaActualFakeOverride/delegation2.kt");
}
@Test
@TestMetadata("disabledFeature.kt")
public void testDisabledFeature() throws Exception {
@@ -69,6 +69,8 @@ sealed class ExpectActualCheckingCompatibility<out D> : ExpectActualCompatibilit
Incompatible<Nothing>("some modifiers on expected declaration are missing on the actual one (infix, inline, operator)")
object ActualFunctionWithDefaultParameters :
Incompatible<Nothing>("actual function cannot have default argument values, they should be declared in the expected function")
object DefaultArgumentsInExpectActualizedByFakeOverride :
Incompatible<Nothing>("default argument values inside expect declaration are not allowed for methods actualized via fake override")
// Properties
object PropertyKind : Incompatible<Nothing>("property kinds are different (val vs var)")