summary refs log tree commit diff stats
diff options
context:
space:
mode:
-rw-r--r--changelog.md1
-rw-r--r--compiler/condsyms.nim1
-rw-r--r--lib/system.nim193
-rw-r--r--tests/arithm/tarithm.nim22
-rw-r--r--tests/concepts/t3330.nim14
-rw-r--r--tests/errmsgs/twrong_at_operator.nim8
-rw-r--r--tests/generics/tgenerics_issues.nim8
-rw-r--r--tests/pragmas/t6448.nim3
8 files changed, 151 insertions, 99 deletions
diff --git a/changelog.md b/changelog.md
index 7381e6697..681d5166d 100644
--- a/changelog.md
+++ b/changelog.md
@@ -30,6 +30,7 @@
 
 ## Language changes
 
+- Unsigned integer operators have been fixed to allow promotion of the first operand.
 
 
 ### Tool changes
diff --git a/compiler/condsyms.nim b/compiler/condsyms.nim
index a4dd25045..dd4ad3b3a 100644
--- a/compiler/condsyms.nim
+++ b/compiler/condsyms.nim
@@ -53,7 +53,6 @@ proc initDefines*(symbols: StringTableRef) =
   defineSymbol("nimKnowsNimvm")
   defineSymbol("nimArrIdx")
   defineSymbol("nimHasalignOf")
-  defineSymbol("nimNewShiftOps")
   defineSymbol("nimDistros")
   defineSymbol("nimHasCppDefine")
   defineSymbol("nimGenericInOutFlags")
diff --git a/lib/system.nim b/lib/system.nim
index 9158b6153..fdbd91c2f 100644
--- a/lib/system.nim
+++ b/lib/system.nim
@@ -1323,65 +1323,51 @@ proc `mod`*(x, y: int16): int16 {.magic: "ModI", noSideEffect.}
 proc `mod`*(x, y: int32): int32 {.magic: "ModI", noSideEffect.}
 proc `mod`*(x, y: int64): int64 {.magic: "ModI", noSideEffect.}
 
-when defined(nimNewShiftOps):
-
-  when defined(nimOldShiftRight) or not defined(nimAshr):
-    const shrDepMessage = "`shr` will become sign preserving."
-    proc `shr`*(x: int, y: SomeInteger): int {.magic: "ShrI", noSideEffect, deprecated: shrDepMessage.}
-    proc `shr`*(x: int8, y: SomeInteger): int8 {.magic: "ShrI", noSideEffect, deprecated: shrDepMessage.}
-    proc `shr`*(x: int16, y: SomeInteger): int16 {.magic: "ShrI", noSideEffect, deprecated: shrDepMessage.}
-    proc `shr`*(x: int32, y: SomeInteger): int32 {.magic: "ShrI", noSideEffect, deprecated: shrDepMessage.}
-    proc `shr`*(x: int64, y: SomeInteger): int64 {.magic: "ShrI", noSideEffect, deprecated: shrDepMessage.}
-  else:
-    proc `shr`*(x: int, y: SomeInteger): int {.magic: "AshrI", noSideEffect.}
-      ## Computes the `shift right` operation of `x` and `y`, filling
-      ## vacant bit positions with the sign bit.
-      ##
-      ## **Note**: `Operator precedence <manual.html#syntax-precedence>`_
-      ## is different than in *C*.
-      ##
-      ## See also:
-      ## * `ashr proc <#ashr,int,SomeInteger>`_ for arithmetic shift right
-      ##
-      ## .. code-block:: Nim
-      ##   0b0001_0000'i8 shr 2 == 0b0000_0100'i8
-      ##   0b0000_0001'i8 shr 1 == 0b0000_0000'i8
-      ##   0b1000_0000'i8 shr 4 == 0b1111_1000'i8
-      ##   -1 shr 5 == -1
-      ##   1 shr 5 == 0
-      ##   16 shr 2 == 4
-      ##   -16 shr 2 == -4
-    proc `shr`*(x: int8, y: SomeInteger): int8 {.magic: "AshrI", noSideEffect.}
-    proc `shr`*(x: int16, y: SomeInteger): int16 {.magic: "AshrI", noSideEffect.}
-    proc `shr`*(x: int32, y: SomeInteger): int32 {.magic: "AshrI", noSideEffect.}
-    proc `shr`*(x: int64, y: SomeInteger): int64 {.magic: "AshrI", noSideEffect.}
-
-
-  proc `shl`*(x: int, y: SomeInteger): int {.magic: "ShlI", noSideEffect.}
-    ## Computes the `shift left` operation of `x` and `y`.
+when defined(nimOldShiftRight) or not defined(nimAshr):
+  const shrDepMessage = "`shr` will become sign preserving."
+  proc `shr`*(x: int, y: SomeInteger): int {.magic: "ShrI", noSideEffect, deprecated: shrDepMessage.}
+  proc `shr`*(x: int8, y: SomeInteger): int8 {.magic: "ShrI", noSideEffect, deprecated: shrDepMessage.}
+  proc `shr`*(x: int16, y: SomeInteger): int16 {.magic: "ShrI", noSideEffect, deprecated: shrDepMessage.}
+  proc `shr`*(x: int32, y: SomeInteger): int32 {.magic: "ShrI", noSideEffect, deprecated: shrDepMessage.}
+  proc `shr`*(x: int64, y: SomeInteger): int64 {.magic: "ShrI", noSideEffect, deprecated: shrDepMessage.}
+else:
+  proc `shr`*(x: int, y: SomeInteger): int {.magic: "AshrI", noSideEffect.}
+    ## Computes the `shift right` operation of `x` and `y`, filling
+    ## vacant bit positions with the sign bit.
     ##
     ## **Note**: `Operator precedence <manual.html#syntax-precedence>`_
     ## is different than in *C*.
     ##
