[NI] Support signed-unsigned conversions for K/Native

#KT-34545 Fixed
This commit is contained in:
Mikhail Zarechenskiy
2020-02-11 08:17:50 +03:00
parent e14e58c121
commit 0d310c0fa4
14 changed files with 179 additions and 57 deletions
@@ -8,6 +8,7 @@ package org.jetbrains.kotlin.resolve.calls.tower
import com.intellij.psi.util.PsiTreeUtil import com.intellij.psi.util.PsiTreeUtil
import org.jetbrains.kotlin.builtins.KotlinBuiltIns.isPrimitiveTypeOrNullablePrimitiveType import org.jetbrains.kotlin.builtins.KotlinBuiltIns.isPrimitiveTypeOrNullablePrimitiveType
import org.jetbrains.kotlin.builtins.KotlinBuiltIns.isUnderKotlinPackage import org.jetbrains.kotlin.builtins.KotlinBuiltIns.isUnderKotlinPackage
import org.jetbrains.kotlin.builtins.UnsignedTypes
import org.jetbrains.kotlin.builtins.createFunctionType import org.jetbrains.kotlin.builtins.createFunctionType
import org.jetbrains.kotlin.config.LanguageVersionSettings import org.jetbrains.kotlin.config.LanguageVersionSettings
import org.jetbrains.kotlin.descriptors.CallableDescriptor 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.DataFlowInfo
import org.jetbrains.kotlin.resolve.calls.smartcasts.DataFlowValueFactory import org.jetbrains.kotlin.resolve.calls.smartcasts.DataFlowValueFactory
import org.jetbrains.kotlin.resolve.calls.util.CallMaker 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.constants.evaluate.ConstantExpressionEvaluator
import org.jetbrains.kotlin.resolve.deprecation.DeprecationResolver import org.jetbrains.kotlin.resolve.deprecation.DeprecationResolver
import org.jetbrains.kotlin.resolve.descriptorUtil.builtIns import org.jetbrains.kotlin.resolve.descriptorUtil.builtIns
@@ -287,4 +290,22 @@ class KotlinResolutionCallbacksImpl(
val context = topLevelCallContext ?: return val context = topLevelCallContext ?: return
disableContractsInsideContractsBlock(atom.psiCall, resolvedAtom.candidateDescriptor, context.scope, trace) 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
}
} }
@@ -22,7 +22,6 @@ import org.jetbrains.kotlin.config.LanguageVersionSettings
import org.jetbrains.kotlin.descriptors.CallableDescriptor import org.jetbrains.kotlin.descriptors.CallableDescriptor
import org.jetbrains.kotlin.descriptors.DeclarationDescriptor import org.jetbrains.kotlin.descriptors.DeclarationDescriptor
import org.jetbrains.kotlin.descriptors.ValueParameterDescriptor import org.jetbrains.kotlin.descriptors.ValueParameterDescriptor
import org.jetbrains.kotlin.name.Name
import org.jetbrains.kotlin.psi.KtSuperExpression import org.jetbrains.kotlin.psi.KtSuperExpression
import org.jetbrains.kotlin.resolve.DescriptorToSourceUtils import org.jetbrains.kotlin.resolve.DescriptorToSourceUtils
import org.jetbrains.kotlin.resolve.calls.callResolverUtil.isConventionCall 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.model.SimpleKotlinCallArgument
import org.jetbrains.kotlin.resolve.calls.results.SimpleConstraintSystem import org.jetbrains.kotlin.resolve.calls.results.SimpleConstraintSystem
import org.jetbrains.kotlin.resolve.deprecation.DeprecationResolver import org.jetbrains.kotlin.resolve.deprecation.DeprecationResolver
import org.jetbrains.kotlin.types.expressions.ControlStructureTypingUtils
import org.jetbrains.kotlin.utils.addToStdlib.safeAs import org.jetbrains.kotlin.utils.addToStdlib.safeAs
class KotlinResolutionStatelessCallbacksImpl( class KotlinResolutionStatelessCallbacksImpl(
private val deprecationResolver: DeprecationResolver, private val deprecationResolver: DeprecationResolver,
private val languageVersionSettings: LanguageVersionSettings private val languageVersionSettings: LanguageVersionSettings,
) : KotlinResolutionStatelessCallbacks { ) : KotlinResolutionStatelessCallbacks {
override fun isDescriptorFromSource(descriptor: CallableDescriptor) = override fun isDescriptorFromSource(descriptor: CallableDescriptor) =
DescriptorToSourceUtils.descriptorToDeclaration(descriptor) != null DescriptorToSourceUtils.descriptorToDeclaration(descriptor) != null
@@ -61,13 +59,13 @@ class KotlinResolutionStatelessCallbacksImpl(
kotlinCall is PSIKotlinCallImpl && isSuperOrDelegatingConstructorCall(kotlinCall.psiCall) kotlinCall is PSIKotlinCallImpl && isSuperOrDelegatingConstructorCall(kotlinCall.psiCall)
override fun isHiddenInResolution( override fun isHiddenInResolution(
descriptor: DeclarationDescriptor, kotlinCall: KotlinCall, resolutionCallbacks: KotlinResolutionCallbacks descriptor: DeclarationDescriptor, kotlinCall: KotlinCall, resolutionCallbacks: KotlinResolutionCallbacks,
) = ) =
deprecationResolver.isHiddenInResolution( deprecationResolver.isHiddenInResolution(
descriptor, descriptor,
(kotlinCall as? PSIKotlinCall)?.psiCall, (kotlinCall as? PSIKotlinCall)?.psiCall,
(resolutionCallbacks as? KotlinResolutionCallbacksImpl)?.trace?.bindingContext, (resolutionCallbacks as? KotlinResolutionCallbacksImpl)?.trace?.bindingContext,
isSuperOrDelegatingConstructorCall(kotlinCall) isSuperOrDelegatingConstructorCall(kotlinCall),
) )
override fun isSuperExpression(receiver: SimpleKotlinCallArgument?): Boolean = override fun isSuperExpression(receiver: SimpleKotlinCallArgument?): Boolean =
@@ -84,13 +82,13 @@ class KotlinResolutionStatelessCallbacksImpl(
override fun isApplicableCallForBuilderInference( override fun isApplicableCallForBuilderInference(
descriptor: CallableDescriptor, descriptor: CallableDescriptor,
languageVersionSettings: LanguageVersionSettings languageVersionSettings: LanguageVersionSettings,
): Boolean { ): Boolean {
return org.jetbrains.kotlin.resolve.calls.inference.isApplicableCallForBuilderInference(descriptor, languageVersionSettings) return org.jetbrains.kotlin.resolve.calls.inference.isApplicableCallForBuilderInference(descriptor, languageVersionSettings)
} }
override fun createConstraintSystemForOverloadResolution( override fun createConstraintSystemForOverloadResolution(
constraintInjector: ConstraintInjector, builtIns: KotlinBuiltIns constraintInjector: ConstraintInjector, builtIns: KotlinBuiltIns,
): SimpleConstraintSystem { ): SimpleConstraintSystem {
return if (languageVersionSettings.getFlag(AnalysisFlags.constraintSystemForOverloadResolution).forNewInference()) return if (languageVersionSettings.getFlag(AnalysisFlags.constraintSystemForOverloadResolution).forNewInference())
SimpleConstraintSystemImpl(constraintInjector, builtIns) SimpleConstraintSystemImpl(constraintInjector, builtIns)
@@ -13,7 +13,9 @@ import org.jetbrains.kotlin.diagnostics.Diagnostic
import org.jetbrains.kotlin.diagnostics.Errors import org.jetbrains.kotlin.diagnostics.Errors
import org.jetbrains.kotlin.psi.* import org.jetbrains.kotlin.psi.*
import org.jetbrains.kotlin.resolve.* 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.callResolverUtil.getEffectiveExpectedType
import org.jetbrains.kotlin.resolve.calls.callUtil.getResolvedCall import org.jetbrains.kotlin.resolve.calls.callUtil.getResolvedCall
import org.jetbrains.kotlin.resolve.calls.callUtil.isFakeElement 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.calls.tasks.TracingStrategy
import org.jetbrains.kotlin.resolve.constants.CompileTimeConstant import org.jetbrains.kotlin.resolve.constants.CompileTimeConstant
import org.jetbrains.kotlin.resolve.constants.IntegerLiteralTypeConstructor 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.constants.evaluate.ConstantExpressionEvaluator
import org.jetbrains.kotlin.resolve.deprecation.DeprecationResolver import org.jetbrains.kotlin.resolve.deprecation.DeprecationResolver
import org.jetbrains.kotlin.resolve.scopes.receivers.CastImplicitClassReceiver import org.jetbrains.kotlin.resolve.scopes.receivers.CastImplicitClassReceiver
@@ -77,7 +80,7 @@ class KotlinToResolvedCallTransformer(
private val typeSystemContext: TypeSystemInferenceExtensionContextDelegate, private val typeSystemContext: TypeSystemInferenceExtensionContextDelegate,
private val smartCastManager: SmartCastManager, private val smartCastManager: SmartCastManager,
private val typeApproximator: TypeApproximator, private val typeApproximator: TypeApproximator,
private val missingSupertypesResolver: MissingSupertypesResolver private val missingSupertypesResolver: MissingSupertypesResolver,
) { ) {
companion object { companion object {
private val REPORT_MISSING_NEW_INFERENCE_DIAGNOSTIC private val REPORT_MISSING_NEW_INFERENCE_DIAGNOSTIC
@@ -94,13 +97,13 @@ class KotlinToResolvedCallTransformer(
fun <D : CallableDescriptor> onlyTransform( fun <D : CallableDescriptor> onlyTransform(
resolvedCallAtom: ResolvedCallAtom, resolvedCallAtom: ResolvedCallAtom,
diagnostics: Collection<KotlinCallDiagnostic> diagnostics: Collection<KotlinCallDiagnostic>,
): ResolvedCall<D> = transformToResolvedCall(resolvedCallAtom, null, null, diagnostics) ): ResolvedCall<D> = transformToResolvedCall(resolvedCallAtom, null, null, diagnostics)
fun <D : CallableDescriptor> transformAndReport( fun <D : CallableDescriptor> transformAndReport(
baseResolvedCall: CallResolutionResult, baseResolvedCall: CallResolutionResult,
context: BasicCallResolutionContext, context: BasicCallResolutionContext,
tracingStrategy: TracingStrategy tracingStrategy: TracingStrategy,
): ResolvedCall<D> { ): ResolvedCall<D> {
return when (baseResolvedCall) { return when (baseResolvedCall) {
is PartialCallResolutionResult -> { is PartialCallResolutionResult -> {
@@ -129,7 +132,7 @@ class KotlinToResolvedCallTransformer(
candidate, candidate,
context.trace, context.trace,
baseResolvedCall.diagnostics, baseResolvedCall.diagnostics,
substitutor = resultSubstitutor substitutor = resultSubstitutor,
) )
forwardCallToInferenceSession(baseResolvedCall, context, stub, tracingStrategy) forwardCallToInferenceSession(baseResolvedCall, context, stub, tracingStrategy)
@@ -141,7 +144,7 @@ class KotlinToResolvedCallTransformer(
val ktPrimitiveCompleter = ResolvedAtomCompleter( val ktPrimitiveCompleter = ResolvedAtomCompleter(
resultSubstitutor, context, this, expressionTypingServices, argumentTypeResolver, resultSubstitutor, context, this, expressionTypingServices, argumentTypeResolver,
doubleColonExpressionResolver, builtIns, deprecationResolver, moduleDescriptor, dataFlowValueFactory, doubleColonExpressionResolver, builtIns, deprecationResolver, moduleDescriptor, dataFlowValueFactory,
typeApproximator, missingSupertypesResolver typeApproximator, missingSupertypesResolver,
) )
if (context.inferenceSession.shouldCompleteResolvedSubAtomsOf(candidate)) { if (context.inferenceSession.shouldCompleteResolvedSubAtomsOf(candidate)) {
@@ -151,7 +154,7 @@ class KotlinToResolvedCallTransformer(
} }
val resolvedCall = ktPrimitiveCompleter.completeResolvedCall( val resolvedCall = ktPrimitiveCompleter.completeResolvedCall(
candidate, baseResolvedCall.completedDiagnostic(resultSubstitutor) candidate, baseResolvedCall.completedDiagnostic(resultSubstitutor),
) as ResolvedCall<D> ) as ResolvedCall<D>
forwardCallToInferenceSession(baseResolvedCall, context, resolvedCall, tracingStrategy) forwardCallToInferenceSession(baseResolvedCall, context, resolvedCall, tracingStrategy)
@@ -168,7 +171,7 @@ class KotlinToResolvedCallTransformer(
baseResolvedCall: CallResolutionResult, baseResolvedCall: CallResolutionResult,
context: BasicCallResolutionContext, context: BasicCallResolutionContext,
resolvedCall: ResolvedCall<*>, resolvedCall: ResolvedCall<*>,
tracingStrategy: TracingStrategy tracingStrategy: TracingStrategy,
) { ) {
if (baseResolvedCall is CompletedCallResolutionResult) { if (baseResolvedCall is CompletedCallResolutionResult) {
context.inferenceSession.addCompletedCallInfo(PSICompletedCallInfo(baseResolvedCall, context, resolvedCall, tracingStrategy)) context.inferenceSession.addCompletedCallInfo(PSICompletedCallInfo(baseResolvedCall, context, resolvedCall, tracingStrategy))
@@ -179,7 +182,7 @@ class KotlinToResolvedCallTransformer(
candidate: ResolvedCallAtom, candidate: ResolvedCallAtom,
trace: BindingTrace, trace: BindingTrace,
diagnostics: Collection<KotlinCallDiagnostic>, diagnostics: Collection<KotlinCallDiagnostic>,
substitutor: NewTypeSubstitutor? substitutor: NewTypeSubstitutor?,
): ResolvedCall<D> { ): ResolvedCall<D> {
val result = transformToResolvedCall<D>(candidate, trace, substitutor, diagnostics) val result = transformToResolvedCall<D>(candidate, trace, substitutor, diagnostics)
val psiKotlinCall = candidate.atom.psiKotlinCall val psiKotlinCall = candidate.atom.psiKotlinCall
@@ -194,14 +197,14 @@ class KotlinToResolvedCallTransformer(
completedCallAtom: ResolvedCallAtom, completedCallAtom: ResolvedCallAtom,
trace: BindingTrace?, trace: BindingTrace?,
resultSubstitutor: NewTypeSubstitutor? = null, // if substitutor is not null, it means that this call is completed resultSubstitutor: NewTypeSubstitutor? = null, // if substitutor is not null, it means that this call is completed
diagnostics: Collection<KotlinCallDiagnostic> diagnostics: Collection<KotlinCallDiagnostic>,
): ResolvedCall<D> { ): ResolvedCall<D> {
val psiKotlinCall = completedCallAtom.atom.psiKotlinCall val psiKotlinCall = completedCallAtom.atom.psiKotlinCall
return if (psiKotlinCall is PSIKotlinCallForInvoke) { return if (psiKotlinCall is PSIKotlinCallForInvoke) {
@Suppress("UNCHECKED_CAST") @Suppress("UNCHECKED_CAST")
NewVariableAsFunctionResolvedCallImpl( NewVariableAsFunctionResolvedCallImpl(
createOrGet(psiKotlinCall.variableCall.resolvedCall, trace, resultSubstitutor, diagnostics), createOrGet(psiKotlinCall.variableCall.resolvedCall, trace, resultSubstitutor, diagnostics),
createOrGet(completedCallAtom, trace, resultSubstitutor, diagnostics) createOrGet(completedCallAtom, trace, resultSubstitutor, diagnostics),
) as ResolvedCall<D> ) as ResolvedCall<D>
} else { } else {
createOrGet(completedCallAtom, trace, resultSubstitutor, diagnostics) createOrGet(completedCallAtom, trace, resultSubstitutor, diagnostics)
@@ -212,7 +215,7 @@ class KotlinToResolvedCallTransformer(
completedSimpleAtom: ResolvedCallAtom, completedSimpleAtom: ResolvedCallAtom,
trace: BindingTrace?, trace: BindingTrace?,
resultSubstitutor: NewTypeSubstitutor?, resultSubstitutor: NewTypeSubstitutor?,
diagnostics: Collection<KotlinCallDiagnostic> diagnostics: Collection<KotlinCallDiagnostic>,
): NewResolvedCallImpl<D> { ): NewResolvedCallImpl<D> {
if (trace != null) { if (trace != null) {
val storedResolvedCall = completedSimpleAtom.atom.psiKotlinCall.getResolvedPsiKotlinCall<D>(trace) val storedResolvedCall = completedSimpleAtom.atom.psiKotlinCall.getResolvedPsiKotlinCall<D>(trace)
@@ -249,14 +252,14 @@ class KotlinToResolvedCallTransformer(
resolvedCall.resultingDescriptor.extensionReceiverParameter, resolvedCall.resultingDescriptor.extensionReceiverParameter,
resolvedCall.extensionReceiver, resolvedCall.extensionReceiver,
resolvedCall.explicitReceiverKind.isExtensionReceiver, resolvedCall.explicitReceiverKind.isExtensionReceiver,
implicitInvokeCheck = false implicitInvokeCheck = false,
) )
context.checkReceiver( context.checkReceiver(
resolvedCall, resolvedCall,
resolvedCall.resultingDescriptor.dispatchReceiverParameter, resolvedCall.resultingDescriptor.dispatchReceiverParameter,
resolvedCall.dispatchReceiver, resolvedCall.dispatchReceiver,
resolvedCall.explicitReceiverKind.isDispatchReceiver, resolvedCall.explicitReceiverKind.isDispatchReceiver,
implicitInvokeCheck = context.call is CallTransformer.CallForImplicitInvoke implicitInvokeCheck = context.call is CallTransformer.CallForImplicitInvoke,
) )
} }
@@ -266,7 +269,7 @@ class KotlinToResolvedCallTransformer(
receiverParameter: ReceiverParameterDescriptor?, receiverParameter: ReceiverParameterDescriptor?,
receiverArgument: ReceiverValue?, receiverArgument: ReceiverValue?,
isExplicitReceiver: Boolean, isExplicitReceiver: Boolean,
implicitInvokeCheck: Boolean implicitInvokeCheck: Boolean,
) { ) {
if (receiverParameter == null || receiverArgument == null) return if (receiverParameter == null || receiverArgument == null) return
val safeAccess = isExplicitReceiver && !implicitInvokeCheck && resolvedCall.call.isSemanticallyEquivalentToSafeCall val safeAccess = isExplicitReceiver && !implicitInvokeCheck && resolvedCall.call.isSemanticallyEquivalentToSafeCall
@@ -277,7 +280,7 @@ class KotlinToResolvedCallTransformer(
fun runArgumentsChecks( fun runArgumentsChecks(
context: BasicCallResolutionContext, context: BasicCallResolutionContext,
trace: BindingTrace, trace: BindingTrace,
resolvedCall: NewResolvedCallImpl<*> resolvedCall: NewResolvedCallImpl<*>,
) { ) {
for (valueArgument in resolvedCall.call.valueArguments) { for (valueArgument in resolvedCall.call.valueArguments) {
@@ -291,7 +294,7 @@ class KotlinToResolvedCallTransformer(
?: getEffectiveExpectedType(argumentMapping.valueParameter, valueArgument, context) ?: getEffectiveExpectedType(argumentMapping.valueParameter, valueArgument, context)
Pair( Pair(
expectedType, expectedType,
CallPosition.ValueArgumentPosition(resolvedCall, argumentMapping.valueParameter, valueArgument) CallPosition.ValueArgumentPosition(resolvedCall, argumentMapping.valueParameter, valueArgument),
) )
} }
else -> { else -> {
@@ -303,12 +306,25 @@ class KotlinToResolvedCallTransformer(
context.replaceDataFlowInfo(resolvedCall.dataFlowInfoForArguments.getInfo(valueArgument)) context.replaceDataFlowInfo(resolvedCall.dataFlowInfoForArguments.getInfo(valueArgument))
.replaceExpectedType(expectedType) .replaceExpectedType(expectedType)
.replaceCallPosition(callPosition) .replaceCallPosition(callPosition)
.replaceBindingTrace(trace)
// todo external argument
val constantConvertedArgument = resolvedCall.getArgumentTypeForConstantConvertedArgument(valueArgument)
val argumentExpression = valueArgument.getArgumentExpression() ?: continue 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, expression: KtExpression,
parameter: ValueParameterDescriptor?, parameter: ValueParameterDescriptor?,
context: BasicCallResolutionContext, context: BasicCallResolutionContext,
reportErrorForTypeMismatch: Boolean convertedArgumentType: UnwrappedType?,
reportErrorForTypeMismatch: Boolean,
): KotlinType? { ): KotlinType? {
val deparenthesized = expression.let { val deparenthesized = expression.let {
KtPsiUtil.getLastElementDeparenthesized(it, context.statementFilter) KtPsiUtil.getLastElementDeparenthesized(it, context.statementFilter)
} ?: return null } ?: return null
val recordedType = context.trace.getType(deparenthesized) val recordedType = context.trace.getType(deparenthesized)
var updatedType = getResolvedCallForArgumentExpression(deparenthesized, context)?.run {
var updatedType = convertedArgumentType ?: getResolvedCallForArgumentExpression(deparenthesized, context)?.run {
makeNullableTypeIfSafeReceiver(resultingDescriptor.returnType, context) makeNullableTypeIfSafeReceiver(resultingDescriptor.returnType, context)
} ?: recordedType } ?: recordedType
@@ -333,7 +351,6 @@ class KotlinToResolvedCallTransformer(
updatedType = argumentTypeResolver.updateResultArgumentTypeIfNotDenotable(context, deparenthesized) ?: updatedType updatedType = argumentTypeResolver.updateResultArgumentTypeIfNotDenotable(context, deparenthesized) ?: updatedType
} }
var reportErrorDuringTypeCheck = reportErrorForTypeMismatch var reportErrorDuringTypeCheck = reportErrorForTypeMismatch
if (parameter != null && ImplicitIntegerCoercion.isEnabledForParameter(parameter)) { if (parameter != null && ImplicitIntegerCoercion.isEnabledForParameter(parameter)) {
@@ -342,12 +359,14 @@ class KotlinToResolvedCallTransformer(
val generalNumberType = createTypeForConvertableConstant(argumentCompileTimeValue) val generalNumberType = createTypeForConvertableConstant(argumentCompileTimeValue)
if (generalNumberType != null) { if (generalNumberType != null) {
updatedType = argumentTypeResolver.updateResultArgumentTypeIfNotDenotable( updatedType = argumentTypeResolver.updateResultArgumentTypeIfNotDenotable(
context.trace, context.statementFilter, context.expectedType, generalNumberType, expression context.trace, context.statementFilter, context.expectedType, generalNumberType, expression,
) )
reportErrorDuringTypeCheck = true reportErrorDuringTypeCheck = true
} }
} }
} else if (convertedArgumentType != null) {
context.trace.report(Errors.SIGNED_CONSTANT_CONVERTED_TO_UNSIGNED.on(deparenthesized))
} }
updatedType = updateRecordedTypeForArgument(updatedType, recordedType, expression, context) updatedType = updateRecordedTypeForArgument(updatedType, recordedType, expression, context)
@@ -362,7 +381,7 @@ class KotlinToResolvedCallTransformer(
val typeConstructor = IntegerLiteralTypeConstructor(value, moduleDescriptor, constant.parameters) val typeConstructor = IntegerLiteralTypeConstructor(value, moduleDescriptor, constant.parameters)
return KotlinTypeFactory.simpleTypeWithNonTrivialMemberScope( return KotlinTypeFactory.simpleTypeWithNonTrivialMemberScope(
Annotations.EMPTY, typeConstructor, emptyList(), false, 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?, updatedType: KotlinType?,
recordedType: KotlinType?, recordedType: KotlinType?,
argumentExpression: KtExpression, argumentExpression: KtExpression,
context: BasicCallResolutionContext context: BasicCallResolutionContext,
): KotlinType? { ): KotlinType? {
if ((!ErrorUtils.containsErrorType(recordedType) && recordedType == updatedType) || updatedType == null) return updatedType if ((!ErrorUtils.containsErrorType(recordedType) && recordedType == updatedType) || updatedType == null) return updatedType
@@ -433,7 +452,7 @@ class KotlinToResolvedCallTransformer(
context: BasicCallResolutionContext, context: BasicCallResolutionContext,
trace: BindingTrace, trace: BindingTrace,
resolvedCall: ResolvedCall<*>, resolvedCall: ResolvedCall<*>,
diagnostics: Collection<KotlinCallDiagnostic> diagnostics: Collection<KotlinCallDiagnostic>,
) { ) {
when (resolvedCall) { when (resolvedCall) {
is NewResolvedCallImpl -> is NewResolvedCallImpl ->
@@ -471,7 +490,7 @@ class KotlinToResolvedCallTransformer(
trace: BindingTrace, trace: BindingTrace,
completedCallAtom: ResolvedCallAtom, completedCallAtom: ResolvedCallAtom,
resultingDescriptor: CallableDescriptor, resultingDescriptor: CallableDescriptor,
diagnostics: Collection<KotlinCallDiagnostic> diagnostics: Collection<KotlinCallDiagnostic>,
) { ) {
val trackingTrace = TrackingBindingTrace(trace) val trackingTrace = TrackingBindingTrace(trace)
val newContext = context.replaceBindingTrace(trackingTrace) val newContext = context.replaceBindingTrace(trackingTrace)
@@ -487,7 +506,7 @@ class KotlinToResolvedCallTransformer(
completedCallAtom.atom.psiKotlinCall, completedCallAtom.atom.psiKotlinCall,
context.dataFlowValueFactory, context.dataFlowValueFactory,
allDiagnostics, allDiagnostics,
smartCastManager smartCastManager,
) )
for (diagnostic in allDiagnostics) { for (diagnostic in allDiagnostics) {
@@ -497,7 +516,7 @@ class KotlinToResolvedCallTransformer(
if (diagnostic is ResolvedUsingDeprecatedVisibility) { if (diagnostic is ResolvedUsingDeprecatedVisibility) {
reportResolvedUsingDeprecatedVisibility( reportResolvedUsingDeprecatedVisibility(
completedCallAtom.atom.psiKotlinCall.psiCall, completedCallAtom.candidateDescriptor, 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( protected abstract fun argumentToParameterMap(
resultingDescriptor: CallableDescriptor, resultingDescriptor: CallableDescriptor,
valueArguments: Map<ValueParameterDescriptor, ResolvedValueArgument> valueArguments: Map<ValueParameterDescriptor, ResolvedValueArgument>,
): Map<ValueArgument, ArgumentMatchImpl> ): Map<ValueArgument, ArgumentMatchImpl>
private fun createValueArguments(): Map<ValueParameterDescriptor, ResolvedValueArgument> = private fun createValueArguments(): Map<ValueParameterDescriptor, ResolvedValueArgument> =
@@ -623,7 +642,7 @@ class NewResolvedCallImpl<D : CallableDescriptor>(
val resolvedCallAtom: ResolvedCallAtom, val resolvedCallAtom: ResolvedCallAtom,
substitutor: NewTypeSubstitutor?, substitutor: NewTypeSubstitutor?,
private var diagnostics: Collection<KotlinCallDiagnostic>, private var diagnostics: Collection<KotlinCallDiagnostic>,
private val typeApproximator: TypeApproximator private val typeApproximator: TypeApproximator,
) : NewAbstractResolvedCall<D>() { ) : NewAbstractResolvedCall<D>() {
var isCompleted = false var isCompleted = false
private set private set
@@ -635,6 +654,7 @@ class NewResolvedCallImpl<D : CallableDescriptor>(
private var dispatchReceiver = resolvedCallAtom.dispatchReceiverArgument?.receiver?.receiverValue private var dispatchReceiver = resolvedCallAtom.dispatchReceiverArgument?.receiver?.receiverValue
private var smartCastDispatchReceiverType: KotlinType? = null private var smartCastDispatchReceiverType: KotlinType? = null
private var expedtedTypeForSamConvertedArgumentMap: MutableMap<ValueArgument, UnwrappedType>? = null private var expedtedTypeForSamConvertedArgumentMap: MutableMap<ValueArgument, UnwrappedType>? = null
private var argumentTypeForConstantConvertedMap: MutableMap<KtExpression, IntegerValueTypeConstant>? = null
override val kotlinCall: KotlinCall get() = resolvedCallAtom.atom override val kotlinCall: KotlinCall get() = resolvedCallAtom.atom
@@ -662,7 +682,7 @@ class NewResolvedCallImpl<D : CallableDescriptor>(
if (extensionReceiver is ImplicitClassReceiver) { if (extensionReceiver is ImplicitClassReceiver) {
extensionReceiver = CastImplicitClassReceiver( extensionReceiver = CastImplicitClassReceiver(
(extensionReceiver as ImplicitClassReceiver).classDescriptor, (extensionReceiver as ImplicitClassReceiver).classDescriptor,
smartCastExtensionReceiverType smartCastExtensionReceiverType,
) )
} }
} }
@@ -715,6 +735,7 @@ class NewResolvedCallImpl<D : CallableDescriptor>(
} }
calculateExpectedTypeForSamConvertedArgumentMap(substitutor) calculateExpectedTypeForSamConvertedArgumentMap(substitutor)
calculateExpectedTypeForConstantConvertedArgumentMap()
} }
private fun KotlinType.withNullabilityFromExplicitTypeArgument(typeArgument: SimpleTypeArgument) = private fun KotlinType.withNullabilityFromExplicitTypeArgument(typeArgument: SimpleTypeArgument) =
@@ -722,7 +743,7 @@ class NewResolvedCallImpl<D : CallableDescriptor>(
private fun getSubstitutorWithoutFlexibleTypes( private fun getSubstitutorWithoutFlexibleTypes(
currentSubstitutor: NewTypeSubstitutor?, currentSubstitutor: NewTypeSubstitutor?,
explicitTypeArguments: List<SimpleTypeArgument> explicitTypeArguments: List<SimpleTypeArgument>,
): NewTypeSubstitutor? { ): NewTypeSubstitutor? {
if (currentSubstitutor !is NewTypeSubstitutorByConstructorMap || explicitTypeArguments.isEmpty()) return currentSubstitutor if (currentSubstitutor !is NewTypeSubstitutorByConstructorMap || explicitTypeArguments.isEmpty()) return currentSubstitutor
if (!currentSubstitutor.map.any { (_, value) -> value.isFlexible() }) 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>() val explicitTypeArguments = resolvedCallAtom.atom.typeArguments.filterIsInstance<SimpleTypeArgument>()
candidateDescriptor.substituteInferredVariablesAndApproximate( candidateDescriptor.substituteInferredVariablesAndApproximate(
getSubstitutorWithoutFlexibleTypes(substitutor, explicitTypeArguments) getSubstitutorWithoutFlexibleTypes(substitutor, explicitTypeArguments),
) )
} }
is FunctionDescriptor -> candidateDescriptor.substituteInferredVariablesAndApproximate(substitutor) is FunctionDescriptor -> candidateDescriptor.substituteInferredVariablesAndApproximate(substitutor)
@@ -774,9 +795,24 @@ class NewResolvedCallImpl<D : CallableDescriptor>(
.substituteAndApproximateTypes(compositeSubstitutor, typeApproximator) .substituteAndApproximateTypes(compositeSubstitutor, typeApproximator)
} }
fun getArgumentTypeForConstantConvertedArgument(valueArgument: ValueArgument): IntegerValueTypeConstant? {
val expression = valueArgument.getArgumentExpression() ?: return null
return argumentTypeForConstantConvertedMap?.get(expression)
}
fun getExpectedTypeForSamConvertedArgument(valueArgument: ValueArgument): UnwrappedType? = fun getExpectedTypeForSamConvertedArgument(valueArgument: ValueArgument): UnwrappedType? =
expedtedTypeForSamConvertedArgumentMap?.get(valueArgument) 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?) { private fun calculateExpectedTypeForSamConvertedArgumentMap(substitutor: NewTypeSubstitutor?) {
if (resolvedCallAtom.argumentsWithConversion.isEmpty()) return if (resolvedCallAtom.argumentsWithConversion.isEmpty()) return
@@ -791,7 +827,7 @@ class NewResolvedCallImpl<D : CallableDescriptor>(
override fun argumentToParameterMap( override fun argumentToParameterMap(
resultingDescriptor: CallableDescriptor, resultingDescriptor: CallableDescriptor,
valueArguments: Map<ValueParameterDescriptor, ResolvedValueArgument> valueArguments: Map<ValueParameterDescriptor, ResolvedValueArgument>,
): Map<ValueArgument, ArgumentMatchImpl> { ): Map<ValueArgument, ArgumentMatchImpl> {
val argumentErrors = collectErrorPositions() val argumentErrors = collectErrorPositions()
@@ -846,7 +882,7 @@ fun ResolutionCandidateApplicability.toResolutionStatus(): ResolutionStatus = wh
class NewVariableAsFunctionResolvedCallImpl( class NewVariableAsFunctionResolvedCallImpl(
override val variableCall: NewResolvedCallImpl<VariableDescriptor>, override val variableCall: NewResolvedCallImpl<VariableDescriptor>,
override val functionCall: NewResolvedCallImpl<FunctionDescriptor> override val functionCall: NewResolvedCallImpl<FunctionDescriptor>,
) : VariableAsFunctionResolvedCall, ResolvedCall<FunctionDescriptor> by functionCall { ) : VariableAsFunctionResolvedCall, ResolvedCall<FunctionDescriptor> by functionCall {
val baseCall get() = functionCall.resolvedCallAtom.atom.psiKotlinCall.cast<PSIKotlinCallForInvoke>().baseCall val baseCall get() = functionCall.resolvedCallAtom.atom.psiKotlinCall.cast<PSIKotlinCallForInvoke>().baseCall
} }
@@ -201,7 +201,11 @@ class ResolvedAtomCompleter(
val argumentExpression = resultValueArgument.valueArgument.getArgumentExpression() ?: continue val argumentExpression = resultValueArgument.valueArgument.getArgumentExpression() ?: continue
kotlinToResolvedCallTransformer.updateRecordedType( kotlinToResolvedCallTransformer.updateRecordedType(
argumentExpression, parameter = null, context = newContext, reportErrorForTypeMismatch = true argumentExpression,
parameter = null,
context = newContext,
reportErrorForTypeMismatch = true,
convertedArgumentType = null
) )
} }
} }
@@ -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.model.*
import org.jetbrains.kotlin.resolve.calls.results.SimpleConstraintSystem import org.jetbrains.kotlin.resolve.calls.results.SimpleConstraintSystem
import org.jetbrains.kotlin.resolve.calls.tower.ImplicitScopeTower 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.KotlinType
import org.jetbrains.kotlin.types.StubType import org.jetbrains.kotlin.types.StubType
import org.jetbrains.kotlin.types.UnwrappedType import org.jetbrains.kotlin.types.UnwrappedType
@@ -75,4 +76,6 @@ interface KotlinResolutionCallbacks {
fun getExpectedTypeFromAsExpressionAndRecordItInTrace(resolvedAtom: ResolvedCallAtom): UnwrappedType? fun getExpectedTypeFromAsExpressionAndRecordItInTrace(resolvedAtom: ResolvedCallAtom): UnwrappedType?
fun disableContractsIfNecessary(resolvedAtom: ResolvedCallAtom) fun disableContractsIfNecessary(resolvedAtom: ResolvedCallAtom)
fun convertSignedConstantToUnsigned(argument: KotlinCallArgument): IntegerValueTypeConstant?
} }
@@ -35,10 +35,11 @@ fun resolveKtPrimitive(
argument: KotlinCallArgument, argument: KotlinCallArgument,
expectedType: UnwrappedType?, expectedType: UnwrappedType?,
diagnosticsHolder: KotlinDiagnosticsHolder, diagnosticsHolder: KotlinDiagnosticsHolder,
isReceiver: Boolean isReceiver: Boolean,
convertedType: UnwrappedType?
): ResolvedAtom = when (argument) { ): ResolvedAtom = when (argument) {
is SimpleKotlinCallArgument -> is SimpleKotlinCallArgument ->
checkSimpleArgument(csBuilder, argument, expectedType, diagnosticsHolder, isReceiver) checkSimpleArgument(csBuilder, argument, expectedType, diagnosticsHolder, isReceiver, convertedType)
is LambdaKotlinCallArgument -> is LambdaKotlinCallArgument ->
preprocessLambdaArgument(csBuilder, argument, expectedType, diagnosticsHolder) preprocessLambdaArgument(csBuilder, argument, expectedType, diagnosticsHolder)
@@ -132,7 +132,7 @@ class PostponedArgumentsAnalyzer(
val subResolvedKtPrimitives = returnArgumentsInfo.nonErrorArguments.map { val subResolvedKtPrimitives = returnArgumentsInfo.nonErrorArguments.map {
resolveKtPrimitive( resolveKtPrimitive(
c.getBuilder(), it, lambda.returnType.let(::substitute), diagnosticHolder, isReceiver = false c.getBuilder(), it, lambda.returnType.let(::substitute), diagnosticHolder, isReceiver = false, convertedType = null
) )
} }
@@ -5,6 +5,7 @@
package org.jetbrains.kotlin.resolve.calls.components package org.jetbrains.kotlin.resolve.calls.components
import org.jetbrains.kotlin.builtins.UnsignedTypes
import org.jetbrains.kotlin.builtins.getReceiverTypeFromFunctionType import org.jetbrains.kotlin.builtins.getReceiverTypeFromFunctionType
import org.jetbrains.kotlin.builtins.isFunctionType import org.jetbrains.kotlin.builtins.isFunctionType
import org.jetbrains.kotlin.config.LanguageFeature 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.contains
import org.jetbrains.kotlin.types.typeUtil.makeNotNullable import org.jetbrains.kotlin.types.typeUtil.makeNotNullable
import org.jetbrains.kotlin.types.typeUtil.makeNullable import org.jetbrains.kotlin.types.typeUtil.makeNullable
import org.jetbrains.kotlin.utils.addToStdlib.cast
import org.jetbrains.kotlin.utils.addToStdlib.safeAs import org.jetbrains.kotlin.utils.addToStdlib.safeAs
internal object CheckInstantiationOfAbstractClass : ResolutionPart() { internal object CheckInstantiationOfAbstractClass : ResolutionPart() {
@@ -288,7 +290,40 @@ private fun KotlinResolutionCandidate.resolveKotlinArgument(
isReceiver: Boolean isReceiver: Boolean
) { ) {
val expectedType = candidateParameter?.let { prepareExpectedType(argument, candidateParameter) } 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( private fun KotlinResolutionCandidate.prepareExpectedType(
@@ -37,9 +37,10 @@ fun checkSimpleArgument(
argument: SimpleKotlinCallArgument, argument: SimpleKotlinCallArgument,
expectedType: UnwrappedType?, expectedType: UnwrappedType?,
diagnosticsHolder: KotlinDiagnosticsHolder, diagnosticsHolder: KotlinDiagnosticsHolder,
isReceiver: Boolean isReceiver: Boolean,
convertedType: UnwrappedType?
): ResolvedAtom = when (argument) { ): 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) is SubKotlinCallArgument -> checkSubCallArgument(csBuilder, argument, expectedType, diagnosticsHolder, isReceiver)
else -> unexpectedArgument(argument) else -> unexpectedArgument(argument)
} }
@@ -49,13 +50,14 @@ private fun checkExpressionArgument(
expressionArgument: ExpressionKotlinCallArgument, expressionArgument: ExpressionKotlinCallArgument,
expectedType: UnwrappedType?, expectedType: UnwrappedType?,
diagnosticsHolder: KotlinDiagnosticsHolder, diagnosticsHolder: KotlinDiagnosticsHolder,
isReceiver: Boolean isReceiver: Boolean,
convertedType: UnwrappedType?
): ResolvedAtom { ): ResolvedAtom {
val resolvedExpression = ResolvedExpressionAtom(expressionArgument) val resolvedExpression = ResolvedExpressionAtom(expressionArgument)
if (expectedType == null) return resolvedExpression if (expectedType == null) return resolvedExpression
// todo run this approximation only once for call // 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( fun unstableSmartCastOrSubtypeError(
unstableType: UnwrappedType?, actualExpectedType: UnwrappedType, position: ConstraintPosition unstableType: UnwrappedType?, actualExpectedType: UnwrappedType, position: ConstraintPosition
@@ -144,6 +144,7 @@ class SimpleCandidateFactory(
if (ErrorUtils.isError(descriptor)) { if (ErrorUtils.isError(descriptor)) {
return KotlinResolutionCandidate( return KotlinResolutionCandidate(
callComponents, callComponents,
resolutionCallbacks,
callableReferenceResolver, callableReferenceResolver,
scopeTower, scopeTower,
baseSystem, baseSystem,
@@ -154,7 +155,7 @@ class SimpleCandidateFactory(
} }
val candidate = KotlinResolutionCandidate( val candidate = KotlinResolutionCandidate(
callComponents, callableReferenceResolver, scopeTower, baseSystem, resolvedKtCall, knownSubstitutor callComponents, resolutionCallbacks, callableReferenceResolver, scopeTower, baseSystem, resolvedKtCall, knownSubstitutor
) )
initialDiagnostics.forEach(candidate::addDiagnostic) 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.TypeVariableForCallableReferenceReturnType
import org.jetbrains.kotlin.resolve.calls.inference.model.TypeVariableForLambdaReturnType import org.jetbrains.kotlin.resolve.calls.inference.model.TypeVariableForLambdaReturnType
import org.jetbrains.kotlin.resolve.calls.tasks.ExplicitReceiverKind 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.KotlinType
import org.jetbrains.kotlin.types.TypeConstructor import org.jetbrains.kotlin.types.TypeConstructor
import org.jetbrains.kotlin.types.TypeSubstitutor import org.jetbrains.kotlin.types.TypeSubstitutor
@@ -70,6 +71,7 @@ abstract class ResolvedCallAtom : ResolvedAtom() {
abstract val freshVariablesSubstitutor: FreshVariableNewTypeSubstitutor abstract val freshVariablesSubstitutor: FreshVariableNewTypeSubstitutor
abstract val knownParametersSubstitutor: TypeSubstitutor abstract val knownParametersSubstitutor: TypeSubstitutor
abstract val argumentsWithConversion: Map<KotlinCallArgument, SamConversionDescription> abstract val argumentsWithConversion: Map<KotlinCallArgument, SamConversionDescription>
abstract val argumentsWithConstantConversion: Map<KotlinCallArgument, IntegerValueTypeConstant>
} }
class SamConversionDescription( class SamConversionDescription(
@@ -20,6 +20,7 @@ import org.jetbrains.kotlin.descriptors.CallableDescriptor
import org.jetbrains.kotlin.descriptors.ValueParameterDescriptor import org.jetbrains.kotlin.descriptors.ValueParameterDescriptor
import org.jetbrains.kotlin.renderer.DescriptorRenderer import org.jetbrains.kotlin.renderer.DescriptorRenderer
import org.jetbrains.kotlin.resolve.calls.components.CallableReferenceResolver 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.NewConstraintSystemImpl
import org.jetbrains.kotlin.resolve.calls.components.TypeArgumentsToParametersMapper import org.jetbrains.kotlin.resolve.calls.components.TypeArgumentsToParametersMapper
import org.jetbrains.kotlin.resolve.calls.inference.NewConstraintSystem 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.inference.model.NewConstraintSystemImpl
import org.jetbrains.kotlin.resolve.calls.tasks.ExplicitReceiverKind import org.jetbrains.kotlin.resolve.calls.tasks.ExplicitReceiverKind
import org.jetbrains.kotlin.resolve.calls.tower.* import org.jetbrains.kotlin.resolve.calls.tower.*
import org.jetbrains.kotlin.resolve.constants.IntegerValueTypeConstant
import org.jetbrains.kotlin.types.TypeSubstitutor import org.jetbrains.kotlin.types.TypeSubstitutor
@@ -65,6 +67,7 @@ fun KotlinDiagnosticsHolder.addDiagnosticIfNotNull(diagnostic: KotlinCallDiagnos
*/ */
class KotlinResolutionCandidate( class KotlinResolutionCandidate(
val callComponents: KotlinCallComponents, val callComponents: KotlinCallComponents,
val resolutionCallbacks: KotlinResolutionCallbacks,
val callableReferenceResolver: CallableReferenceResolver, val callableReferenceResolver: CallableReferenceResolver,
val scopeTower: ImplicitScopeTower, val scopeTower: ImplicitScopeTower,
private val baseSystem: ConstraintStorage, private val baseSystem: ConstraintStorage,
@@ -182,6 +185,7 @@ class MutableResolvedCallAtom(
override lateinit var knownParametersSubstitutor: TypeSubstitutor override lateinit var knownParametersSubstitutor: TypeSubstitutor
lateinit var argumentToCandidateParameter: Map<KotlinCallArgument, ValueParameterDescriptor> lateinit var argumentToCandidateParameter: Map<KotlinCallArgument, ValueParameterDescriptor>
private var samAdapterMap: HashMap<KotlinCallArgument, SamConversionDescription>? = null private var samAdapterMap: HashMap<KotlinCallArgument, SamConversionDescription>? = null
private var signedUnsignedConstantConversions: HashMap<KotlinCallArgument, IntegerValueTypeConstant>? = null
val hasSamConversion: Boolean val hasSamConversion: Boolean
get() = samAdapterMap != null get() = samAdapterMap != null
@@ -189,6 +193,9 @@ class MutableResolvedCallAtom(
override val argumentsWithConversion: Map<KotlinCallArgument, SamConversionDescription> override val argumentsWithConversion: Map<KotlinCallArgument, SamConversionDescription>
get() = samAdapterMap ?: emptyMap() get() = samAdapterMap ?: emptyMap()
override val argumentsWithConstantConversion: Map<KotlinCallArgument, IntegerValueTypeConstant>
get() = signedUnsignedConstantConversions ?: emptyMap()
fun registerArgumentWithSamConversion(argument: KotlinCallArgument, samConversionDescription: SamConversionDescription) { fun registerArgumentWithSamConversion(argument: KotlinCallArgument, samConversionDescription: SamConversionDescription) {
if (samAdapterMap == null) if (samAdapterMap == null)
samAdapterMap = hashMapOf() samAdapterMap = hashMapOf()
@@ -196,6 +203,14 @@ class MutableResolvedCallAtom(
samAdapterMap!![argument] = samConversionDescription samAdapterMap!![argument] = samConversionDescription
} }
fun registerArgumentWithConstantConversion(argument: KotlinCallArgument, convertedConstant: IntegerValueTypeConstant) {
if (signedUnsignedConstantConversions == null)
signedUnsignedConstantConversions = hashMapOf()
signedUnsignedConstantConversions!![argument] = convertedConstant
}
override public fun setAnalyzedResults(subResolvedAtoms: List<ResolvedAtom>) { override public fun setAnalyzedResults(subResolvedAtoms: List<ResolvedAtom>) {
super.setAnalyzedResults(subResolvedAtoms) super.setAnalyzedResults(subResolvedAtoms)
} }
@@ -1,5 +1,6 @@
// !DIAGNOSTICS: -UNUSED_PARAMETER, -UNUSED_VARIABLE // !DIAGNOSTICS: -UNUSED_PARAMETER, -UNUSED_VARIABLE
// !CHECK_TYPE // !CHECK_TYPE
// !WITH_NEW_INFERENCE
// Here we mostly trying to fix behaviour in order to track changes in inference rules for unsigned types later // 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 takeUByte(u: UByte) {}
fun foo() { fun foo() {
select(1, 1u) checkType { _<Comparable<*>>() } <!NI;TYPE_MISMATCH!>select<!>(1, 1u) checkType { <!NI;UNRESOLVED_REFERENCE_WRONG_RECEIVER!>_<!><Comparable<*>>() }
takeUByte(<!TYPE_INFERENCE_EXPECTED_TYPE_MISMATCH!>id(1)<!>) takeUByte(<!NI;TYPE_MISMATCH, OI;TYPE_INFERENCE_EXPECTED_TYPE_MISMATCH!>id(1)<!>)
1 <!NONE_APPLICABLE!>+<!> 1u 1 <!NONE_APPLICABLE!>+<!> 1u
(1u + <!SIGNED_CONSTANT_CONVERTED_TO_UNSIGNED!>1<!>) checkType { _<UInt>() } (1u + <!SIGNED_CONSTANT_CONVERTED_TO_UNSIGNED!>1<!>) checkType { _<UInt>() }
id<UInt>(<!SIGNED_CONSTANT_CONVERTED_TO_UNSIGNED!>1<!>)
} }
@@ -1,4 +1,5 @@
// !DIAGNOSTICS: -UNUSED_PARAMETER // !DIAGNOSTICS: -UNUSED_PARAMETER
// !WITH_NEW_INFERENCE
fun takeUByte(u: UByte) {} fun takeUByte(u: UByte) {}
fun takeUShort(u: UShort) {} fun takeUShort(u: UShort) {}
@@ -26,7 +27,7 @@ fun test() {
takeUInt(<!SIGNED_CONSTANT_CONVERTED_TO_UNSIGNED!>1<!>) takeUInt(<!SIGNED_CONSTANT_CONVERTED_TO_UNSIGNED!>1<!>)
takeULong(<!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(<!SIGNED_CONSTANT_CONVERTED_TO_UNSIGNED!>1844674407370955161<!>)
takeULong(18446744073709551615u) takeULong(18446744073709551615u)