[FIR] 2/2 Cleanup: drop no longer necessary FirActualCallableDeclarationChecker
It became possible to drop it after KT-62590. Now, on a frontend, the return type check is part of a common AbstractExpectActualChecker logic Change in nestedAnnotationClassViaActualTypealias.fir.kt aligns the behaviour with K1. KT-61964 Review: https://jetbrains.team/p/kt/reviews/12750/timeline
This commit is contained in:
-1
@@ -49,7 +49,6 @@ object CommonDeclarationCheckers : DeclarationCheckers() {
|
||||
FirKClassWithIncorrectTypeArgumentChecker,
|
||||
FirImplicitNothingReturnTypeChecker,
|
||||
FirDynamicReceiverChecker,
|
||||
FirActualCallableDeclarationChecker,
|
||||
)
|
||||
|
||||
override val functionCheckers: Set<FirFunctionChecker>
|
||||
|
||||
-69
@@ -1,69 +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.diagnostics.DiagnosticReporter
|
||||
import org.jetbrains.kotlin.diagnostics.reportOn
|
||||
import org.jetbrains.kotlin.fir.analysis.checkers.context.CheckerContext
|
||||
import org.jetbrains.kotlin.fir.analysis.checkers.getContainingClassSymbol
|
||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors
|
||||
import org.jetbrains.kotlin.fir.declarations.FirCallableDeclaration
|
||||
import org.jetbrains.kotlin.fir.declarations.expectForActual
|
||||
import org.jetbrains.kotlin.fir.declarations.getSingleExpectForActualOrNull
|
||||
import org.jetbrains.kotlin.fir.declarations.utils.isActual
|
||||
import org.jetbrains.kotlin.fir.symbols.FirBasedSymbol
|
||||
import org.jetbrains.kotlin.fir.symbols.impl.FirCallableSymbol
|
||||
import org.jetbrains.kotlin.fir.types.areCompatibleExpectActualTypes
|
||||
import org.jetbrains.kotlin.fir.types.createExpectActualTypeParameterSubstitutor
|
||||
import org.jetbrains.kotlin.resolve.multiplatform.ExpectActualCompatibility
|
||||
import org.jetbrains.kotlin.resolve.multiplatform.ExpectActualMatchingCompatibility
|
||||
import org.jetbrains.kotlin.utils.zipIfSizesAreEqual
|
||||
|
||||
object FirActualCallableDeclarationChecker : FirCallableDeclarationChecker() {
|
||||
override fun check(declaration: FirCallableDeclaration, context: CheckerContext, reporter: DiagnosticReporter) {
|
||||
if (!declaration.isActual) return
|
||||
|
||||
checkReturnTypes(declaration, context, reporter)
|
||||
}
|
||||
|
||||
private fun checkReturnTypes(callableDeclaration: FirCallableDeclaration, context: CheckerContext, reporter: DiagnosticReporter) {
|
||||
val actualFunctionSymbol = callableDeclaration.symbol
|
||||
val expectFunctionSymbol = actualFunctionSymbol.getSingleExpectForActualOrNull() as? FirCallableSymbol ?: return
|
||||
|
||||
val expectTypeParameters = expectFunctionSymbol.getContainingClassSymbol(expectFunctionSymbol.moduleData.session)
|
||||
?.typeParameterSymbols.orEmpty()
|
||||
val actualClassTypeParameters = actualFunctionSymbol.getContainingClassSymbol(context.session)?.typeParameterSymbols.orEmpty()
|
||||
|
||||
val parentSubstitutor = createExpectActualTypeParameterSubstitutor(
|
||||
// It's responsibility of AbstractExpectActualCompatibilityChecker to report that
|
||||
(expectTypeParameters zipIfSizesAreEqual actualClassTypeParameters) ?: return,
|
||||
context.session
|
||||
)
|
||||
|
||||
val substitutor = createExpectActualTypeParameterSubstitutor(
|
||||
// It's responsibility of AbstractExpectActualCompatibilityChecker to check that
|
||||
(expectFunctionSymbol.typeParameterSymbols zipIfSizesAreEqual actualFunctionSymbol.typeParameterSymbols) ?: return,
|
||||
context.session,
|
||||
parentSubstitutor
|
||||
)
|
||||
|
||||
if (!areCompatibleExpectActualTypes(
|
||||
substitutor.substituteOrSelf(expectFunctionSymbol.resolvedReturnType.type),
|
||||
actualFunctionSymbol.resolvedReturnType.type,
|
||||
context.session,
|
||||
dynamicTypesEqualToAnything = false
|
||||
)
|
||||
) {
|
||||
reporter.reportOn(
|
||||
callableDeclaration.source,
|
||||
FirErrors.ACTUAL_WITHOUT_EXPECT,
|
||||
actualFunctionSymbol,
|
||||
actualFunctionSymbol.expectForActual as Map<ExpectActualMatchingCompatibility, Collection<FirBasedSymbol<*>>>,
|
||||
context
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -10,7 +10,6 @@ import org.jetbrains.kotlin.fir.resolve.substitution.ConeSubstitutor
|
||||
import org.jetbrains.kotlin.fir.resolve.substitution.ConeSubstitutorByMap
|
||||
import org.jetbrains.kotlin.fir.resolve.substitution.chain
|
||||
import org.jetbrains.kotlin.fir.symbols.impl.FirTypeParameterSymbol
|
||||
import org.jetbrains.kotlin.types.AbstractTypeChecker
|
||||
|
||||
fun createExpectActualTypeParameterSubstitutor(
|
||||
expectActualTypeParameters: List<Pair<FirTypeParameterSymbol, FirTypeParameterSymbol>>,
|
||||
@@ -29,28 +28,3 @@ fun createExpectActualTypeParameterSubstitutor(
|
||||
}
|
||||
return substitutor.chain(parentSubstitutor)
|
||||
}
|
||||
|
||||
// Copy-pasted to org.jetbrains.kotlin.fir.resolve.transformers.mpp.FirExpectActualMatchingContextImpl.areCompatibleExpectActualTypes
|
||||
fun areCompatibleExpectActualTypes(
|
||||
expectedType: ConeKotlinType?,
|
||||
actualType: ConeKotlinType?,
|
||||
actualSession: FirSession,
|
||||
dynamicTypesEqualToAnything: Boolean = true
|
||||
): Boolean {
|
||||
if (expectedType == null) return actualType == null
|
||||
if (actualType == null) return false
|
||||
|
||||
if (!dynamicTypesEqualToAnything) {
|
||||
val isExpectedDynamic = expectedType is ConeDynamicType
|
||||
val isActualDynamic = actualType is ConeDynamicType
|
||||
if (isExpectedDynamic && !isActualDynamic || !isExpectedDynamic && isActualDynamic) {
|
||||
return false
|
||||
}
|
||||
}
|
||||
|
||||
return AbstractTypeChecker.equalTypes(
|
||||
actualSession.typeContext,
|
||||
expectedType,
|
||||
actualType
|
||||
)
|
||||
}
|
||||
-4
@@ -43,9 +43,6 @@ class FirExpectActualMatchingContextImpl private constructor(
|
||||
private val scopeSession: ScopeSession,
|
||||
private val allowedWritingMemberExpectForActualMapping: Boolean,
|
||||
) : FirExpectActualMatchingContext, TypeSystemContext by actualSession.typeContext {
|
||||
override val shouldCheckReturnTypesOfCallables: Boolean
|
||||
get() = false
|
||||
|
||||
override val shouldCheckAbsenceOfDefaultParamsInActual: Boolean
|
||||
get() = true
|
||||
|
||||
@@ -303,7 +300,6 @@ class FirExpectActualMatchingContextImpl private constructor(
|
||||
override val TypeParameterSymbolMarker.isReified: Boolean
|
||||
get() = asSymbol().isReified
|
||||
|
||||
// Copy-pasted to org.jetbrains.kotlin.fir.types.ExpectActualUtilsKt.areCompatibleExpectActualTypes
|
||||
override fun areCompatibleExpectActualTypes(
|
||||
expectType: KotlinTypeMarker?,
|
||||
actualType: KotlinTypeMarker?,
|
||||
|
||||
-3
@@ -92,9 +92,6 @@ internal abstract class IrExpectActualMatchingContext(
|
||||
|
||||
private inline fun <reified T : IrDeclaration> DeclarationSymbolMarker.safeAsIr(): T? = (this as IrSymbol).owner as? T
|
||||
|
||||
override val shouldCheckReturnTypesOfCallables: Boolean
|
||||
get() = true
|
||||
|
||||
override val innerClassesCapturesOuterTypeParameters: Boolean
|
||||
get() = false
|
||||
|
||||
|
||||
+13
-15
@@ -362,22 +362,20 @@ object AbstractExpectActualChecker {
|
||||
val expectedValueParameters = expectDeclaration.valueParameters
|
||||
val actualValueParameters = actualDeclaration.valueParameters
|
||||
|
||||
if (shouldCheckReturnTypesOfCallables) {
|
||||
val substitutor = createExpectActualTypeParameterSubstitutor(
|
||||
(expectedTypeParameters zipIfSizesAreEqual actualTypeParameters)
|
||||
?: error("expect/actual type parameters sizes are checked earlier"),
|
||||
parentSubstitutor
|
||||
)
|
||||
val substitutor = createExpectActualTypeParameterSubstitutor(
|
||||
(expectedTypeParameters zipIfSizesAreEqual actualTypeParameters)
|
||||
?: error("expect/actual type parameters sizes are checked earlier"),
|
||||
parentSubstitutor
|
||||
)
|
||||
|
||||
if (!areCompatibleExpectActualTypes(
|
||||
substitutor.safeSubstitute(expectDeclaration.returnType),
|
||||
actualDeclaration.returnType,
|
||||
parameterOfAnnotationComparisonMode = insideAnnotationClass,
|
||||
dynamicTypesEqualToAnything = false
|
||||
)
|
||||
) {
|
||||
return ExpectActualCheckingCompatibility.ReturnType
|
||||
}
|
||||
if (!areCompatibleExpectActualTypes(
|
||||
substitutor.safeSubstitute(expectDeclaration.returnType),
|
||||
actualDeclaration.returnType,
|
||||
parameterOfAnnotationComparisonMode = insideAnnotationClass,
|
||||
dynamicTypesEqualToAnything = false
|
||||
)
|
||||
) {
|
||||
return ExpectActualCheckingCompatibility.ReturnType
|
||||
}
|
||||
|
||||
if (actualDeclaration.hasStableParameterNames && !equalsBy(expectedValueParameters, actualValueParameters) { it.name }) {
|
||||
|
||||
-2
@@ -20,8 +20,6 @@ import org.jetbrains.kotlin.types.model.TypeSubstitutorMarker
|
||||
import org.jetbrains.kotlin.types.model.TypeSystemContext
|
||||
|
||||
interface ExpectActualMatchingContext<T : DeclarationSymbolMarker> : TypeSystemContext {
|
||||
val shouldCheckReturnTypesOfCallables: Boolean
|
||||
|
||||
/*
|
||||
* This flag indicates how are type parameters of inner classes stored in the specific implementation of RegularClassSymbolMarker
|
||||
*
|
||||
|
||||
+1
-1
@@ -11,4 +11,4 @@ class DefaultArgsInNestedClassImpl {
|
||||
}
|
||||
|
||||
// Incompatible because of bug KT-31636
|
||||
actual typealias DefaultArgsInNestedClass = DefaultArgsInNestedClassImpl
|
||||
actual typealias <!NO_ACTUAL_CLASS_MEMBER_FOR_EXPECTED_CLASS!>DefaultArgsInNestedClass<!> = DefaultArgsInNestedClassImpl
|
||||
|
||||
@@ -34,7 +34,7 @@ interface KotlinXStringDemoInterface {
|
||||
// FILE: StringDemoInterface.kt
|
||||
actual typealias StringDemoInterface = KotlinXStringDemoInterface
|
||||
|
||||
actual fun StringDemoIn<!EXPECT_ACTUAL_INCOMPATIBILITY!>terface.<!ACTUAL_WITHOUT_EXPECT("actual fun StringDemoInterface.plusK(): <ERROR TYPE REF: Unresolved name: value>; The following declaration is incompatible: expect fun StringDemoInterface.plusK(): String")!>plusK<!>() = <!EXPECT_CLASS_AS_FUNCTION!>StringValue<!>(value).plus("K")<!>.<!UNRESOLVED_REFERENCE!>value<!>
|
||||
actual fun StringDemoIn<!EXPECT_ACTUAL_INCOMPATIBILITY!>terface.<!ACTUAL_WITHOUT_EXPECT("actual fun StringDemoInterface.plusK(): <ERROR TYPE REF: Unresolved name: value>; The following declaration is incompatible because return type is different: expect fun StringDemoInterface.plusK(): String")!>plusK<!>() = <!EXPECT_CLASS_AS_FUNCTION!>StringValue<!>(value).plus("K")<!>.<!UNRESOLVED_REFERENCE!>value<!>
|
||||
|
||||
// FILE: main.kt
|
||||
class StringDemo(override val value: String) : StringDemoInterface
|
||||
|
||||
+1
-1
@@ -6,7 +6,7 @@ Output:
|
||||
Exit code: COMPILATION_ERROR
|
||||
Output:
|
||||
compiler/testData/multiplatform/classScopes/functionIncorrectSignature/jvm.kt:2:16: error: 'actual fun function(b: ByteArray): Long' has no corresponding expected declaration
|
||||
The following declaration is incompatible:
|
||||
The following declaration is incompatible because return type is different:
|
||||
expect fun function(b: ByteArray): Int
|
||||
|
||||
actual fun function(b: ByteArray): Long = b.size.toLong()
|
||||
|
||||
Vendored
+9
-6
@@ -5,9 +5,12 @@ Output:
|
||||
-- JVM --
|
||||
Exit code: COMPILATION_ERROR
|
||||
Output:
|
||||
compiler/testData/multiplatform/classScopes/functionIncorrectSignatureFromSuperclass/common.kt:1:1: error: expect declaration `Foo` doesn't match actual `Foo` because some expected members have no actual ones
|
||||
expect class Foo {
|
||||
^
|
||||
compiler/testData/multiplatform/classScopes/functionIncorrectSignatureFromSuperclass/common.kt:2:5: error: expect declaration `function` doesn't match actual `function` because return type is different
|
||||
fun function(b: ByteArray): Int
|
||||
^
|
||||
compiler/testData/multiplatform/classScopes/functionIncorrectSignatureFromSuperclass/jvm.kt:5:14: error: 'actual class Foo : Base' has no corresponding members for expected class members:
|
||||
|
||||
expect fun function(b: ByteArray): Int
|
||||
|
||||
The following declaration is incompatible because return type is different:
|
||||
fun function(b: ByteArray): Long
|
||||
|
||||
actual class Foo : Base()
|
||||
^
|
||||
|
||||
@@ -6,7 +6,7 @@ Output:
|
||||
Exit code: COMPILATION_ERROR
|
||||
Output:
|
||||
compiler/testData/multiplatform/incompatibleCallables/jvm.kt:1:12: error: 'actual fun f1(): String' has no corresponding expected declaration
|
||||
The following declaration is incompatible:
|
||||
The following declaration is incompatible because return type is different:
|
||||
expect fun f1(): Unit
|
||||
|
||||
actual fun f1(): String = ""
|
||||
|
||||
Reference in New Issue
Block a user