+    ## See also:
+    ## * `ashr proc <#ashr,int,SomeInteger>`_ for arithmetic shift right
+    ##
     ## .. code-block:: Nim
-    ##  1'i32 shl 4 == 0x0000_0010
-    ##  1'i64 shl 4 == 0x0000_0000_0000_0010
-  proc `shl`*(x: int8, y: SomeInteger): int8 {.magic: "ShlI", noSideEffect.}
-  proc `shl`*(x: int16, y: SomeInteger): int16 {.magic: "ShlI", noSideEffect.}
-  proc `shl`*(x: int32, y: SomeInteger): int32 {.magic: "ShlI", noSideEffect.}
-  proc `shl`*(x: int64, y: SomeInteger): int64 {.magic: "ShlI", noSideEffect.}
-else:
-  proc `shr`*(x, y: int): int {.magic: "ShrI", noSideEffect.}
-  proc `shr`*(x, y: int8): int8 {.magic: "ShrI", noSideEffect.}
-  proc `shr`*(x, y: int16): int16 {.magic: "ShrI", noSideEffect.}
-  proc `shr`*(x, y: int32): int32 {.magic: "ShrI", noSideEffect.}
-  proc `shr`*(x, y: int64): int64 {.magic: "ShrI", noSideEffect.}
-
-  proc `shl`*(x, y: int): int {.magic: "ShlI", noSideEffect.}
-  proc `shl`*(x, y: int8): int8 {.magic: "ShlI", noSideEffect.}
-  proc `shl`*(x, y: int16): int16 {.magic: "ShlI", noSideEffect.}
-  proc `shl`*(x, y: int32): int32 {.magic: "ShlI", noSideEffect.}
-  proc `shl`*(x, y: int64): int64 {.magic: "ShlI", noSideEffect.}
+    ##   0b0001_0000'i8 shr 2 == 0b0000_0100'i8
+    ##   0b0000_0001'i8 shr 1 == 0b0000_0000'i8
+    ##   0b1000_0000'i8 shr 4 == 0b1111_1000'i8
+    ##   -1 shr 5 == -1
+    ##   1 shr 5 == 0
+    ##   16 shr 2 == 4
+    ##   -16 shr 2 == -4
+  proc `shr`*(x: int8, y: SomeInteger): int8 {.magic: "AshrI", noSideEffect.}
+  proc `shr`*(x: int16, y: SomeInteger): int16 {.magic: "AshrI", noSideEffect.}
+  proc `shr`*(x: int32, y: SomeInteger): int32 {.magic: "AshrI", noSideEffect.}
+  proc `shr`*(x: int64, y: SomeInteger): int64 {.magic: "AshrI", noSideEffect.}
+
+
+proc `shl`*(x: int, y: SomeInteger): int {.magic: "ShlI", noSideEffect.}
+  ## Computes the `shift left` operation of `x` and `y`.
+  ##
+  ## **Note**: `Operator precedence <manual.html#syntax-precedence>`_
+  ## is different than in *C*.
+  ##
+  ## .. code-block:: Nim
+  ##  1'i32 shl 4 == 0x0000_0010
+  ##  1'i64 shl 4 == 0x0000_0000_0000_0010
+proc `shl`*(x: int8, y: SomeInteger): int8 {.magic: "ShlI", noSideEffect.}
+proc `shl`*(x: int16, y: SomeInteger): int16 {.magic: "ShlI", noSideEffect.}
+proc `shl`*(x: int32, y: SomeInteger): int32 {.magic: "ShlI", noSideEffect.}
+proc `shl`*(x: int64, y: SomeInteger): int64 {.magic: "ShlI", noSideEffect.}
 
 when defined(nimAshr):
   proc ashr*(x: int, y: SomeInteger): int {.magic: "AshrI", noSideEffect.}
