diff --git a/compiler/fir/fir2ir/src/org/jetbrains/kotlin/fir/backend/ConversionUtils.kt b/compiler/fir/fir2ir/src/org/jetbrains/kotlin/fir/backend/ConversionUtils.kt index 77b5a628230..a2676ac0069 100644 --- a/compiler/fir/fir2ir/src/org/jetbrains/kotlin/fir/backend/ConversionUtils.kt +++ b/compiler/fir/fir2ir/src/org/jetbrains/kotlin/fir/backend/ConversionUtils.kt @@ -277,7 +277,7 @@ private fun FirCallableSymbol<*>.toSymbolForCall( } fun FirConstExpression<*>.getIrConstKind(): IrConstKind<*> = when (kind) { - ConstantValueKind.IntegerLiteral -> { + ConstantValueKind.IntegerLiteral, ConstantValueKind.UnsignedIntegerLiteral -> { val type = typeRef.coneTypeUnsafe() type.getApproximatedType().toConstKind()!!.toIrConstKind() } diff --git a/compiler/fir/fir2ir/tests-gen/org/jetbrains/kotlin/test/runners/codegen/FirBlackBoxCodegenTestGenerated.java b/compiler/fir/fir2ir/tests-gen/org/jetbrains/kotlin/test/runners/codegen/FirBlackBoxCodegenTestGenerated.java index a1d9a07c1ed..450048ebc7d 100644 --- a/compiler/fir/fir2ir/tests-gen/org/jetbrains/kotlin/test/runners/codegen/FirBlackBoxCodegenTestGenerated.java +++ b/compiler/fir/fir2ir/tests-gen/org/jetbrains/kotlin/test/runners/codegen/FirBlackBoxCodegenTestGenerated.java @@ -41154,6 +41154,12 @@ public class FirBlackBoxCodegenTestGenerated extends AbstractFirBlackBoxCodegenT KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("compiler/testData/codegen/box/ranges/unsigned"), Pattern.compile("^(.+)\\.kt$"), null, TargetBackend.JVM_IR, true); } + @Test + @TestMetadata("bitShifting.kt") + public void testBitShifting() throws Exception { + runTest("compiler/testData/codegen/box/ranges/unsigned/bitShifting.kt"); + } + @Test @TestMetadata("inMixedUnsignedRange.kt") public void testInMixedUnsignedRange() throws Exception { diff --git a/compiler/fir/providers/src/org/jetbrains/kotlin/fir/scopes/impl/ConvertibleIntegerOperators.kt b/compiler/fir/providers/src/org/jetbrains/kotlin/fir/scopes/impl/ConvertibleIntegerOperators.kt index 6a47855f350..05982af7c95 100644 --- a/compiler/fir/providers/src/org/jetbrains/kotlin/fir/scopes/impl/ConvertibleIntegerOperators.kt +++ b/compiler/fir/providers/src/org/jetbrains/kotlin/fir/scopes/impl/ConvertibleIntegerOperators.kt @@ -19,5 +19,9 @@ object ConvertibleIntegerOperators { "inv", "unaryPlus", "unaryMinus" ).toNameSet() + val binaryOperatorsWithSignedArgument: Set = listOf( + "shl", "shr", "ushr", + ).toNameSet() + private fun List.toNameSet(): Set = mapTo(mutableSetOf()) { Name.identifier(it) } } diff --git a/compiler/fir/providers/src/org/jetbrains/kotlin/fir/scopes/impl/FirIntegerConstantOperatorScope.kt b/compiler/fir/providers/src/org/jetbrains/kotlin/fir/scopes/impl/FirIntegerConstantOperatorScope.kt index 22741b7df7a..d5d19d7c621 100644 --- a/compiler/fir/providers/src/org/jetbrains/kotlin/fir/scopes/impl/FirIntegerConstantOperatorScope.kt +++ b/compiler/fir/providers/src/org/jetbrains/kotlin/fir/scopes/impl/FirIntegerConstantOperatorScope.kt @@ -16,6 +16,7 @@ import org.jetbrains.kotlin.fir.scopes.FakeOverrideTypeCalculator import org.jetbrains.kotlin.fir.scopes.FirTypeScope import org.jetbrains.kotlin.fir.scopes.ProcessorAction import org.jetbrains.kotlin.fir.scopes.getFunctions +import org.jetbrains.kotlin.fir.scopes.impl.ConvertibleIntegerOperators.binaryOperatorsWithSignedArgument import org.jetbrains.kotlin.fir.symbols.FirBasedSymbol import org.jetbrains.kotlin.fir.symbols.impl.* import org.jetbrains.kotlin.fir.types.* @@ -46,6 +47,7 @@ class FirIntegerConstantOperatorScope( if (!isUnaryOperator && !isBinaryOperator) { return baseScope.processFunctionsByName(name, processor) } + val requiresUnsignedOperand = isUnsigned && name !in binaryOperatorsWithSignedArgument val wrappedSymbol = mappedFunctions.getOrPut(name) { val allFunctions = baseScope.getFunctions(name) val functionSymbol = allFunctions.first { @@ -53,7 +55,7 @@ class FirIntegerConstantOperatorScope( if (isUnaryOperator) return@first true val coneType = it.fir.valueParameters.first().returnTypeRef.coneType - if (isUnsigned) { + if (requiresUnsignedOperand) { coneType.isUInt } else { coneType.isInt diff --git a/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/ResolveUtils.kt b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/ResolveUtils.kt index a91913c8bc3..a4bf8972d68 100644 --- a/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/ResolveUtils.kt +++ b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/ResolveUtils.kt @@ -566,7 +566,11 @@ fun FirExpression?.isIntegerLiteralOrOperatorCall(): Boolean { returns(true) implies (this@isIntegerLiteralOrOperatorCall != null) } return when (this) { - is FirConstExpression<*> -> kind == ConstantValueKind.Int || kind == ConstantValueKind.IntegerLiteral + is FirConstExpression<*> -> kind == ConstantValueKind.Int + || kind == ConstantValueKind.IntegerLiteral + || kind == ConstantValueKind.UnsignedInt + || kind == ConstantValueKind.UnsignedIntegerLiteral + is FirIntegerLiteralOperatorCall -> true else -> false } diff --git a/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/transformers/FirCallCompletionResultsWriterTransformer.kt b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/transformers/FirCallCompletionResultsWriterTransformer.kt index 5f18e6a2888..a2dad2e1aaa 100644 --- a/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/transformers/FirCallCompletionResultsWriterTransformer.kt +++ b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/transformers/FirCallCompletionResultsWriterTransformer.kt @@ -36,6 +36,7 @@ import org.jetbrains.kotlin.fir.resolve.transformers.body.resolve.FirArrayOfCall import org.jetbrains.kotlin.fir.resolve.transformers.body.resolve.remapArgumentsWithVararg import org.jetbrains.kotlin.fir.resolve.transformers.body.resolve.resultType import org.jetbrains.kotlin.fir.resolve.transformers.body.resolve.writeResultType +import org.jetbrains.kotlin.fir.scopes.impl.ConvertibleIntegerOperators.binaryOperatorsWithSignedArgument import org.jetbrains.kotlin.fir.scopes.impl.isWrappedIntegerOperator import org.jetbrains.kotlin.fir.scopes.impl.isWrappedIntegerOperatorForUnsignedType import org.jetbrains.kotlin.fir.symbols.FirBasedSymbol @@ -469,7 +470,7 @@ class FirCallCompletionResultsWriterTransformer( val arguments = argumentMapping?.map { (argument, valueParameter) -> val expectedType = when { isIntegerOperator -> ConeIntegerConstantOperatorTypeImpl( - isUnsigned = symbol.isWrappedIntegerOperatorForUnsignedType(), + isUnsigned = symbol.isWrappedIntegerOperatorForUnsignedType() && callInfo.name in binaryOperatorsWithSignedArgument, ConeNullability.NOT_NULL ) valueParameter.isVararg -> valueParameter.returnTypeRef.substitute(this).varargElementType() diff --git a/compiler/testData/codegen/box/ranges/unsigned/bitShifting.kt b/compiler/testData/codegen/box/ranges/unsigned/bitShifting.kt new file mode 100644 index 00000000000..35e8ce8388c --- /dev/null +++ b/compiler/testData/codegen/box/ranges/unsigned/bitShifting.kt @@ -0,0 +1,25 @@ +// WITH_STDLIB + +fun test(): Int { + return 1 shl 12 +} + +fun rest(): UInt { + return 1u shl 20 +} + +fun fest(): Long { + return 1L shl 12 +} + +fun mest(): ULong { + return 1uL shl 20 +} + +fun box(): String = when { + test() != 4096 -> "fail: test" + rest() != 1_048_576u -> "fail: rest" + fest() != 4096L -> "fail: fest" + mest() != 1_048_576uL -> "fail: mest" + else -> "OK" +} diff --git a/compiler/tests-common-new/tests-gen/org/jetbrains/kotlin/test/runners/codegen/BlackBoxCodegenTestGenerated.java b/compiler/tests-common-new/tests-gen/org/jetbrains/kotlin/test/runners/codegen/BlackBoxCodegenTestGenerated.java index a418032460b..7d3532da3cf 100644 --- a/compiler/tests-common-new/tests-gen/org/jetbrains/kotlin/test/runners/codegen/BlackBoxCodegenTestGenerated.java +++ b/compiler/tests-common-new/tests-gen/org/jetbrains/kotlin/test/runners/codegen/BlackBoxCodegenTestGenerated.java @@ -39678,6 +39678,12 @@ public class BlackBoxCodegenTestGenerated extends AbstractBlackBoxCodegenTest { KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("compiler/testData/codegen/box/ranges/unsigned"), Pattern.compile("^(.+)\\.kt$"), null, TargetBackend.JVM, true); } + @Test + @TestMetadata("bitShifting.kt") + public void testBitShifting() throws Exception { + runTest("compiler/testData/codegen/box/ranges/unsigned/bitShifting.kt"); + } + @Test @TestMetadata("inMixedUnsignedRange.kt") public void testInMixedUnsignedRange() throws Exception { diff --git a/compiler/tests-common-new/tests-gen/org/jetbrains/kotlin/test/runners/codegen/IrBlackBoxCodegenTestGenerated.java b/compiler/tests-common-new/tests-gen/org/jetbrains/kotlin/test/runners/codegen/IrBlackBoxCodegenTestGenerated.java index f0bd1bed940..401d8ea98db 100644 --- a/compiler/tests-common-new/tests-gen/org/jetbrains/kotlin/test/runners/codegen/IrBlackBoxCodegenTestGenerated.java +++ b/compiler/tests-common-new/tests-gen/org/jetbrains/kotlin/test/runners/codegen/IrBlackBoxCodegenTestGenerated.java @@ -41154,6 +41154,12 @@ public class IrBlackBoxCodegenTestGenerated extends AbstractIrBlackBoxCodegenTes KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("compiler/testData/codegen/box/ranges/unsigned"), Pattern.compile("^(.+)\\.kt$"), null, TargetBackend.JVM_IR, true); } + @Test + @TestMetadata("bitShifting.kt") + public void testBitShifting() throws Exception { + runTest("compiler/testData/codegen/box/ranges/unsigned/bitShifting.kt"); + } + @Test @TestMetadata("inMixedUnsignedRange.kt") public void testInMixedUnsignedRange() throws Exception { diff --git a/compiler/tests-gen/org/jetbrains/kotlin/codegen/LightAnalysisModeTestGenerated.java b/compiler/tests-gen/org/jetbrains/kotlin/codegen/LightAnalysisModeTestGenerated.java index bca64e3f8df..bdcac1e3356 100644 --- a/compiler/tests-gen/org/jetbrains/kotlin/codegen/LightAnalysisModeTestGenerated.java +++ b/compiler/tests-gen/org/jetbrains/kotlin/codegen/LightAnalysisModeTestGenerated.java @@ -31595,6 +31595,11 @@ public class LightAnalysisModeTestGenerated extends AbstractLightAnalysisModeTes KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("compiler/testData/codegen/box/ranges/unsigned"), Pattern.compile("^(.+)\\.kt$"), null, TargetBackend.JVM, true); } + @TestMetadata("bitShifting.kt") + public void testBitShifting() throws Exception { + runTest("compiler/testData/codegen/box/ranges/unsigned/bitShifting.kt"); + } + @TestMetadata("inMixedUnsignedRange.kt") public void testInMixedUnsignedRange() throws Exception { runTest("compiler/testData/codegen/box/ranges/unsigned/inMixedUnsignedRange.kt"); diff --git a/js/js.tests/tests-gen/org/jetbrains/kotlin/js/test/JsCodegenBoxTestGenerated.java b/js/js.tests/tests-gen/org/jetbrains/kotlin/js/test/JsCodegenBoxTestGenerated.java index 1b39c3c3472..7e94f45bc35 100644 --- a/js/js.tests/tests-gen/org/jetbrains/kotlin/js/test/JsCodegenBoxTestGenerated.java +++ b/js/js.tests/tests-gen/org/jetbrains/kotlin/js/test/JsCodegenBoxTestGenerated.java @@ -30752,6 +30752,12 @@ public class JsCodegenBoxTestGenerated extends AbstractJsCodegenBoxTest { KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("compiler/testData/codegen/box/ranges/unsigned"), Pattern.compile("^(.+)\\.kt$"), null, TargetBackend.JS, true); } + @Test + @TestMetadata("bitShifting.kt") + public void testBitShifting() throws Exception { + runTest("compiler/testData/codegen/box/ranges/unsigned/bitShifting.kt"); + } + @Test @TestMetadata("inMixedUnsignedRange.kt") public void testInMixedUnsignedRange() throws Exception { diff --git a/js/js.tests/tests-gen/org/jetbrains/kotlin/js/test/ir/IrJsCodegenBoxTestGenerated.java b/js/js.tests/tests-gen/org/jetbrains/kotlin/js/test/ir/IrJsCodegenBoxTestGenerated.java index 7bae7d31194..2d4d1b2dc9d 100644 --- a/js/js.tests/tests-gen/org/jetbrains/kotlin/js/test/ir/IrJsCodegenBoxTestGenerated.java +++ b/js/js.tests/tests-gen/org/jetbrains/kotlin/js/test/ir/IrJsCodegenBoxTestGenerated.java @@ -30932,6 +30932,12 @@ public class IrJsCodegenBoxTestGenerated extends AbstractIrJsCodegenBoxTest { KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("compiler/testData/codegen/box/ranges/unsigned"), Pattern.compile("^(.+)\\.kt$"), null, TargetBackend.JS_IR, true); } + @Test + @TestMetadata("bitShifting.kt") + public void testBitShifting() throws Exception { + runTest("compiler/testData/codegen/box/ranges/unsigned/bitShifting.kt"); + } + @Test @TestMetadata("inMixedUnsignedRange.kt") public void testInMixedUnsignedRange() throws Exception { diff --git a/js/js.tests/tests-gen/org/jetbrains/kotlin/js/testOld/wasm/semantics/IrCodegenBoxWasmTestGenerated.java b/js/js.tests/tests-gen/org/jetbrains/kotlin/js/testOld/wasm/semantics/IrCodegenBoxWasmTestGenerated.java index a52a0cf3125..f7001ac0c1b 100644 --- a/js/js.tests/tests-gen/org/jetbrains/kotlin/js/testOld/wasm/semantics/IrCodegenBoxWasmTestGenerated.java +++ b/js/js.tests/tests-gen/org/jetbrains/kotlin/js/testOld/wasm/semantics/IrCodegenBoxWasmTestGenerated.java @@ -27640,6 +27640,11 @@ public class IrCodegenBoxWasmTestGenerated extends AbstractIrCodegenBoxWasmTest KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("compiler/testData/codegen/box/ranges/unsigned"), Pattern.compile("^([^_](.+))\\.kt$"), null, TargetBackend.WASM, true); } + @TestMetadata("bitShifting.kt") + public void testBitShifting() throws Exception { + runTest("compiler/testData/codegen/box/ranges/unsigned/bitShifting.kt"); + } + @TestMetadata("inMixedUnsignedRange.kt") public void testInMixedUnsignedRange() throws Exception { runTest("compiler/testData/codegen/box/ranges/unsigned/inMixedUnsignedRange.kt"); diff --git a/native/native.tests/tests-gen/org/jetbrains/kotlin/konan/blackboxtest/NativeCodegenBoxTestGenerated.java b/native/native.tests/tests-gen/org/jetbrains/kotlin/konan/blackboxtest/NativeCodegenBoxTestGenerated.java index c28bb1ffac8..76b7d046e01 100644 --- a/native/native.tests/tests-gen/org/jetbrains/kotlin/konan/blackboxtest/NativeCodegenBoxTestGenerated.java +++ b/native/native.tests/tests-gen/org/jetbrains/kotlin/konan/blackboxtest/NativeCodegenBoxTestGenerated.java @@ -33911,6 +33911,12 @@ public class NativeCodegenBoxTestGenerated extends AbstractNativeCodegenBoxTest KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("compiler/testData/codegen/box/ranges/unsigned"), Pattern.compile("^(.+)\\.kt$"), null, TargetBackend.NATIVE, true); } + @Test + @TestMetadata("bitShifting.kt") + public void testBitShifting() throws Exception { + runTest("compiler/testData/codegen/box/ranges/unsigned/bitShifting.kt"); + } + @Test @TestMetadata("inMixedUnsignedRange.kt") public void testInMixedUnsignedRange() throws Exception {