[NI] Support signed-unsigned conversions for K/Native
#KT-34545 Fixed
This commit is contained in:
+21
@@ -8,6 +8,7 @@ package org.jetbrains.kotlin.resolve.calls.tower
|
||||
import com.intellij.psi.util.PsiTreeUtil
|
||||
import org.jetbrains.kotlin.builtins.KotlinBuiltIns.isPrimitiveTypeOrNullablePrimitiveType
|
||||
import org.jetbrains.kotlin.builtins.KotlinBuiltIns.isUnderKotlinPackage
|
||||
import org.jetbrains.kotlin.builtins.UnsignedTypes
|
||||
import org.jetbrains.kotlin.builtins.createFunctionType
|
||||
import org.jetbrains.kotlin.config.LanguageVersionSettings
|
||||
import org.jetbrains.kotlin.descriptors.CallableDescriptor
|
||||
@@ -33,6 +34,8 @@ import org.jetbrains.kotlin.resolve.calls.model.*
|
||||
import org.jetbrains.kotlin.resolve.calls.smartcasts.DataFlowInfo
|
||||
import org.jetbrains.kotlin.resolve.calls.smartcasts.DataFlowValueFactory
|
||||
import org.jetbrains.kotlin.resolve.calls.util.CallMaker
|
||||
import org.jetbrains.kotlin.resolve.constants.CompileTimeConstant
|
||||
import org.jetbrains.kotlin.resolve.constants.IntegerValueTypeConstant
|
||||
import org.jetbrains.kotlin.resolve.constants.evaluate.ConstantExpressionEvaluator
|
||||
import org.jetbrains.kotlin.resolve.deprecation.DeprecationResolver
|
||||
import org.jetbrains.kotlin.resolve.descriptorUtil.builtIns
|
||||
@@ -287,4 +290,22 @@ class KotlinResolutionCallbacksImpl(
|
||||
val context = topLevelCallContext ?: return
|
||||
disableContractsInsideContractsBlock(atom.psiCall, resolvedAtom.candidateDescriptor, context.scope, trace)
|
||||
}
|
||||
|
||||
override fun convertSignedConstantToUnsigned(argument: KotlinCallArgument): IntegerValueTypeConstant? {
|
||||
val argumentExpression = argument.psiExpression ?: return null
|
||||
return convertSignedConstantToUnsigned(argumentExpression)
|
||||
}
|
||||
|
||||
private fun convertSignedConstantToUnsigned(expression: KtExpression): IntegerValueTypeConstant? {
|
||||
val constant = trace[BindingContext.COMPILE_TIME_VALUE, expression]
|
||||
if (constant !is IntegerValueTypeConstant || !constantCanBeConvertedToUnsigned(constant)) return null
|
||||
|
||||
return with(IntegerValueTypeConstant) {
|
||||
constant.convertToUnsignedConstant(moduleDescriptor)
|
||||
}
|
||||
}
|
||||
|
||||
private fun constantCanBeConvertedToUnsigned(constant: CompileTimeConstant<*>): Boolean {
|
||||
return !constant.isError && constant.parameters.isPure
|
||||
}
|
||||
}
|
||||
|
||||
+5
-7
@@ -22,7 +22,6 @@ import org.jetbrains.kotlin.config.LanguageVersionSettings
|
||||
import org.jetbrains.kotlin.descriptors.CallableDescriptor
|
||||
import org.jetbrains.kotlin.descriptors.DeclarationDescriptor
|
||||
import org.jetbrains.kotlin.descriptors.ValueParameterDescriptor
|
||||
import org.jetbrains.kotlin.name.Name
|
||||
import org.jetbrains.kotlin.psi.KtSuperExpression
|
||||
import org.jetbrains.kotlin.resolve.DescriptorToSourceUtils
|
||||
import org.jetbrains.kotlin.resolve.calls.callResolverUtil.isConventionCall
|
||||
@@ -40,12 +39,11 @@ import org.jetbrains.kotlin.resolve.calls.model.KotlinCallArgument
|
||||
import org.jetbrains.kotlin.resolve.calls.model.SimpleKotlinCallArgument
|
||||
import org.jetbrains.kotlin.resolve.calls.results.SimpleConstraintSystem
|
||||
import org.jetbrains.kotlin.resolve.deprecation.DeprecationResolver
|
||||
import org.jetbrains.kotlin.types.expressions.ControlStructureTypingUtils
|
||||
import org.jetbrains.kotlin.utils.addToStdlib.safeAs
|
||||
|
||||
class KotlinResolutionStatelessCallbacksImpl(
|
||||
private val deprecationResolver: DeprecationResolver,
|
||||
private val languageVersionSettings: LanguageVersionSettings
|
||||
private val languageVersionSettings: LanguageVersionSettings,
|
||||
) : KotlinResolutionStatelessCallbacks {
|
||||
override fun isDescriptorFromSource(descriptor: CallableDescriptor) =
|
||||
DescriptorToSourceUtils.descriptorToDeclaration(descriptor) != null
|
||||
@@ -61,13 +59,13 @@ class KotlinResolutionStatelessCallbacksImpl(
|
||||
kotlinCall is PSIKotlinCallImpl && isSuperOrDelegatingConstructorCall(kotlinCall.psiCall)
|
||||
|
||||
override fun isHiddenInResolution(
|
||||
descriptor: DeclarationDescriptor, kotlinCall: KotlinCall, resolutionCallbacks: KotlinResolutionCallbacks
|
||||
descriptor: DeclarationDescriptor, kotlinCall: KotlinCall, resolutionCallbacks: KotlinResolutionCallbacks,
|
||||
) =
|
||||
deprecationResolver.isHiddenInResolution(
|
||||
descriptor,
|
||||
(kotlinCall as? PSIKotlinCall)?.psiCall,
|
||||
(resolutionCallbacks as? KotlinResolutionCallbacksImpl)?.trace?.bindingContext,
|
||||
isSuperOrDelegatingConstructorCall(kotlinCall)
|
||||
isSuperOrDelegatingConstructorCall(kotlinCall),
|
||||
)
|
||||
|
||||
override fun isSuperExpression(receiver: SimpleKotlinCallArgument?): Boolean =
|
||||
@@ -84,13 +82,13 @@ class KotlinResolutionStatelessCallbacksImpl(
|
||||
|
||||
override fun isApplicableCallForBuilderInference(
|
||||
descriptor: CallableDescriptor,
|
||||
languageVersionSettings: LanguageVersionSettings
|
||||
languageVersionSettings: LanguageVersionSettings,
|
||||
): Boolean {
|
||||
return org.jetbrains.kotlin.resolve.calls.inference.isApplicableCallForBuilderInference(descriptor, languageVersionSettings)
|
||||
}
|
||||
|
||||
override fun createConstraintSystemForOverloadResolution(
|
||||
constraintInjector: ConstraintInjector, builtIns: KotlinBuiltIns
|
||||
constraintInjector: ConstraintInjector, builtIns: KotlinBuiltIns,
|
||||
): SimpleConstraintSystem {
|
||||
return if (languageVersionSettings.getFlag(AnalysisFlags.constraintSystemForOverloadResolution).forNewInference())
|
||||
SimpleConstraintSystemImpl(constraintInjector, builtIns)
|
||||
|
||||
+73
-37
@@ -13,7 +13,9 @@ import org.jetbrains.kotlin.diagnostics.Diagnostic
|
||||
import org.jetbrains.kotlin.diagnostics.Errors
|
||||
import org.jetbrains.kotlin.psi.*
|
||||
import org.jetbrains.kotlin.resolve.*
|
||||
import org.jetbrains.kotlin.resolve.calls.*
|
||||
import org.jetbrains.kotlin.resolve.calls.ArgumentTypeResolver
|
||||
import org.jetbrains.kotlin.resolve.calls.CallTransformer
|
||||
import org.jetbrains.kotlin.resolve.calls.DiagnosticReporterByTrackingStrategy
|
||||
import org.jetbrains.kotlin.resolve.calls.callResolverUtil.getEffectiveExpectedType
|
||||
import org.jetbrains.kotlin.resolve.calls.callUtil.getResolvedCall
|
||||
import org.jetbrains.kotlin.resolve.calls.callUtil.isFakeElement
|
||||
@@ -42,6 +44,7 @@ import org.jetbrains.kotlin.resolve.calls.tasks.ExplicitReceiverKind
|
||||
import org.jetbrains.kotlin.resolve.calls.tasks.TracingStrategy
|
||||
import org.jetbrains.kotlin.resolve.constants.CompileTimeConstant
|
||||
import org.jetbrains.kotlin.resolve.constants.IntegerLiteralTypeConstructor
|
||||
import org.jetbrains.kotlin.resolve.constants.IntegerValueTypeConstant
|
||||
import org.jetbrains.kotlin.resolve.constants.evaluate.ConstantExpressionEvaluator
|
||||
import org.jetbrains.kotlin.resolve.deprecation.DeprecationResolver
|
||||
import org.jetbrains.kotlin.resolve.scopes.receivers.CastImplicitClassReceiver
|
||||
@@ -77,7 +80,7 @@ class KotlinToResolvedCallTransformer(
|
||||
private val typeSystemContext: TypeSystemInferenceExtensionContextDelegate,
|
||||
private val smartCastManager: SmartCastManager,
|
||||
private val typeApproximator: TypeApproximator,
|
||||
private val missingSupertypesResolver: MissingSupertypesResolver
|
||||
private val missingSupertypesResolver: MissingSupertypesResolver,
|
||||
) {
|
||||
companion object {
|
||||
private val REPORT_MISSING_NEW_INFERENCE_DIAGNOSTIC
|
||||
@@ -94,13 +97,13 @@ class KotlinToResolvedCallTransformer(
|
||||
|
||||
fun <D : CallableDescriptor> onlyTransform(
|
||||
resolvedCallAtom: ResolvedCallAtom,
|
||||
diagnostics: Collection<KotlinCallDiagnostic>
|
||||
diagnostics: Collection<KotlinCallDiagnostic>,
|
||||
): ResolvedCall<D> = transformToResolvedCall(resolvedCallAtom, null, null, diagnostics)
|
||||
|
||||
fun <D : CallableDescriptor> transformAndReport(
|
||||
baseResolvedCall: CallResolutionResult,
|
||||
context: BasicCallResolutionContext,
|
||||
tracingStrategy: TracingStrategy
|
||||
tracingStrategy: TracingStrategy,
|
||||
): ResolvedCall<D> {
|
||||
return when (baseResolvedCall) {
|
||||
is PartialCallResolutionResult -> {
|
||||
@@ -129,7 +132,7 @@ class KotlinToResolvedCallTransformer(
|
||||
candidate,
|
||||
context.trace,
|
||||
baseResolvedCall.diagnostics,
|
||||
substitutor = resultSubstitutor
|
||||
substitutor = resultSubstitutor,
|
||||
)
|
||||
|
||||
forwardCallToInferenceSession(baseResolvedCall, context, stub, tracingStrategy)
|
||||
@@ -141,7 +144,7 @@ class KotlinToResolvedCallTransformer(
|
||||
val ktPrimitiveCompleter = ResolvedAtomCompleter(
|
||||
resultSubstitutor, context, this, expressionTypingServices, argumentTypeResolver,
|
||||
doubleColonExpressionResolver, builtIns, deprecationResolver, moduleDescriptor, dataFlowValueFactory,
|
||||
typeApproximator, missingSupertypesResolver
|
||||
typeApproximator, missingSupertypesResolver,
|
||||
)
|
||||
|
||||
if (context.inferenceSession.shouldCompleteResolvedSubAtomsOf(candidate)) {
|
||||
@@ -151,7 +154,7 @@ class KotlinToResolvedCallTransformer(
|
||||
}
|
||||
|
||||
val resolvedCall = ktPrimitiveCompleter.completeResolvedCall(
|
||||
candidate, baseResolvedCall.completedDiagnostic(resultSubstitutor)
|
||||
candidate, baseResolvedCall.completedDiagnostic(resultSubstitutor),
|
||||
) as ResolvedCall<D>
|
||||
|
||||
forwardCallToInferenceSession(baseResolvedCall, context, resolvedCall, tracingStrategy)
|
||||
@@ -168,7 +171,7 @@ class KotlinToResolvedCallTransformer(
|
||||
baseResolvedCall: CallResolutionResult,
|
||||
context: BasicCallResolutionContext,
|
||||
resolvedCall: ResolvedCall<*>,
|
||||
tracingStrategy: TracingStrategy
|
||||
tracingStrategy: TracingStrategy,
|
||||
) {
|
||||
if (baseResolvedCall is CompletedCallResolutionResult) {
|
||||
context.inferenceSession.addCompletedCallInfo(PSICompletedCallInfo(baseResolvedCall, context, resolvedCall, tracingStrategy))
|
||||
@@ -179,7 +182,7 @@ class KotlinToResolvedCallTransformer(
|
||||
candidate: ResolvedCallAtom,
|
||||
trace: BindingTrace,
|
||||
diagnostics: Collection<KotlinCallDiagnostic>,
|
||||
substitutor: NewTypeSubstitutor?
|
||||
substitutor: NewTypeSubstitutor?,
|
||||
): ResolvedCall<D> {
|
||||
val result = transformToResolvedCall<D>(candidate, trace, substitutor, diagnostics)
|
||||
val psiKotlinCall = candidate.atom.psiKotlinCall
|
||||
@@ -194,14 +197,14 @@ class KotlinToResolvedCallTransformer(
|
||||
completedCallAtom: ResolvedCallAtom,
|
||||
trace: BindingTrace?,
|
||||
resultSubstitutor: NewTypeSubstitutor? = null, // if substitutor is not null, it means that this call is completed
|
||||
diagnostics: Collection<KotlinCallDiagnostic>
|
||||
diagnostics: Collection<KotlinCallDiagnostic>,
|
||||
): ResolvedCall<D> {
|
||||
val psiKotlinCall = completedCallAtom.atom.psiKotlinCall
|
||||
return if (psiKotlinCall is PSIKotlinCallForInvoke) {
|
||||
@Suppress("UNCHECKED_CAST")
|
||||
NewVariableAsFunctionResolvedCallImpl(
|
||||
createOrGet(psiKotlinCall.variableCall.resolvedCall, trace, resultSubstitutor, diagnostics),
|
||||
createOrGet(completedCallAtom, trace, resultSubstitutor, diagnostics)
|
||||
createOrGet(completedCallAtom, trace, resultSubstitutor, diagnostics),
|
||||
) as ResolvedCall<D>
|
||||
} else {
|
||||
createOrGet(completedCallAtom, trace, resultSubstitutor, diagnostics)
|
||||
@@ -212,7 +215,7 @@ class KotlinToResolvedCallTransformer(
|
||||
completedSimpleAtom: ResolvedCallAtom,
|
||||
trace: BindingTrace?,
|
||||
resultSubstitutor: NewTypeSubstitutor?,
|
||||
diagnostics: Collection<KotlinCallDiagnostic>
|
||||
diagnostics: Collection<KotlinCallDiagnostic>,
|
||||
): NewResolvedCallImpl<D> {
|
||||
if (trace != null) {
|
||||
val storedResolvedCall = completedSimpleAtom.atom.psiKotlinCall.getResolvedPsiKotlinCall<D>(trace)
|
||||
@@ -249,14 +252,14 @@ class KotlinToResolvedCallTransformer(
|
||||
resolvedCall.resultingDescriptor.extensionReceiverParameter,
|
||||
resolvedCall.extensionReceiver,
|
||||
resolvedCall.explicitReceiverKind.isExtensionReceiver,
|
||||
implicitInvokeCheck = false
|
||||
implicitInvokeCheck = false,
|
||||
)
|
||||
context.checkReceiver(
|
||||
resolvedCall,
|
||||
resolvedCall.resultingDescriptor.dispatchReceiverParameter,
|
||||
resolvedCall.dispatchReceiver,
|
||||
resolvedCall.explicitReceiverKind.isDispatchReceiver,
|
||||
implicitInvokeCheck = context.call is CallTransformer.CallForImplicitInvoke
|
||||
implicitInvokeCheck = context.call is CallTransformer.CallForImplicitInvoke,
|
||||
)
|
||||
|
||||
}
|
||||
@@ -266,7 +269,7 @@ class KotlinToResolvedCallTransformer(
|
||||
receiverParameter: ReceiverParameterDescriptor?,
|
||||
receiverArgument: ReceiverValue?,
|
||||
isExplicitReceiver: Boolean,
|
||||
implicitInvokeCheck: Boolean
|
||||
implicitInvokeCheck: Boolean,
|
||||
) {
|
||||
if (receiverParameter == null || receiverArgument == null) return
|
||||
val safeAccess = isExplicitReceiver && !implicitInvokeCheck && resolvedCall.call.isSemanticallyEquivalentToSafeCall
|
||||
@@ -277,7 +280,7 @@ class KotlinToResolvedCallTransformer(
|
||||
fun runArgumentsChecks(
|
||||
context: BasicCallResolutionContext,
|
||||
trace: BindingTrace,
|
||||
resolvedCall: NewResolvedCallImpl<*>
|
||||
resolvedCall: NewResolvedCallImpl<*>,
|
||||
) {
|
||||
|
||||
for (valueArgument in resolvedCall.call.valueArguments) {
|
||||
@@ -291,7 +294,7 @@ class KotlinToResolvedCallTransformer(
|
||||
?: getEffectiveExpectedType(argumentMapping.valueParameter, valueArgument, context)
|
||||
Pair(
|
||||
expectedType,
|
||||
CallPosition.ValueArgumentPosition(resolvedCall, argumentMapping.valueParameter, valueArgument)
|
||||
CallPosition.ValueArgumentPosition(resolvedCall, argumentMapping.valueParameter, valueArgument),
|
||||
)
|
||||
}
|
||||
else -> {
|
||||
@@ -303,12 +306,25 @@ class KotlinToResolvedCallTransformer(
|
||||
context.replaceDataFlowInfo(resolvedCall.dataFlowInfoForArguments.getInfo(valueArgument))
|
||||
.replaceExpectedType(expectedType)
|
||||
.replaceCallPosition(callPosition)
|
||||
.replaceBindingTrace(trace)
|
||||
|
||||
// todo external argument
|
||||
|
||||
val constantConvertedArgument = resolvedCall.getArgumentTypeForConstantConvertedArgument(valueArgument)
|
||||
val argumentExpression = valueArgument.getArgumentExpression() ?: continue
|
||||
updateRecordedType(argumentExpression, parameter, newContext, resolvedCall.isReallySuccess())
|
||||
|
||||
if (constantConvertedArgument != null) {
|
||||
context.trace.record(BindingContext.COMPILE_TIME_VALUE, argumentExpression, constantConvertedArgument)
|
||||
BindingContextUtils.updateRecordedType(
|
||||
constantConvertedArgument.unknownIntegerType, argumentExpression, context.trace, false
|
||||
)
|
||||
}
|
||||
|
||||
updateRecordedType(
|
||||
argumentExpression,
|
||||
parameter,
|
||||
newContext,
|
||||
constantConvertedArgument?.unknownIntegerType?.unwrap(),
|
||||
resolvedCall.isReallySuccess()
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -316,14 +332,16 @@ class KotlinToResolvedCallTransformer(
|
||||
expression: KtExpression,
|
||||
parameter: ValueParameterDescriptor?,
|
||||
context: BasicCallResolutionContext,
|
||||
reportErrorForTypeMismatch: Boolean
|
||||
convertedArgumentType: UnwrappedType?,
|
||||
reportErrorForTypeMismatch: Boolean,
|
||||
): KotlinType? {
|
||||
val deparenthesized = expression.let {
|
||||
KtPsiUtil.getLastElementDeparenthesized(it, context.statementFilter)
|
||||
} ?: return null
|
||||
|
||||
val recordedType = context.trace.getType(deparenthesized)
|
||||
var updatedType = getResolvedCallForArgumentExpression(deparenthesized, context)?.run {
|
||||
|
||||
var updatedType = convertedArgumentType ?: getResolvedCallForArgumentExpression(deparenthesized, context)?.run {
|
||||
makeNullableTypeIfSafeReceiver(resultingDescriptor.returnType, context)
|
||||
} ?: recordedType
|
||||
|
||||
@@ -333,7 +351,6 @@ class KotlinToResolvedCallTransformer(
|
||||
updatedType = argumentTypeResolver.updateResultArgumentTypeIfNotDenotable(context, deparenthesized) ?: updatedType
|
||||
}
|
||||
|
||||
|
||||
var reportErrorDuringTypeCheck = reportErrorForTypeMismatch
|
||||
|
||||
if (parameter != null && ImplicitIntegerCoercion.isEnabledForParameter(parameter)) {
|
||||
@@ -342,12 +359,14 @@ class KotlinToResolvedCallTransformer(
|
||||
val generalNumberType = createTypeForConvertableConstant(argumentCompileTimeValue)
|
||||
if (generalNumberType != null) {
|
||||
updatedType = argumentTypeResolver.updateResultArgumentTypeIfNotDenotable(
|
||||
context.trace, context.statementFilter, context.expectedType, generalNumberType, expression
|
||||
context.trace, context.statementFilter, context.expectedType, generalNumberType, expression,
|
||||
)
|
||||
reportErrorDuringTypeCheck = true
|
||||
}
|
||||
|
||||
}
|
||||
} else if (convertedArgumentType != null) {
|
||||
context.trace.report(Errors.SIGNED_CONSTANT_CONVERTED_TO_UNSIGNED.on(deparenthesized))
|
||||
}
|
||||
|
||||
updatedType = updateRecordedTypeForArgument(updatedType, recordedType, expression, context)
|
||||
@@ -362,7 +381,7 @@ class KotlinToResolvedCallTransformer(
|
||||
val typeConstructor = IntegerLiteralTypeConstructor(value, moduleDescriptor, constant.parameters)
|
||||
return KotlinTypeFactory.simpleTypeWithNonTrivialMemberScope(
|
||||
Annotations.EMPTY, typeConstructor, emptyList(), false,
|
||||
ErrorUtils.createErrorScope("Scope for number value type ($typeConstructor)", true)
|
||||
ErrorUtils.createErrorScope("Scope for number value type ($typeConstructor)", true),
|
||||
)
|
||||
}
|
||||
|
||||
@@ -377,7 +396,7 @@ class KotlinToResolvedCallTransformer(
|
||||
updatedType: KotlinType?,
|
||||
recordedType: KotlinType?,
|
||||
argumentExpression: KtExpression,
|
||||
context: BasicCallResolutionContext
|
||||
context: BasicCallResolutionContext,
|
||||
): KotlinType? {
|
||||
if ((!ErrorUtils.containsErrorType(recordedType) && recordedType == updatedType) || updatedType == null) return updatedType
|
||||
|
||||
@@ -433,7 +452,7 @@ class KotlinToResolvedCallTransformer(
|
||||
context: BasicCallResolutionContext,
|
||||
trace: BindingTrace,
|
||||
resolvedCall: ResolvedCall<*>,
|
||||
diagnostics: Collection<KotlinCallDiagnostic>
|
||||
diagnostics: Collection<KotlinCallDiagnostic>,
|
||||
) {
|
||||
when (resolvedCall) {
|
||||
is NewResolvedCallImpl ->
|
||||
@@ -471,7 +490,7 @@ class KotlinToResolvedCallTransformer(
|
||||
trace: BindingTrace,
|
||||
completedCallAtom: ResolvedCallAtom,
|
||||
resultingDescriptor: CallableDescriptor,
|
||||
diagnostics: Collection<KotlinCallDiagnostic>
|
||||
diagnostics: Collection<KotlinCallDiagnostic>,
|
||||
) {
|
||||
val trackingTrace = TrackingBindingTrace(trace)
|
||||
val newContext = context.replaceBindingTrace(trackingTrace)
|
||||
@@ -487,7 +506,7 @@ class KotlinToResolvedCallTransformer(
|
||||
completedCallAtom.atom.psiKotlinCall,
|
||||
context.dataFlowValueFactory,
|
||||
allDiagnostics,
|
||||
smartCastManager
|
||||
smartCastManager,
|
||||
)
|
||||
|
||||
for (diagnostic in allDiagnostics) {
|
||||
@@ -497,7 +516,7 @@ class KotlinToResolvedCallTransformer(
|
||||
if (diagnostic is ResolvedUsingDeprecatedVisibility) {
|
||||
reportResolvedUsingDeprecatedVisibility(
|
||||
completedCallAtom.atom.psiKotlinCall.psiCall, completedCallAtom.candidateDescriptor,
|
||||
resultingDescriptor, diagnostic, trace
|
||||
resultingDescriptor, diagnostic, trace,
|
||||
)
|
||||
}
|
||||
|
||||
@@ -592,7 +611,7 @@ sealed class NewAbstractResolvedCall<D : CallableDescriptor>() : ResolvedCall<D>
|
||||
|
||||
protected abstract fun argumentToParameterMap(
|
||||
resultingDescriptor: CallableDescriptor,
|
||||
valueArguments: Map<ValueParameterDescriptor, ResolvedValueArgument>
|
||||
valueArguments: Map<ValueParameterDescriptor, ResolvedValueArgument>,
|
||||
): Map<ValueArgument, ArgumentMatchImpl>
|
||||
|
||||
private fun createValueArguments(): Map<ValueParameterDescriptor, ResolvedValueArgument> =
|
||||
@@ -623,7 +642,7 @@ class NewResolvedCallImpl<D : CallableDescriptor>(
|
||||
val resolvedCallAtom: ResolvedCallAtom,
|
||||
substitutor: NewTypeSubstitutor?,
|
||||
private var diagnostics: Collection<KotlinCallDiagnostic>,
|
||||
private val typeApproximator: TypeApproximator
|
||||
private val typeApproximator: TypeApproximator,
|
||||
) : NewAbstractResolvedCall<D>() {
|
||||
var isCompleted = false
|
||||
private set
|
||||
@@ -635,6 +654,7 @@ class NewResolvedCallImpl<D : CallableDescriptor>(
|
||||
private var dispatchReceiver = resolvedCallAtom.dispatchReceiverArgument?.receiver?.receiverValue
|
||||
private var smartCastDispatchReceiverType: KotlinType? = null
|
||||
private var expedtedTypeForSamConvertedArgumentMap: MutableMap<ValueArgument, UnwrappedType>? = null
|
||||
private var argumentTypeForConstantConvertedMap: MutableMap<KtExpression, IntegerValueTypeConstant>? = null
|
||||
|
||||
|
||||
override val kotlinCall: KotlinCall get() = resolvedCallAtom.atom
|
||||
@@ -662,7 +682,7 @@ class NewResolvedCallImpl<D : CallableDescriptor>(
|
||||
if (extensionReceiver is ImplicitClassReceiver) {
|
||||
extensionReceiver = CastImplicitClassReceiver(
|
||||
(extensionReceiver as ImplicitClassReceiver).classDescriptor,
|
||||
smartCastExtensionReceiverType
|
||||
smartCastExtensionReceiverType,
|
||||
)
|
||||
}
|
||||
}
|
||||
@@ -715,6 +735,7 @@ class NewResolvedCallImpl<D : CallableDescriptor>(
|
||||
}
|
||||
|
||||
calculateExpectedTypeForSamConvertedArgumentMap(substitutor)
|
||||
calculateExpectedTypeForConstantConvertedArgumentMap()
|
||||
}
|
||||
|
||||
private fun KotlinType.withNullabilityFromExplicitTypeArgument(typeArgument: SimpleTypeArgument) =
|
||||
@@ -722,7 +743,7 @@ class NewResolvedCallImpl<D : CallableDescriptor>(
|
||||
|
||||
private fun getSubstitutorWithoutFlexibleTypes(
|
||||
currentSubstitutor: NewTypeSubstitutor?,
|
||||
explicitTypeArguments: List<SimpleTypeArgument>
|
||||
explicitTypeArguments: List<SimpleTypeArgument>,
|
||||
): NewTypeSubstitutor? {
|
||||
if (currentSubstitutor !is NewTypeSubstitutorByConstructorMap || explicitTypeArguments.isEmpty()) return currentSubstitutor
|
||||
if (!currentSubstitutor.map.any { (_, value) -> value.isFlexible() }) return currentSubstitutor
|
||||
@@ -747,7 +768,7 @@ class NewResolvedCallImpl<D : CallableDescriptor>(
|
||||
val explicitTypeArguments = resolvedCallAtom.atom.typeArguments.filterIsInstance<SimpleTypeArgument>()
|
||||
|
||||
candidateDescriptor.substituteInferredVariablesAndApproximate(
|
||||
getSubstitutorWithoutFlexibleTypes(substitutor, explicitTypeArguments)
|
||||
getSubstitutorWithoutFlexibleTypes(substitutor, explicitTypeArguments),
|
||||
)
|
||||
}
|
||||
is FunctionDescriptor -> candidateDescriptor.substituteInferredVariablesAndApproximate(substitutor)
|
||||
@@ -774,9 +795,24 @@ class NewResolvedCallImpl<D : CallableDescriptor>(
|
||||
.substituteAndApproximateTypes(compositeSubstitutor, typeApproximator)
|
||||
}
|
||||
|
||||
fun getArgumentTypeForConstantConvertedArgument(valueArgument: ValueArgument): IntegerValueTypeConstant? {
|
||||
val expression = valueArgument.getArgumentExpression() ?: return null
|
||||
return argumentTypeForConstantConvertedMap?.get(expression)
|
||||
}
|
||||
|
||||
fun getExpectedTypeForSamConvertedArgument(valueArgument: ValueArgument): UnwrappedType? =
|
||||
expedtedTypeForSamConvertedArgumentMap?.get(valueArgument)
|
||||
|
||||
private fun calculateExpectedTypeForConstantConvertedArgumentMap() {
|
||||
if (resolvedCallAtom.argumentsWithConstantConversion.isEmpty()) return
|
||||
|
||||
argumentTypeForConstantConvertedMap = hashMapOf()
|
||||
for ((argument, convertedConstant) in resolvedCallAtom.argumentsWithConstantConversion) {
|
||||
val expression = argument.psiExpression ?: continue
|
||||
argumentTypeForConstantConvertedMap!![expression] = convertedConstant
|
||||
}
|
||||
}
|
||||
|
||||
private fun calculateExpectedTypeForSamConvertedArgumentMap(substitutor: NewTypeSubstitutor?) {
|
||||
if (resolvedCallAtom.argumentsWithConversion.isEmpty()) return
|
||||
|
||||
@@ -791,7 +827,7 @@ class NewResolvedCallImpl<D : CallableDescriptor>(
|
||||
|
||||
override fun argumentToParameterMap(
|
||||
resultingDescriptor: CallableDescriptor,
|
||||
valueArguments: Map<ValueParameterDescriptor, ResolvedValueArgument>
|
||||
valueArguments: Map<ValueParameterDescriptor, ResolvedValueArgument>,
|
||||
): Map<ValueArgument, ArgumentMatchImpl> {
|
||||
val argumentErrors = collectErrorPositions()
|
||||
|
||||
@@ -846,7 +882,7 @@ fun ResolutionCandidateApplicability.toResolutionStatus(): ResolutionStatus = wh
|
||||
|
||||
class NewVariableAsFunctionResolvedCallImpl(
|
||||
override val variableCall: NewResolvedCallImpl<VariableDescriptor>,
|
||||
override val functionCall: NewResolvedCallImpl<FunctionDescriptor>
|
||||
override val functionCall: NewResolvedCallImpl<FunctionDescriptor>,
|
||||
) : VariableAsFunctionResolvedCall, ResolvedCall<FunctionDescriptor> by functionCall {
|
||||
val baseCall get() = functionCall.resolvedCallAtom.atom.psiKotlinCall.cast<PSIKotlinCallForInvoke>().baseCall
|
||||
}
|
||||
|
||||
+5
-1
@@ -201,7 +201,11 @@ class ResolvedAtomCompleter(
|
||||
|
||||
val argumentExpression = resultValueArgument.valueArgument.getArgumentExpression() ?: continue
|
||||
kotlinToResolvedCallTransformer.updateRecordedType(
|
||||
argumentExpression, parameter = null, context = newContext, reportErrorForTypeMismatch = true
|
||||
argumentExpression,
|
||||
parameter = null,
|
||||
context = newContext,
|
||||
reportErrorForTypeMismatch = true,
|
||||
convertedArgumentType = null
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
+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)
|
||||
}
|
||||
|
||||
+5
-2
@@ -1,5 +1,6 @@
|
||||
// !DIAGNOSTICS: -UNUSED_PARAMETER, -UNUSED_VARIABLE
|
||||
// !CHECK_TYPE
|
||||
// !WITH_NEW_INFERENCE
|
||||
|
||||
// Here we mostly trying to fix behaviour in order to track changes in inference rules for unsigned types later
|
||||
|
||||
@@ -9,9 +10,11 @@ fun <K> select(x: K, y: K): K = TODO()
|
||||
fun takeUByte(u: UByte) {}
|
||||
|
||||
fun foo() {
|
||||
select(1, 1u) checkType { _<Comparable<*>>() }
|
||||
takeUByte(<!TYPE_INFERENCE_EXPECTED_TYPE_MISMATCH!>id(1)<!>)
|
||||
<!NI;TYPE_MISMATCH!>select<!>(1, 1u) checkType { <!NI;UNRESOLVED_REFERENCE_WRONG_RECEIVER!>_<!><Comparable<*>>() }
|
||||
takeUByte(<!NI;TYPE_MISMATCH, OI;TYPE_INFERENCE_EXPECTED_TYPE_MISMATCH!>id(1)<!>)
|
||||
|
||||
1 <!NONE_APPLICABLE!>+<!> 1u
|
||||
(1u + <!SIGNED_CONSTANT_CONVERTED_TO_UNSIGNED!>1<!>) checkType { _<UInt>() }
|
||||
|
||||
id<UInt>(<!SIGNED_CONSTANT_CONVERTED_TO_UNSIGNED!>1<!>)
|
||||
}
|
||||
+2
-1
@@ -1,4 +1,5 @@
|
||||
// !DIAGNOSTICS: -UNUSED_PARAMETER
|
||||
// !WITH_NEW_INFERENCE
|
||||
|
||||
fun takeUByte(u: UByte) {}
|
||||
fun takeUShort(u: UShort) {}
|
||||
@@ -26,7 +27,7 @@ fun test() {
|
||||
takeUInt(<!SIGNED_CONSTANT_CONVERTED_TO_UNSIGNED!>1<!>)
|
||||
takeULong(<!SIGNED_CONSTANT_CONVERTED_TO_UNSIGNED!>1<!>)
|
||||
|
||||
takeULong(<!INT_LITERAL_OUT_OF_RANGE!>18446744073709551615<!>)
|
||||
takeULong(<!INT_LITERAL_OUT_OF_RANGE, NI;TYPE_MISMATCH!>18446744073709551615<!>)
|
||||
takeULong(<!SIGNED_CONSTANT_CONVERTED_TO_UNSIGNED!>1844674407370955161<!>)
|
||||
takeULong(18446744073709551615u)
|
||||
|
||||
|
||||
Reference in New Issue
Block a user