@@ -1518,54 +1504,105 @@ template `>%`*(x, y: untyped): untyped = y <% x
 
 
 # unsigned integer operations:
-proc `not`*[T: SomeUnsignedInt](x: T): T {.magic: "BitnotI", noSideEffect.}
+proc `not`*(x: uint): uint {.magic: "BitnotI", noSideEffect.}
   ## Computes the `bitwise complement` of the integer `x`.
-
-when defined(nimNewShiftOps):
-  proc `shr`*[T: SomeUnsignedInt](x: T, y: SomeInteger): T {.magic: "ShrI", noSideEffect.}
-    ## Computes the `shift right` operation of `x` and `y`.
-  proc `shl`*[T: SomeUnsignedInt](x: T, y: SomeInteger): T {.magic: "ShlI", noSideEffect.}
-    ## Computes the `shift left` operation of `x` and `y`.
-else:
-  proc `shr`*[T: SomeUnsignedInt](x, y: T): T {.magic: "ShrI", noSideEffect.}
-    ## Computes the `shift right` operation of `x` and `y`.
-  proc `shl`*[T: SomeUnsignedInt](x, y: T): T {.magic: "ShlI", noSideEffect.}
-    ## Computes the `shift left` operation of `x` and `y`.
-
-proc `and`*[T: SomeUnsignedInt](x, y: T): T {.magic: "BitandI", noSideEffect.}
+proc `not`*(x: uint8): uint8 {.magic: "BitnotI", noSideEffect.}
+proc `not`*(x: uint16): uint16 {.magic: "BitnotI", noSideEffect.}
+proc `not`*(x: uint32): uint32 {.magic: "BitnotI", noSideEffect.}
+proc `not`*(x: uint64): uint64 {.magic: "BitnotI", noSideEffect.}
+
+proc `shr`*(x: uint, y: SomeInteger): uint {.magic: "ShrI", noSideEffect.}
+  ## Computes the `shift right` operation of `x` and `y`.
+proc `shr`*(x: uint8, y: SomeInteger): uint8 {.magic: "ShrI", noSideEffect.}
+proc `shr`*(x: uint16, y: SomeInteger): uint16 {.magic: "ShrI", noSideEffect.}
+proc `shr`*(x: uint32, y: SomeInteger): uint32 {.magic: "ShrI", noSideEffect.}
+proc `shr`*(x: uint64, y: SomeInteger): uint64 {.magic: "ShrI", noSideEffect.}
+
+proc `shl`*(x: uint, y: SomeInteger): uint {.magic: "ShlI", noSideEffect.}
+  ## Computes the `shift left` operation of `x` and `y`.
+proc `shl`*(x: uint8, y: SomeInteger): uint8 {.magic: "ShlI", noSideEffect.}
+proc `shl`*(x: uint16, y: SomeInteger): uint16 {.magic: "ShlI", noSideEffect.}
+proc `shl`*(x: uint32, y: SomeInteger): uint32 {.magic: "ShlI", noSideEffect.}
+proc `shl`*(x: uint64, y: SomeInteger): uint64 {.magic: "ShlI", noSideEffect.}
+
+proc `and`*(x, y: uint): uint {.magic: "BitandI", noSideEffect.}
   ## Computes the `bitwise and` of numbers `x` and `y`.
