[NI] Support signed-unsigned conversions for K/Native
#KT-34545 Fixed
This commit is contained in:
+3
@@ -19,6 +19,7 @@ import org.jetbrains.kotlin.resolve.calls.inference.model.NewTypeVariable
|
||||
import org.jetbrains.kotlin.resolve.calls.model.*
|
||||
import org.jetbrains.kotlin.resolve.calls.results.SimpleConstraintSystem
|
||||
import org.jetbrains.kotlin.resolve.calls.tower.ImplicitScopeTower
|
||||
import org.jetbrains.kotlin.resolve.constants.IntegerValueTypeConstant
|
||||
import org.jetbrains.kotlin.types.KotlinType
|
||||
import org.jetbrains.kotlin.types.StubType
|
||||
import org.jetbrains.kotlin.types.UnwrappedType
|
||||
@@ -75,4 +76,6 @@ interface KotlinResolutionCallbacks {
|
||||
fun getExpectedTypeFromAsExpressionAndRecordItInTrace(resolvedAtom: ResolvedCallAtom): UnwrappedType?
|
||||
|
||||
fun disableContractsIfNecessary(resolvedAtom: ResolvedCallAtom)
|
||||
|
||||
fun convertSignedConstantToUnsigned(argument: KotlinCallArgument): IntegerValueTypeConstant?
|
||||
}
|
||||
|
||||
+3
-2
@@ -35,10 +35,11 @@ fun resolveKtPrimitive(
|
||||
argument: KotlinCallArgument,
|
||||
expectedType: UnwrappedType?,
|
||||
diagnosticsHolder: KotlinDiagnosticsHolder,
|
||||
isReceiver: Boolean
|
||||
isReceiver: Boolean,
|
||||
convertedType: UnwrappedType?
|
||||
): ResolvedAtom = when (argument) {
|
||||
is SimpleKotlinCallArgument ->
|
||||
checkSimpleArgument(csBuilder, argument, expectedType, diagnosticsHolder, isReceiver)
|
||||
checkSimpleArgument(csBuilder, argument, expectedType, diagnosticsHolder, isReceiver, convertedType)
|
||||
|
||||
is LambdaKotlinCallArgument ->
|
||||
preprocessLambdaArgument(csBuilder, argument, expectedType, diagnosticsHolder)
|
||||
|
||||
+1
-1
@@ -132,7 +132,7 @@ class PostponedArgumentsAnalyzer(
|
||||
|
||||
val subResolvedKtPrimitives = returnArgumentsInfo.nonErrorArguments.map {
|
||||
resolveKtPrimitive(
|
||||
c.getBuilder(), it, lambda.returnType.let(::substitute), diagnosticHolder, isReceiver = false
|
||||
c.getBuilder(), it, lambda.returnType.let(::substitute), diagnosticHolder, isReceiver = false, convertedType = null
|
||||
)
|
||||
}
|
||||
|
||||
|
||||
+36
-1
@@ -5,6 +5,7 @@
|
||||
|
||||
package org.jetbrains.kotlin.resolve.calls.components
|
||||
|
||||
import org.jetbrains.kotlin.builtins.UnsignedTypes
|
||||
import org.jetbrains.kotlin.builtins.getReceiverTypeFromFunctionType
|
||||
import org.jetbrains.kotlin.builtins.isFunctionType
|
||||
import org.jetbrains.kotlin.config.LanguageFeature
|
||||
@@ -26,6 +27,7 @@ import org.jetbrains.kotlin.types.*
|
||||
import org.jetbrains.kotlin.types.typeUtil.contains
|
||||
import org.jetbrains.kotlin.types.typeUtil.makeNotNullable
|
||||
import org.jetbrains.kotlin.types.typeUtil.makeNullable
|
||||
import org.jetbrains.kotlin.utils.addToStdlib.cast
|
||||
import org.jetbrains.kotlin.utils.addToStdlib.safeAs
|
||||
|
||||
internal object CheckInstantiationOfAbstractClass : ResolutionPart() {
|
||||
@@ -288,7 +290,40 @@ private fun KotlinResolutionCandidate.resolveKotlinArgument(
|
||||
isReceiver: Boolean
|
||||
) {
|
||||
val expectedType = candidateParameter?.let { prepareExpectedType(argument, candidateParameter) }
|
||||
addResolvedKtPrimitive(resolveKtPrimitive(csBuilder, argument, expectedType, this, isReceiver))
|
||||
val convertedArgument = if (expectedType != null && shouldRunConversionForConstants(expectedType)) {
|
||||
val convertedConstant = resolutionCallbacks.convertSignedConstantToUnsigned(argument)
|
||||
if (convertedConstant != null) {
|
||||
resolvedCall.registerArgumentWithConstantConversion(argument, convertedConstant)
|
||||
}
|
||||
|
||||
convertedConstant
|
||||
} else null
|
||||
|
||||
addResolvedKtPrimitive(
|
||||
resolveKtPrimitive(
|
||||
csBuilder,
|
||||
argument,
|
||||
expectedType,
|
||||
this,
|
||||
isReceiver,
|
||||
convertedArgument?.unknownIntegerType?.unwrap()
|
||||
)
|
||||
)
|
||||
}
|
||||
|
||||
private fun KotlinResolutionCandidate.shouldRunConversionForConstants(expectedType: UnwrappedType): Boolean {
|
||||
if (UnsignedTypes.isUnsignedType(expectedType)) return true
|
||||
if (csBuilder.isTypeVariable(expectedType)) {
|
||||
val variableWithConstraints = csBuilder.currentStorage().notFixedTypeVariables[expectedType.constructor] ?: return false
|
||||
return variableWithConstraints.constraints.any {
|
||||
it.kind == ConstraintKind.EQUALITY &&
|
||||
it.position.from is ExplicitTypeParameterConstraintPosition &&
|
||||
UnsignedTypes.isUnsignedType(it.type as UnwrappedType)
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
return false
|
||||
}
|
||||
|
||||
private fun KotlinResolutionCandidate.prepareExpectedType(
|
||||
|
||||
+6
-4
@@ -37,9 +37,10 @@ fun checkSimpleArgument(
|
||||
argument: SimpleKotlinCallArgument,
|
||||
expectedType: UnwrappedType?,
|
||||
diagnosticsHolder: KotlinDiagnosticsHolder,
|
||||
isReceiver: Boolean
|
||||
isReceiver: Boolean,
|
||||
convertedType: UnwrappedType?
|
||||
): ResolvedAtom = when (argument) {
|
||||
is ExpressionKotlinCallArgument -> checkExpressionArgument(csBuilder, argument, expectedType, diagnosticsHolder, isReceiver)
|
||||
is ExpressionKotlinCallArgument -> checkExpressionArgument(csBuilder, argument, expectedType, diagnosticsHolder, isReceiver, convertedType)
|
||||
is SubKotlinCallArgument -> checkSubCallArgument(csBuilder, argument, expectedType, diagnosticsHolder, isReceiver)
|
||||
else -> unexpectedArgument(argument)
|
||||
}
|
||||
@@ -49,13 +50,14 @@ private fun checkExpressionArgument(
|
||||
expressionArgument: ExpressionKotlinCallArgument,
|
||||
expectedType: UnwrappedType?,
|
||||
diagnosticsHolder: KotlinDiagnosticsHolder,
|
||||
isReceiver: Boolean
|
||||
isReceiver: Boolean,
|
||||
convertedType: UnwrappedType?
|
||||
): ResolvedAtom {
|
||||
val resolvedExpression = ResolvedExpressionAtom(expressionArgument)
|
||||
if (expectedType == null) return resolvedExpression
|
||||
|
||||
// todo run this approximation only once for call
|
||||
val argumentType = captureFromTypeParameterUpperBoundIfNeeded(expressionArgument.receiver.stableType, expectedType)
|
||||
val argumentType = convertedType ?: captureFromTypeParameterUpperBoundIfNeeded(expressionArgument.receiver.stableType, expectedType)
|
||||
|
||||
fun unstableSmartCastOrSubtypeError(
|
||||
unstableType: UnwrappedType?, actualExpectedType: UnwrappedType, position: ConstraintPosition
|
||||
|
||||
+2
-1
@@ -144,6 +144,7 @@ class SimpleCandidateFactory(
|
||||
if (ErrorUtils.isError(descriptor)) {
|
||||
return KotlinResolutionCandidate(
|
||||
callComponents,
|
||||
resolutionCallbacks,
|
||||
callableReferenceResolver,
|
||||
scopeTower,
|
||||
baseSystem,
|
||||
@@ -154,7 +155,7 @@ class SimpleCandidateFactory(
|
||||
}
|
||||
|
||||
val candidate = KotlinResolutionCandidate(
|
||||
callComponents, callableReferenceResolver, scopeTower, baseSystem, resolvedKtCall, knownSubstitutor
|
||||
callComponents, resolutionCallbacks, callableReferenceResolver, scopeTower, baseSystem, resolvedKtCall, knownSubstitutor
|
||||
)
|
||||
|
||||
initialDiagnostics.forEach(candidate::addDiagnostic)
|
||||
|
||||
@@ -18,6 +18,7 @@ import org.jetbrains.kotlin.resolve.calls.inference.model.NewConstraintError
|
||||
import org.jetbrains.kotlin.resolve.calls.inference.model.TypeVariableForCallableReferenceReturnType
|
||||
import org.jetbrains.kotlin.resolve.calls.inference.model.TypeVariableForLambdaReturnType
|
||||
import org.jetbrains.kotlin.resolve.calls.tasks.ExplicitReceiverKind
|
||||
import org.jetbrains.kotlin.resolve.constants.IntegerValueTypeConstant
|
||||
import org.jetbrains.kotlin.types.KotlinType
|
||||
import org.jetbrains.kotlin.types.TypeConstructor
|
||||
import org.jetbrains.kotlin.types.TypeSubstitutor
|
||||
@@ -70,6 +71,7 @@ abstract class ResolvedCallAtom : ResolvedAtom() {
|
||||
abstract val freshVariablesSubstitutor: FreshVariableNewTypeSubstitutor
|
||||
abstract val knownParametersSubstitutor: TypeSubstitutor
|
||||
abstract val argumentsWithConversion: Map<KotlinCallArgument, SamConversionDescription>
|
||||
abstract val argumentsWithConstantConversion: Map<KotlinCallArgument, IntegerValueTypeConstant>
|
||||
}
|
||||
|
||||
class SamConversionDescription(
|
||||
|
||||
+15
@@ -20,6 +20,7 @@ import org.jetbrains.kotlin.descriptors.CallableDescriptor
|
||||
import org.jetbrains.kotlin.descriptors.ValueParameterDescriptor
|
||||
import org.jetbrains.kotlin.renderer.DescriptorRenderer
|
||||
import org.jetbrains.kotlin.resolve.calls.components.CallableReferenceResolver
|
||||
import org.jetbrains.kotlin.resolve.calls.components.KotlinResolutionCallbacks
|
||||
import org.jetbrains.kotlin.resolve.calls.components.NewConstraintSystemImpl
|
||||
import org.jetbrains.kotlin.resolve.calls.components.TypeArgumentsToParametersMapper
|
||||
import org.jetbrains.kotlin.resolve.calls.inference.NewConstraintSystem
|
||||
@@ -28,6 +29,7 @@ import org.jetbrains.kotlin.resolve.calls.inference.model.ConstraintStorage
|
||||
import org.jetbrains.kotlin.resolve.calls.inference.model.NewConstraintSystemImpl
|
||||
import org.jetbrains.kotlin.resolve.calls.tasks.ExplicitReceiverKind
|
||||
import org.jetbrains.kotlin.resolve.calls.tower.*
|
||||
import org.jetbrains.kotlin.resolve.constants.IntegerValueTypeConstant
|
||||
import org.jetbrains.kotlin.types.TypeSubstitutor
|
||||
|
||||
|
||||
@@ -65,6 +67,7 @@ fun KotlinDiagnosticsHolder.addDiagnosticIfNotNull(diagnostic: KotlinCallDiagnos
|
||||
*/
|
||||
class KotlinResolutionCandidate(
|
||||
val callComponents: KotlinCallComponents,
|
||||
val resolutionCallbacks: KotlinResolutionCallbacks,
|
||||
val callableReferenceResolver: CallableReferenceResolver,
|
||||
val scopeTower: ImplicitScopeTower,
|
||||
private val baseSystem: ConstraintStorage,
|
||||
@@ -182,6 +185,7 @@ class MutableResolvedCallAtom(
|
||||
override lateinit var knownParametersSubstitutor: TypeSubstitutor
|
||||
lateinit var argumentToCandidateParameter: Map<KotlinCallArgument, ValueParameterDescriptor>
|
||||
private var samAdapterMap: HashMap<KotlinCallArgument, SamConversionDescription>? = null
|
||||
private var signedUnsignedConstantConversions: HashMap<KotlinCallArgument, IntegerValueTypeConstant>? = null
|
||||
|
||||
val hasSamConversion: Boolean
|
||||
get() = samAdapterMap != null
|
||||
@@ -189,6 +193,9 @@ class MutableResolvedCallAtom(
|
||||
override val argumentsWithConversion: Map<KotlinCallArgument, SamConversionDescription>
|
||||
get() = samAdapterMap ?: emptyMap()
|
||||
|
||||
override val argumentsWithConstantConversion: Map<KotlinCallArgument, IntegerValueTypeConstant>
|
||||
get() = signedUnsignedConstantConversions ?: emptyMap()
|
||||
|
||||
fun registerArgumentWithSamConversion(argument: KotlinCallArgument, samConversionDescription: SamConversionDescription) {
|
||||
if (samAdapterMap == null)
|
||||
samAdapterMap = hashMapOf()
|
||||
@@ -196,6 +203,14 @@ class MutableResolvedCallAtom(
|
||||
samAdapterMap!![argument] = samConversionDescription
|
||||
}
|
||||
|
||||
fun registerArgumentWithConstantConversion(argument: KotlinCallArgument, convertedConstant: IntegerValueTypeConstant) {
|
||||
if (signedUnsignedConstantConversions == null)
|
||||
signedUnsignedConstantConversions = hashMapOf()
|
||||
|
||||
signedUnsignedConstantConversions!![argument] = convertedConstant
|
||||
}
|
||||
|
||||
|
||||
override public fun setAnalyzedResults(subResolvedAtoms: List<ResolvedAtom>) {
|
||||
super.setAnalyzedResults(subResolvedAtoms)
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user