Introduce Unit-conversions for simple arguments
This commit is contained in:
+83
@@ -0,0 +1,83 @@
|
||||
/*
|
||||
* Copyright 2010-2020 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.resolve.calls.components
|
||||
|
||||
import org.jetbrains.kotlin.builtins.*
|
||||
import org.jetbrains.kotlin.descriptors.ParameterDescriptor
|
||||
import org.jetbrains.kotlin.resolve.calls.inference.model.LowerPriorityToPreserveCompatibility
|
||||
import org.jetbrains.kotlin.resolve.calls.model.KotlinCallArgument
|
||||
import org.jetbrains.kotlin.resolve.calls.model.KotlinResolutionCandidate
|
||||
import org.jetbrains.kotlin.resolve.calls.model.SimpleKotlinCallArgument
|
||||
import org.jetbrains.kotlin.types.KotlinType
|
||||
import org.jetbrains.kotlin.types.UnwrappedType
|
||||
import org.jetbrains.kotlin.types.isDynamic
|
||||
import org.jetbrains.kotlin.types.typeUtil.isUnit
|
||||
|
||||
object UnitTypeConversions : ParameterTypeConversion {
|
||||
override fun conversionDefinitelyNotNeeded(
|
||||
candidate: KotlinResolutionCandidate,
|
||||
argument: KotlinCallArgument,
|
||||
expectedParameterType: UnwrappedType
|
||||
): Boolean {
|
||||
// for callable references and lambdas it already works
|
||||
if (argument !is SimpleKotlinCallArgument) return true
|
||||
|
||||
val receiver = argument.receiver
|
||||
if (receiver.receiverValue.type.hasUnitOrDynamicReturnType()) return true
|
||||
if (receiver.typesFromSmartCasts.any { it.hasUnitOrDynamicReturnType() }) return true
|
||||
|
||||
if (
|
||||
!expectedParameterType.isBuiltinFunctionalType ||
|
||||
!expectedParameterType.getReturnTypeFromFunctionType().isUnit()
|
||||
) return true
|
||||
|
||||
return false
|
||||
}
|
||||
|
||||
private fun KotlinType.hasUnitOrDynamicReturnType(): Boolean =
|
||||
isFunctionOrKFunctionTypeWithAnySuspendability && arguments.last().type.isUnitOrDynamic()
|
||||
|
||||
private fun KotlinType.isUnitOrDynamic(): Boolean = isUnit() || isDynamic()
|
||||
|
||||
override fun conversionIsNeededBeforeSubtypingCheck(argument: KotlinCallArgument): Boolean =
|
||||
argument is SimpleKotlinCallArgument && argument.receiver.stableType.isFunctionType
|
||||
|
||||
override fun conversionIsNeededAfterSubtypingCheck(argument: KotlinCallArgument): Boolean {
|
||||
if (argument !is SimpleKotlinCallArgument) return false
|
||||
|
||||
var isFunctionTypeOrSubtype = false
|
||||
val hasReturnTypeInSubtypes = argument.receiver.stableType.isFunctionTypeOrSubtype {
|
||||
isFunctionTypeOrSubtype = true
|
||||
it.getReturnTypeFromFunctionType().isUnitOrDynamic()
|
||||
}
|
||||
|
||||
if (!isFunctionTypeOrSubtype) return false
|
||||
|
||||
return !hasReturnTypeInSubtypes
|
||||
}
|
||||
|
||||
override fun convertParameterType(
|
||||
candidate: KotlinResolutionCandidate,
|
||||
argument: KotlinCallArgument,
|
||||
parameter: ParameterDescriptor,
|
||||
expectedParameterType: UnwrappedType
|
||||
): UnwrappedType? {
|
||||
val nonUnitReturnedParameterType = createFunctionType(
|
||||
candidate.callComponents.builtIns,
|
||||
expectedParameterType.annotations,
|
||||
expectedParameterType.getReceiverTypeFromFunctionType(),
|
||||
expectedParameterType.getValueParameterTypesFromFunctionType().map { it.type },
|
||||
parameterNames = null,
|
||||
candidate.callComponents.builtIns.nullableAnyType,
|
||||
suspendFunction = expectedParameterType.isSuspendFunctionType
|
||||
)
|
||||
|
||||
candidate.addDiagnostic(LowerPriorityToPreserveCompatibility)
|
||||
|
||||
return nonUnitReturnedParameterType
|
||||
}
|
||||
|
||||
}
|
||||
+18
-6
@@ -40,14 +40,23 @@ object TypeConversions {
|
||||
)
|
||||
|
||||
val suspendConversionData = performConversionBeforeSubtyping(
|
||||
candidate, argument, candidateParameter, samConversionData.convertedType ?: candidateExpectedType, SuspendTypeConversions
|
||||
candidate, argument, candidateParameter,
|
||||
candidateExpectedType = samConversionData.convertedType ?: candidateExpectedType,
|
||||
SuspendTypeConversions
|
||||
)
|
||||
|
||||
val unitConversionData = performConversionBeforeSubtyping(
|
||||
candidate, argument, candidateParameter,
|
||||
candidateExpectedType = suspendConversionData.convertedType ?: samConversionData.convertedType ?: candidateExpectedType,
|
||||
UnitTypeConversions
|
||||
)
|
||||
|
||||
return ConversionData(
|
||||
convertedType = suspendConversionData.convertedType ?: samConversionData.convertedType,
|
||||
wasConversion = samConversionData.wasConversion || suspendConversionData.wasConversion,
|
||||
convertedType = unitConversionData.convertedType ?: suspendConversionData.convertedType ?: samConversionData.convertedType,
|
||||
wasConversion = samConversionData.wasConversion || suspendConversionData.wasConversion || unitConversionData.wasConversion,
|
||||
conversionDefinitelyNotNeeded = samConversionData.conversionDefinitelyNotNeeded &&
|
||||
suspendConversionData.conversionDefinitelyNotNeeded
|
||||
suspendConversionData.conversionDefinitelyNotNeeded &&
|
||||
unitConversionData.conversionDefinitelyNotNeeded
|
||||
)
|
||||
}
|
||||
|
||||
@@ -60,10 +69,13 @@ object TypeConversions {
|
||||
val samConvertedType = performConversionAfterSubtyping(
|
||||
candidate, argument, candidateParameter, candidateExpectedType, SamTypeConversions
|
||||
)
|
||||
|
||||
if (samConvertedType != null) return samConvertedType
|
||||
|
||||
return performConversionAfterSubtyping(candidate, argument, candidateParameter, candidateExpectedType, SuspendTypeConversions)
|
||||
val suspendConvertedType =
|
||||
performConversionAfterSubtyping(candidate, argument, candidateParameter, candidateExpectedType, SuspendTypeConversions)
|
||||
if (suspendConvertedType != null) return suspendConvertedType
|
||||
|
||||
return performConversionAfterSubtyping(candidate, argument, candidateParameter, candidateExpectedType, UnitTypeConversions)
|
||||
}
|
||||
|
||||
private fun performConversionAfterSubtyping(
|
||||
|
||||
Reference in New Issue
Block a user