+proc `and`*(x, y: uint8): uint8 {.magic: "BitandI", noSideEffect.}
+proc `and`*(x, y: uint16): uint16 {.magic: "BitandI", noSideEffect.}
+proc `and`*(x, y: uint32): uint32 {.magic: "BitandI", noSideEffect.}
+proc `and`*(x, y: uint64): uint64 {.magic: "BitandI", noSideEffect.}
 
-proc `or`*[T: SomeUnsignedInt](x, y: T): T {.magic: "BitorI", noSideEffect.}
+proc `or`*(x, y: uint): uint {.magic: "BitorI", noSideEffect.}
   ## Computes the `bitwise or` of numbers `x` and `y`.
+proc `or`*(x, y: uint8): uint8 {.magic: "BitorI", noSideEffect.}
+proc `or`*(x, y: uint16): uint16 {.magic: "BitorI", noSideEffect.}
+proc `or`*(x, y: uint32): uint32 {.magic: "BitorI", noSideEffect.}
+proc `or`*(x, y: uint64): uint64 {.magic: "BitorI", noSideEffect.}
 
-proc `xor`*[T: SomeUnsignedInt](x, y: T): T {.magic: "BitxorI", noSideEffect.}
+proc `xor`*(x, y: uint): uint {.magic: "BitxorI", noSideEffect.}
   ## Computes the `bitwise xor` of numbers `x` and `y`.
+proc `xor`*(x, y: uint8): uint8 {.magic: "BitxorI", noSideEffect.}
+proc `xor`*(x, y: uint16): uint16 {.magic: "BitxorI", noSideEffect.}
+proc `xor`*(x, y: uint32): uint32 {.magic: "BitxorI", noSideEffect.}
+proc `xor`*(x, y: uint64): uint64 {.magic: "BitxorI", noSideEffect.}
 
-proc `==`*[T: SomeUnsignedInt](x, y: T): bool {.magic: "EqI", noSideEffect.}
+proc `==`*(x, y: uint): bool {.magic: "EqI", noSideEffect.}
   ## Compares two unsigned integers for equality.
+proc `==`*(x, y: uint8): bool {.magic: "EqI", noSideEffect.}
+proc `==`*(x, y: uint16): bool {.magic: "EqI", noSideEffect.}
+proc `==`*(x, y: uint32): bool {.magic: "EqI", noSideEffect.}
+proc `==`*(x, y: uint64): bool {.magic: "EqI", noSideEffect.}
 
-proc `+`*[T: SomeUnsignedInt](x, y: T): T {.magic: "AddU", noSideEffect.}
+proc `+`*(x, y: uint): uint {.magic: "AddU", noSideEffect.}
   ## Binary `+` operator for unsigned integers.
+proc `+`*(x, y: uint8): uint8 {.magic: "AddU", noSideEffect.}
+proc `+`*(x, y: uint16): uint16 {.magic: "AddU", noSideEffect.}
+proc `+`*(x, y: uint32): uint32 {.magic: "AddU", noSideEffect.}
+proc `+`*(x, y: uint64): uint64 {.magic: "AddU", noSideEffect.}
 
-proc `-`*[T: SomeUnsignedInt](x, y: T): T {.magic: "SubU", noSideEffect.}
+proc `-`*(x, y: uint): uint {.magic: "SubU", noSideEffect.}
   ## Binary `-` operator for unsigned integers.
+proc `-`*(x, y: uint8): uint8 {.magic: "SubU", noSideEffect.}
+proc `-`*(x, y: uint16): uint16 {.magic: "SubU", noSideEffect.}
+proc `-`*(x, y: uint32): uint32 {.magic: "SubU", noSideEffect.}
+proc `-`*(x, y: uint64): uint64 {.magic: "SubU", noSideEffect.}
 
