Use non-allowed actual defaults in backends to workaround compiler exception
It's difficult to fix KT-22818 until the IR comes along, so we're providing a workaround where one can disable the ACTUAL_FUNCTION_WITH_DEFAULT_ARGUMENTS error and provide default values in the actual function, to avoid exception from the backend. #KT-22818
This commit is contained in:
@@ -23,6 +23,7 @@ import org.jetbrains.kotlin.resolve.calls.callUtil.getResolvedCall
|
||||
import org.jetbrains.kotlin.resolve.checkers.ExpectedActualDeclarationChecker
|
||||
import org.jetbrains.kotlin.resolve.multiplatform.ExpectedActualResolver
|
||||
import org.jetbrains.kotlin.types.KotlinType
|
||||
import org.jetbrains.kotlin.utils.DFS
|
||||
|
||||
object CodegenUtil {
|
||||
@JvmStatic
|
||||
@@ -200,16 +201,25 @@ object CodegenUtil {
|
||||
trace: DiagnosticSink?
|
||||
): List<ValueParameterDescriptor> {
|
||||
if (descriptor.isActual) {
|
||||
val actualParameters = descriptor.valueParameters
|
||||
if (actualParameters.any { it.declaresOrInheritsDefaultValue() }) {
|
||||
// This is incorrect code: actual function cannot have default values, they should be declared in the expected function.
|
||||
// But until KT-22818 is fixed, we need to provide a workaround for the exception that happens on complex default values
|
||||
// in the expected function. One may suppress the error then, and declare default values _both_ in expect and actual.
|
||||
// With this code, we'll generate actual default values if they're present, and expected default values otherwise.
|
||||
return actualParameters
|
||||
}
|
||||
|
||||
val expected = CodegenUtil.findExpectedFunctionForActual(descriptor)
|
||||
if (expected != null && expected.valueParameters.any(ValueParameterDescriptor::declaresDefaultValue)) {
|
||||
val element = DescriptorToSourceUtils.descriptorToDeclaration(expected)
|
||||
if (element == null) {
|
||||
if (trace != null) {
|
||||
val actualDeclaration = DescriptorToSourceUtils.descriptorToDeclaration(descriptor)
|
||||
?: error("Not a source declaration: $descriptor")
|
||||
?: error("Not a source declaration: $descriptor")
|
||||
trace.report(Errors.EXPECTED_FUNCTION_SOURCE_WITH_DEFAULT_ARGUMENTS_NOT_FOUND.on(actualDeclaration))
|
||||
}
|
||||
return descriptor.valueParameters
|
||||
return actualParameters
|
||||
}
|
||||
|
||||
return expected.valueParameters
|
||||
@@ -218,6 +228,16 @@ object CodegenUtil {
|
||||
|
||||
return descriptor.valueParameters
|
||||
}
|
||||
|
||||
// This function is private here because no one is supposed to use it except for the hack above.
|
||||
// Please use ValueParameterDescriptor.hasDefaultValue instead.
|
||||
private fun ValueParameterDescriptor.declaresOrInheritsDefaultValue(): Boolean {
|
||||
return DFS.ifAny(
|
||||
listOf(this),
|
||||
{ current -> current.overriddenDescriptors.map(ValueParameterDescriptor::getOriginal) },
|
||||
{ it.declaresDefaultValue() }
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
fun DeclarationDescriptor.isTopLevelInPackage(name: String, packageName: String): Boolean {
|
||||
@@ -226,4 +246,4 @@ fun DeclarationDescriptor.isTopLevelInPackage(name: String, packageName: String)
|
||||
val containingDeclaration = containingDeclaration as? PackageFragmentDescriptor ?: return false
|
||||
val packageFqName = containingDeclaration.fqName.asString()
|
||||
return packageName == packageFqName
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user