diff --git a/core/descriptors/src/org/jetbrains/kotlin/resolve/constants/CompileTimeConstant.kt b/core/descriptors/src/org/jetbrains/kotlin/resolve/constants/CompileTimeConstant.kt index 2cd9ecc7b58..bc8ad78b081 100644 --- a/core/descriptors/src/org/jetbrains/kotlin/resolve/constants/CompileTimeConstant.kt +++ b/core/descriptors/src/org/jetbrains/kotlin/resolve/constants/CompileTimeConstant.kt @@ -138,6 +138,20 @@ class IntegerValueTypeConstant( return IntegerValueTypeConstant(value, module, newParameters, convertedFromSigned = true) } + + fun IntegerValueTypeConstant.convertToSignedConstant(module: ModuleDescriptor): IntegerValueTypeConstant { + val newParameters = CompileTimeConstant.Parameters( + parameters.canBeUsedInAnnotation, + parameters.isPure, + isUnsignedNumberLiteral = false, + isUnsignedLongNumberLiteral = parameters.isUnsignedLongNumberLiteral, + usesVariableAsConstant = parameters.usesVariableAsConstant, + usesNonConstValAsConstant = parameters.usesNonConstValAsConstant, + isConvertableConstVal = parameters.isConvertableConstVal + ) + + return IntegerValueTypeConstant(value, module, newParameters, convertedFromSigned = true) + } } private val typeConstructor = IntegerValueTypeConstructor(value.toLong(), module, parameters) diff --git a/idea/src/org/jetbrains/kotlin/idea/quickfix/QuickFixFactoryForTypeMismatchError.kt b/idea/src/org/jetbrains/kotlin/idea/quickfix/QuickFixFactoryForTypeMismatchError.kt index 7f395cd2988..62b26c31e01 100644 --- a/idea/src/org/jetbrains/kotlin/idea/quickfix/QuickFixFactoryForTypeMismatchError.kt +++ b/idea/src/org/jetbrains/kotlin/idea/quickfix/QuickFixFactoryForTypeMismatchError.kt @@ -26,6 +26,7 @@ import org.jetbrains.kotlin.diagnostics.Diagnostic import org.jetbrains.kotlin.diagnostics.Errors import org.jetbrains.kotlin.diagnostics.rendering.DefaultErrorMessages import org.jetbrains.kotlin.idea.caches.resolve.analyzeWithContent +import org.jetbrains.kotlin.idea.caches.resolve.findModuleDescriptor import org.jetbrains.kotlin.idea.caches.resolve.getResolutionFacade import org.jetbrains.kotlin.idea.core.quickfix.QuickFixUtil import org.jetbrains.kotlin.idea.util.approximateWithResolvableType @@ -34,6 +35,7 @@ import org.jetbrains.kotlin.name.FqName import org.jetbrains.kotlin.psi.* import org.jetbrains.kotlin.psi.psiUtil.getQualifiedExpressionForSelectorOrThis import org.jetbrains.kotlin.psi.psiUtil.getStrictParentOfType +import org.jetbrains.kotlin.resolve.BindingContext import org.jetbrains.kotlin.resolve.DescriptorToSourceUtils import org.jetbrains.kotlin.resolve.bindingContextUtil.getTargetFunction import org.jetbrains.kotlin.resolve.calls.callUtil.getParameterForArgument @@ -41,10 +43,12 @@ import org.jetbrains.kotlin.resolve.calls.callUtil.getParentResolvedCall import org.jetbrains.kotlin.resolve.calls.callUtil.getResolvedCall import org.jetbrains.kotlin.resolve.calls.callUtil.getValueArgumentForExpression import org.jetbrains.kotlin.resolve.calls.model.ResolvedCall +import org.jetbrains.kotlin.resolve.constants.IntegerValueTypeConstant import org.jetbrains.kotlin.resolve.descriptorUtil.fqNameSafe import org.jetbrains.kotlin.types.KotlinType import org.jetbrains.kotlin.types.KotlinTypeFactory import org.jetbrains.kotlin.types.TypeUtils +import org.jetbrains.kotlin.types.TypeUtils.NO_EXPECTED_TYPE import org.jetbrains.kotlin.types.typeUtil.* import java.util.* @@ -90,16 +94,28 @@ class QuickFixFactoryForTypeMismatchError : KotlinIntentionActionsFactory() { val diagnosticWithParameters = Errors.CONSTANT_EXPECTED_TYPE_MISMATCH.cast(diagnostic) expectedType = diagnosticWithParameters.b expressionType = context.getType(diagnosticElement) - if (expressionType == null) { - LOG.error("No type inferred: " + diagnosticElement.text) - return emptyList() - } + } + Errors.SIGNED_CONSTANT_CONVERTED_TO_UNSIGNED -> { + val constantValue = context[BindingContext.COMPILE_TIME_VALUE, diagnosticElement] + if (constantValue is IntegerValueTypeConstant) { + // Here we have unsigned type (despite really constant is signed) + expectedType = constantValue.getType(NO_EXPECTED_TYPE) + val signedConstantValue = with(IntegerValueTypeConstant) { + constantValue.convertToSignedConstant(diagnosticElement.findModuleDescriptor()) + } + // And here we have signed type + expressionType = signedConstantValue.getType(NO_EXPECTED_TYPE) + } else return emptyList() } else -> { LOG.error("Unexpected diagnostic: " + DefaultErrorMessages.render(diagnostic)) return emptyList() } } + if (expressionType == null) { + LOG.error("No type inferred: " + diagnosticElement.text) + return emptyList() + } if (expressionType.isPrimitiveNumberType() && expectedType.isPrimitiveNumberType()) { var wrongPrimitiveLiteralFix: WrongPrimitiveLiteralFix? = null @@ -240,10 +256,10 @@ class QuickFixFactoryForTypeMismatchError : KotlinIntentionActionsFactory() { val correspondingParameterDescriptor = resolvedCall.getParameterForArgument(valueArgument) val correspondingParameter = QuickFixUtil.safeGetDeclaration(correspondingParameterDescriptor) as? KtParameter val expressionFromArgument = valueArgument.getArgumentExpression() - val valueArgumentType = if (diagnostic.factory === Errors.NULL_FOR_NONNULL_TYPE) - expressionType - else - expressionFromArgument?.let { context.getType(it) } + val valueArgumentType = when (diagnostic.factory) { + Errors.NULL_FOR_NONNULL_TYPE, Errors.SIGNED_CONSTANT_CONVERTED_TO_UNSIGNED -> expressionType + else -> expressionFromArgument?.let { context.getType(it) } + } if (valueArgumentType != null) { if (correspondingParameter != null) { val callable = PsiTreeUtil.getParentOfType(correspondingParameter, KtCallableDeclaration::class.java, true) diff --git a/idea/src/org/jetbrains/kotlin/idea/quickfix/QuickFixRegistrar.kt b/idea/src/org/jetbrains/kotlin/idea/quickfix/QuickFixRegistrar.kt index 7a060a38642..511025742ad 100644 --- a/idea/src/org/jetbrains/kotlin/idea/quickfix/QuickFixRegistrar.kt +++ b/idea/src/org/jetbrains/kotlin/idea/quickfix/QuickFixRegistrar.kt @@ -370,6 +370,7 @@ class QuickFixRegistrar : QuickFixContributor { NULL_FOR_NONNULL_TYPE.registerFactory(factoryForTypeMismatchError) CONSTANT_EXPECTED_TYPE_MISMATCH.registerFactory(factoryForTypeMismatchError) TYPE_INFERENCE_EXPECTED_TYPE_MISMATCH.registerFactory(factoryForTypeMismatchError) + SIGNED_CONSTANT_CONVERTED_TO_UNSIGNED.registerFactory(factoryForTypeMismatchError) SMARTCAST_IMPOSSIBLE.registerFactory(SmartCastImpossibleExclExclFixFactory) SMARTCAST_IMPOSSIBLE.registerFactory(CastExpressionFix.SmartCastImpossibleFactory) diff --git a/idea/testData/quickfix/typeMismatch/parameterTypeMismatch/unsigned.kt b/idea/testData/quickfix/typeMismatch/parameterTypeMismatch/unsigned.kt new file mode 100644 index 00000000000..cf70d0a8428 --- /dev/null +++ b/idea/testData/quickfix/typeMismatch/parameterTypeMismatch/unsigned.kt @@ -0,0 +1,6 @@ +// "Change parameter 'u' type of function 'takeUInt' to 'Int'" "true" +// WITH_RUNTIME + +fun takeUInt(u: UInt) = 0 + +val b = takeUInt(1) \ No newline at end of file diff --git a/idea/testData/quickfix/typeMismatch/parameterTypeMismatch/unsigned.kt.after b/idea/testData/quickfix/typeMismatch/parameterTypeMismatch/unsigned.kt.after new file mode 100644 index 00000000000..c34a706dbad --- /dev/null +++ b/idea/testData/quickfix/typeMismatch/parameterTypeMismatch/unsigned.kt.after @@ -0,0 +1,6 @@ +// "Change parameter 'u' type of function 'takeUInt' to 'Int'" "true" +// WITH_RUNTIME + +fun takeUInt(u: Int) = 0 + +val b = takeUInt(1) \ No newline at end of file diff --git a/idea/tests/org/jetbrains/kotlin/idea/quickfix/QuickFixTestGenerated.java b/idea/tests/org/jetbrains/kotlin/idea/quickfix/QuickFixTestGenerated.java index 3a0260693aa..5c8b4146e52 100644 --- a/idea/tests/org/jetbrains/kotlin/idea/quickfix/QuickFixTestGenerated.java +++ b/idea/tests/org/jetbrains/kotlin/idea/quickfix/QuickFixTestGenerated.java @@ -12531,6 +12531,11 @@ public class QuickFixTestGenerated extends AbstractQuickFixTest { public void testMultiFakeOverride() throws Exception { runTest("idea/testData/quickfix/typeMismatch/parameterTypeMismatch/multiFakeOverride.kt"); } + + @TestMetadata("unsigned.kt") + public void testUnsigned() throws Exception { + runTest("idea/testData/quickfix/typeMismatch/parameterTypeMismatch/unsigned.kt"); + } } @TestMetadata("idea/testData/quickfix/typeMismatch/typeMismatchOnReturnedExpression")