-proc `*`*[T: SomeUnsignedInt](x, y: T): T {.magic: "MulU", noSideEffect.}
+proc `*`*(x, y: uint): uint {.magic: "MulU", noSideEffect.}
   ## Binary `*` operator for unsigned integers.
+proc `*`*(x, y: uint8): uint8 {.magic: "MulU", noSideEffect.}
+proc `*`*(x, y: uint16): uint16 {.magic: "MulU", noSideEffect.}
+proc `*`*(x, y: uint32): uint32 {.magic: "MulU", noSideEffect.}
+proc `*`*(x, y: uint64): uint64 {.magic: "MulU", noSideEffect.}
 
-proc `div`*[T: SomeUnsignedInt](x, y: T): T {.magic: "DivU", noSideEffect.}
+proc `div`*(x, y: uint): uint {.magic: "DivU", noSideEffect.}
   ## Computes the integer division for unsigned integers.
   ## This is roughly the same as ``trunc(x/y)``.
+proc `div`*(x, y: uint8): uint8 {.magic: "DivU", noSideEffect.}
+proc `div`*(x, y: uint16): uint16 {.magic: "DivU", noSideEffect.}
+proc `div`*(x, y: uint32): uint32 {.magic: "DivU", noSideEffect.}
+proc `div`*(x, y: uint64): uint64 {.magic: "DivU", noSideEffect.}
 
-proc `mod`*[T: SomeUnsignedInt](x, y: T): T {.magic: "ModU", noSideEffect.}
+proc `mod`*(x, y: uint): uint {.magic: "ModU", noSideEffect.}
   ## Computes the integer modulo operation (remainder) for unsigned integers.
   ## This is the same as ``x - (x div y) * y``.
+proc `mod`*(x, y: uint8): uint8 {.magic: "ModU", noSideEffect.}
+proc `mod`*(x, y: uint16): uint16 {.magic: "ModU", noSideEffect.}
+proc `mod`*(x, y: uint32): uint32 {.magic: "ModU", noSideEffect.}
+proc `mod`*(x, y: uint64): uint64 {.magic: "ModU", noSideEffect.}
 
-proc `<=`*[T: SomeUnsignedInt](x, y: T): bool {.magic: "LeU", noSideEffect.}
+proc `<=`*(x, y: uint): bool {.magic: "LeU", noSideEffect.}
   ## Returns true if ``x <= y``.
+proc `<=`*(x, y: uint8): bool {.magic: "LeU", noSideEffect.}
+proc `<=`*(x, y: uint16): bool {.magic: "LeU", noSideEffect.}
+proc `<=`*(x, y: uint32): bool {.magic: "LeU", noSideEffect.}
+proc `<=`*(x, y: uint64): bool {.magic: "LeU", noSideEffect.}
 
-proc `<`*[T: SomeUnsignedInt](x, y: T): bool {.magic: "LtU", noSideEffect.}
+proc `<`*(x, y: uint): bool {.magic: "LtU", noSideEffect.}
   ## Returns true if ``unsigned(x) < unsigned(y)``.
+proc `<`*(x, y: uint8): bool {.magic: "LtU", noSideEffect.}
+proc `<`*(x, y: uint16): bool {.magic: "LtU", noSideEffect.}
+proc `<`*(x, y: uint32): bool {.magic: "LtU", noSideEffect.}
+proc `<`*(x, y: uint64): bool {.magic: "LtU", noSideEffect.}
 
 # floating point operations:
 proc `+`*(x: float32): float32 {.magic: "UnaryPlusF64", noSideEffect.}
diff --git a/tests/arithm/tarithm.nim b/tests/arithm/tarithm.nim
index 4625a5ecf..fcb78bd7a 100644
--- a/tests/arithm/tarithm.nim
+++ b/tests/arithm/tarithm.nim
@@ -4,6 +4,14 @@ int32
 int32
 1280
 1280
