[FIR] Support of ACTUAL_FUNCTION_WITH_DEFAULT_ARGUMENTS diagnostic
^KT-56522 Fixed
This commit is contained in:
committed by
Space Team
parent
f1fef62f76
commit
c418a7a7bf
+45
-30
@@ -22,38 +22,53 @@ object FirActualDeclarationChecker : FirBasicDeclarationChecker() {
|
|||||||
if (declaration !is FirMemberDeclaration || !declaration.isActual) return
|
if (declaration !is FirMemberDeclaration || !declaration.isActual) return
|
||||||
|
|
||||||
if (declaration is FirCallableDeclaration) {
|
if (declaration is FirCallableDeclaration) {
|
||||||
val actualFunctionSymbol = declaration.symbol
|
if (declaration is FirFunction) {
|
||||||
val expectFunctionSymbol = actualFunctionSymbol.getSingleCompatibleExpectForActualOrNull() as? FirCallableSymbol ?: return
|
checkActualFunctionWithDefaultArguments(declaration, reporter, context)
|
||||||
|
}
|
||||||
|
checkReturnTypes(declaration, context, reporter)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
val expectTypeParameters = expectFunctionSymbol.getContainingClassSymbol(expectFunctionSymbol.moduleData.session)
|
private fun checkActualFunctionWithDefaultArguments(function: FirFunction, reporter: DiagnosticReporter, context: CheckerContext) {
|
||||||
?.typeParameterSymbols.orEmpty()
|
for (valueParameter in function.valueParameters) {
|
||||||
val actualClassTypeParameters = actualFunctionSymbol.getContainingClassSymbol(context.session)?.typeParameterSymbols.orEmpty()
|
if (valueParameter.defaultValue != null) {
|
||||||
val parentSubstitutor =
|
reporter.reportOn(valueParameter.source, FirErrors.ACTUAL_FUNCTION_WITH_DEFAULT_ARGUMENTS, context)
|
||||||
createExpectActualTypeParameterSubstitutor(expectTypeParameters, actualClassTypeParameters, context.session)
|
|
||||||
|
|
||||||
val substitutor = createExpectActualTypeParameterSubstitutor(
|
|
||||||
expectFunctionSymbol.typeParameterSymbols,
|
|
||||||
actualFunctionSymbol.typeParameterSymbols,
|
|
||||||
context.session,
|
|
||||||
parentSubstitutor
|
|
||||||
)
|
|
||||||
|
|
||||||
if (!areCompatibleExpectActualTypes(
|
|
||||||
substitutor.substituteOrSelf(expectFunctionSymbol.resolvedReturnType.type),
|
|
||||||
actualFunctionSymbol.resolvedReturnType.type,
|
|
||||||
expectFunctionSymbol.moduleData.session,
|
|
||||||
context.session
|
|
||||||
)
|
|
||||||
) {
|
|
||||||
@Suppress("UNCHECKED_CAST")
|
|
||||||
reporter.reportOn(
|
|
||||||
declaration.source,
|
|
||||||
FirErrors.ACTUAL_WITHOUT_EXPECT,
|
|
||||||
actualFunctionSymbol,
|
|
||||||
actualFunctionSymbol.expectForActual as Map<ExpectActualCompatibility.Incompatible<FirBasedSymbol<*>>, Collection<FirBasedSymbol<*>>>,
|
|
||||||
context
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private fun checkReturnTypes(callableDeclaration: FirCallableDeclaration, context: CheckerContext, reporter: DiagnosticReporter) {
|
||||||
|
val actualFunctionSymbol = callableDeclaration.symbol
|
||||||
|
val expectFunctionSymbol = actualFunctionSymbol.getSingleCompatibleExpectForActualOrNull() as? FirCallableSymbol ?: return
|
||||||
|
|
||||||
|
val expectTypeParameters = expectFunctionSymbol.getContainingClassSymbol(expectFunctionSymbol.moduleData.session)
|
||||||
|
?.typeParameterSymbols.orEmpty()
|
||||||
|
val actualClassTypeParameters = actualFunctionSymbol.getContainingClassSymbol(context.session)?.typeParameterSymbols.orEmpty()
|
||||||
|
val parentSubstitutor =
|
||||||
|
createExpectActualTypeParameterSubstitutor(expectTypeParameters, actualClassTypeParameters, context.session)
|
||||||
|
|
||||||
|
val substitutor = createExpectActualTypeParameterSubstitutor(
|
||||||
|
expectFunctionSymbol.typeParameterSymbols,
|
||||||
|
actualFunctionSymbol.typeParameterSymbols,
|
||||||
|
context.session,
|
||||||
|
parentSubstitutor
|
||||||
|
)
|
||||||
|
|
||||||
|
if (!areCompatibleExpectActualTypes(
|
||||||
|
substitutor.substituteOrSelf(expectFunctionSymbol.resolvedReturnType.type),
|
||||||
|
actualFunctionSymbol.resolvedReturnType.type,
|
||||||
|
expectFunctionSymbol.moduleData.session,
|
||||||
|
context.session
|
||||||
|
)
|
||||||
|
) {
|
||||||
|
@Suppress("UNCHECKED_CAST")
|
||||||
|
reporter.reportOn(
|
||||||
|
callableDeclaration.source,
|
||||||
|
FirErrors.ACTUAL_WITHOUT_EXPECT,
|
||||||
|
actualFunctionSymbol,
|
||||||
|
actualFunctionSymbol.expectForActual as Map<ExpectActualCompatibility.Incompatible<FirBasedSymbol<*>>, Collection<FirBasedSymbol<*>>>,
|
||||||
|
context
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
-22
@@ -1,22 +0,0 @@
|
|||||||
// MODULE: m1-common
|
|
||||||
// FILE: common.kt
|
|
||||||
|
|
||||||
expect class Ok(x: Int, y: String = "")
|
|
||||||
|
|
||||||
expect class FailX(x: Int, y: String = "")
|
|
||||||
|
|
||||||
expect class FailY(x: Int, y: String = "")
|
|
||||||
|
|
||||||
fun test() {
|
|
||||||
Ok(42)
|
|
||||||
Ok(42, "OK")
|
|
||||||
}
|
|
||||||
|
|
||||||
// MODULE: m2-jvm()()(m1-common)
|
|
||||||
// FILE: jvm.kt
|
|
||||||
|
|
||||||
actual class Ok actual constructor(x: Int, y: String)
|
|
||||||
|
|
||||||
actual class FailX actual constructor(x: Int = 0, y: String)
|
|
||||||
|
|
||||||
actual class FailY actual constructor(x: Int, y: String = "")
|
|
||||||
+1
@@ -1,3 +1,4 @@
|
|||||||
|
// FIR_IDENTICAL
|
||||||
// MODULE: m1-common
|
// MODULE: m1-common
|
||||||
// FILE: common.kt
|
// FILE: common.kt
|
||||||
|
|
||||||
|
|||||||
-40
@@ -1,40 +0,0 @@
|
|||||||
// MODULE: m1-common
|
|
||||||
// FILE: common.kt
|
|
||||||
|
|
||||||
expect fun ok(x: Int, y: String = "")
|
|
||||||
|
|
||||||
expect fun failX(x: Int, y: String = "")
|
|
||||||
|
|
||||||
expect fun failY(x: Int, y: String = "")
|
|
||||||
|
|
||||||
expect open class Foo {
|
|
||||||
fun ok(x: Int, y: String = "")
|
|
||||||
|
|
||||||
fun failX(x: Int, y: String = "")
|
|
||||||
|
|
||||||
fun failY(x: Int, y: String = "")
|
|
||||||
}
|
|
||||||
|
|
||||||
fun test(foo: Foo) {
|
|
||||||
ok(42)
|
|
||||||
ok(42, "OK")
|
|
||||||
foo.ok(42)
|
|
||||||
foo.ok(42, "OK")
|
|
||||||
}
|
|
||||||
|
|
||||||
// MODULE: m2-jvm()()(m1-common)
|
|
||||||
// FILE: jvm.kt
|
|
||||||
|
|
||||||
actual fun ok(x: Int, y: String) {}
|
|
||||||
|
|
||||||
actual fun failX(x: Int = 0, y: String) {}
|
|
||||||
|
|
||||||
actual fun failY(x: Int, y: String = "") {}
|
|
||||||
|
|
||||||
actual open class Foo {
|
|
||||||
actual fun ok(x: Int, y: String) {}
|
|
||||||
|
|
||||||
actual fun failX(x: Int = 0, y: String) {}
|
|
||||||
|
|
||||||
actual fun failY(x: Int, y: String = "") {}
|
|
||||||
}
|
|
||||||
+1
@@ -1,3 +1,4 @@
|
|||||||
|
// FIR_IDENTICAL
|
||||||
// MODULE: m1-common
|
// MODULE: m1-common
|
||||||
// FILE: common.kt
|
// FILE: common.kt
|
||||||
|
|
||||||
|
|||||||
+2
-2
@@ -30,7 +30,7 @@ fun test(foo: Foo, bar: Bar) {
|
|||||||
actual class Bar : Foo {
|
actual class Bar : Foo {
|
||||||
actual override fun ok(x: Int, y: String) {}
|
actual override fun ok(x: Int, y: String) {}
|
||||||
|
|
||||||
actual override fun failX(x: Int = 0, y: String) {}
|
actual override fun failX(<!ACTUAL_FUNCTION_WITH_DEFAULT_ARGUMENTS!>x: Int = 0<!>, y: String) {}
|
||||||
|
|
||||||
actual override fun failY(x: Int, y: String = "") {}
|
actual override fun failY(x: Int, <!ACTUAL_FUNCTION_WITH_DEFAULT_ARGUMENTS!>y: String = ""<!>) {}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user