+3
+1
+2
+2
+3
+4294967295
+2
+0
 '''
 """
 
@@ -145,3 +153,17 @@ block tsubrange:
 
   level = min(level + 2, maxLevel).n16
   doAssert level == 1
+
+block tissue12177:
+  var a: uint16 = 1
+  var b: uint32 = 2
+
+  echo(b + a)
+  echo(b - a)
+  echo(b * a)
+  echo(b div a)
+
+  echo(a + b)
+  echo(a - b)
+  echo(a * b)
+  echo(a div b)
diff --git a/tests/concepts/t3330.nim b/tests/concepts/t3330.nim
index ed1590e16..ab77dd347 100644
--- a/tests/concepts/t3330.nim
+++ b/tests/concepts/t3330.nim
@@ -9,23 +9,23 @@ proc test(foo: Foo[int])
   required type for foo: Foo[int]
   but expression 'bar' is of type: Bar[system.int]
 t3330.nim(63, 8) Hint: Non-matching candidates for add(k, string, T)
-proc add[T](x: var seq[T]; y: openArray[T])
+proc add[T](x: var seq[T]; y: T)
   first type mismatch at position: 1
   required type for x: var seq[T]
   but expression 'k' is of type: Alias
-proc add[T](x: var seq[T]; y: T)
+proc add(x: var string; y: string)
   first type mismatch at position: 1
-  required type for x: var seq[T]
+  required type for x: var string
   but expression 'k' is of type: Alias
 proc add(result: var string; x: float)
   first type mismatch at position: 1
   required type for result: var string
   but expression 'k' is of type: Alias
-proc add(x: var string; y: cstring)
+proc add(x: var string; y: char)
   first type mismatch at position: 1
   required type for x: var string
   but expression 'k' is of type: Alias
-proc add(x: var string; y: string)
+proc add(x: var string; y: cstring)
   first type mismatch at position: 1
   required type for x: var string
   but expression 'k' is of type: Alias
@@ -33,9 +33,9 @@ proc add(result: var string; x: int64)
   first type mismatch at position: 1
   required type for result: var string
   but expression 'k' is of type: Alias
-proc add(x: var string; y: char)
+proc add[T](x: var seq[T]; y: openArray[T])
   first type mismatch at position: 1
-  required type for x: var string
+  required type for x: var seq[T]
   but expression 'k' is of type: Alias
 
 t3330.nim(63, 8) template/generic instantiation of `add` from here
diff --git a/tests/errmsgs/twrong_at_operator.nim b/tests/errmsgs/twrong_at_operator.nim
index 9933b0f39..ebf6d966b 100644
--- a/tests/errmsgs/twrong_at_operator.nim
+++ b/tests/errmsgs/twrong_at_operator.nim
@@ -4,14 +4,14 @@ line: 22
 nimout: '''
 twrong_at_operator.nim(22, 30) Error: type mismatch: got <array[0..0, type int]>
 but expected one of:
-proc `@`[T](a: openArray[T]): seq[T]
-  first type mismatch at position: 1
-  required type for a: openArray[T]
-  but expression '[int]' is of type: array[0..0, type int]
 proc `@`[IDX, T](a: sink array[IDX, T]): seq[T]
   first type mismatch at position: 1
   required type for a: sink array[IDX, T]
   but expression '[int]' is of type: array[0..0, type int]
+proc `@`[T](a: openArray[T]): seq[T]
+  first type mismatch at position: 1
+  required type for a: openArray[T]
+  but expression '[int]' is of type: array[0..0, type int]
 
 expression: @[int]
 '''
diff --git a/tests/generics/tgenerics_issues.nim b/tests/generics/tgenerics_issues.nim
index 3d5d65c75..af71a8938 100644
--- a/tests/generics/tgenerics_issues.nim
+++ b/tests/generics/tgenerics_issues.nim
@@ -762,11 +762,3 @@ block t3717:
 
   var f: Foo[Foo[int]]
   discard foo(f)
-
-
-
-block t5707:
-  proc foo[T]: seq[int] =
-      return lc[x | (x <- 1..10, x mod 2 == 0), int]
-
-  doAssert foo[float32]() == @[2, 4, 6, 8, 10]
diff --git a/tests/pragmas/t6448.nim b/tests/pragmas/t6448.nim
index a1bd747a0..ab2e3811f 100644
--- a/tests/pragmas/t6448.nim
+++ b/tests/pragmas/t6448.nim
@@ -1,6 +1,7 @@
 discard """
   errormsg: '''ambiguous call; both foobar.async'''
-  line: 9
+  line: 10
+  disabled: "32bit"
 """
 
 import foobar