summary refs log tree commit diff stats
path: root/tests/tuples
diff options
context:
space:
mode:
Diffstat (limited to 'tests/tuples')
-rw-r--r--tests/tuples/mnimsconstunpack.nim4
-rw-r--r--tests/tuples/t12892.nim8
-rw-r--r--tests/tuples/t18125_1.nim14
-rw-r--r--tests/tuples/t18125_2.nim20
-rw-r--r--tests/tuples/t7012.nim7
-rw-r--r--tests/tuples/t9177.nim15
-rw-r--r--tests/tuples/tanontuples.nim14
-rw-r--r--tests/tuples/tconver_tuple.nim23
-rw-r--r--tests/tuples/tdifferent_instantiations.nim9
-rw-r--r--tests/tuples/tfortupleunpack.nim52
-rw-r--r--tests/tuples/tgeneric_tuple.nim9
-rw-r--r--tests/tuples/tgeneric_tuple2.nim17
-rw-r--r--tests/tuples/tinferred_generic_const.nim14
-rw-r--r--tests/tuples/tnimsconstunpack.nim8
-rw-r--r--tests/tuples/ttuples_issues.nim133
-rw-r--r--tests/tuples/ttuples_various.nim211
-rw-r--r--tests/tuples/ttypedesc_in_tuple_a.nim5
-rw-r--r--tests/tuples/ttypedesc_in_tuple_b.nim5
-rw-r--r--tests/tuples/tuint_tuple.nim10
-rw-r--r--tests/tuples/tunpack_asgn.nim32
-rw-r--r--tests/tuples/tuple_with_nil.nim58
-rw-r--r--tests/tuples/tuple_with_seq.nim46
-rw-r--r--tests/tuples/twrong_generic_caching.nim4
-rw-r--r--tests/tuples/twrongtupleaccess.nim3
24 files changed, 526 insertions, 195 deletions
diff --git a/tests/tuples/mnimsconstunpack.nim b/tests/tuples/mnimsconstunpack.nim
new file mode 100644
index 000000000..65fafc12f
--- /dev/null
+++ b/tests/tuples/mnimsconstunpack.nim
@@ -0,0 +1,4 @@
+proc foo(): tuple[a, b: string] =
+  result = ("a", "b")
+
+const (a, b*) = foo()
diff --git a/tests/tuples/t12892.nim b/tests/tuples/t12892.nim
new file mode 100644
index 000000000..d69e99c7f
--- /dev/null
+++ b/tests/tuples/t12892.nim
@@ -0,0 +1,8 @@
+discard """
+  disabled: i386
+"""
+
+template works[T](): auto = T.high - 1
+template breaks[T](): auto = (T.high - 1, true)
+doAssert $works[uint]() == "18446744073709551614"
+doAssert $breaks[uint]() == "(18446744073709551614, true)"
diff --git a/tests/tuples/t18125_1.nim b/tests/tuples/t18125_1.nim
new file mode 100644
index 000000000..74fdfe8f5
--- /dev/null
+++ b/tests/tuples/t18125_1.nim
@@ -0,0 +1,14 @@
+# issue #18125 solved with type inference
+
+type
+  Parent = ref object of RootObj
+
+  Child = ref object of Parent
+    c: char
+
+func foo(c: char): (Parent, int) =
+  # Works if you use (Parent(Child(c: c)), 0)
+  (Child(c: c), 0)
+
+let x = foo('x')[0]
+doAssert Child(x).c == 'x'
diff --git a/tests/tuples/t18125_2.nim b/tests/tuples/t18125_2.nim
new file mode 100644
index 000000000..fe0a4a8bb
--- /dev/null
+++ b/tests/tuples/t18125_2.nim
@@ -0,0 +1,20 @@
+discard """
+  errormsg: "type mismatch: got <(Child, int)> but expected '(Parent, int)'"
+  line: 17
+"""
+
+# issue #18125 solved with correct type relation
+
+type
+  Parent = ref object of RootObj
+
+  Child = ref object of Parent
+    c: char
+
+func foo(c: char): (Parent, int) =
+  # Works if you use (Parent(Child(c: c)), 0)
+  let x = (Child(c: c), 0)
+  x
+
+let x = foo('x')[0]
+doAssert Child(x).c == 'x'
diff --git a/tests/tuples/t7012.nim b/tests/tuples/t7012.nim
new file mode 100644
index 000000000..32d441ddd
--- /dev/null
+++ b/tests/tuples/t7012.nim
@@ -0,0 +1,7 @@
+discard """
+  errormsg: "illegal recursion in type 'Node'"
+"""
+
+type Node[T] = tuple
+    next: ref Node[T]
+var n: Node[int]
\ No newline at end of file
diff --git a/tests/tuples/t9177.nim b/tests/tuples/t9177.nim
new file mode 100644
index 000000000..e6dd0cb1d
--- /dev/null
+++ b/tests/tuples/t9177.nim
@@ -0,0 +1,15 @@
+discard """
+  action: run
+"""
+
+block:
+  var x = (a: 5, b: 1)
+  x = (3 * x.a + 2 * x.b, x.a + x.b)
+  doAssert x.a == 17
+  doAssert x.b == 6
+block:
+  # Transformation of a tuple constructor with named arguments
+  var x = (a: 5, b: 1)
+  x = (a: 3 * x.a + 2 * x.b, b: x.a + x.b)
+  doAssert x.a == 17
+  doAssert x.b == 6
diff --git a/tests/tuples/tanontuples.nim b/tests/tuples/tanontuples.nim
deleted file mode 100644
index 49803e5ac..000000000
--- a/tests/tuples/tanontuples.nim
+++ /dev/null
@@ -1,14 +0,0 @@
-discard """
-  output: '''61, 125'''
-"""
-
-proc `^` (a, b: int): int =
-  result = 1
-  for i in 1..b: result = result * a
-
-var m = (0, 5)
-var n = (56, 3)
-
-m = (n[0] + m[1], m[1] ^ n[1])
-
-echo m[0], ", ", m[1]
diff --git a/tests/tuples/tconver_tuple.nim b/tests/tuples/tconver_tuple.nim
deleted file mode 100644
index 306da77fe..000000000
--- a/tests/tuples/tconver_tuple.nim
+++ /dev/null
@@ -1,23 +0,0 @@
-# Bug 4479
-
-type
-  MyTuple = tuple
-    num: int
-    strings: seq[string]
-    ints: seq[int]
-
-var foo = MyTuple((
-  num: 7,
-  strings: @[],
-  ints: @[],
-))
-
-var bar = (
-  num: 7,
-  strings: @[],
-  ints: @[],
-).MyTuple
-
-var fooUnnamed = MyTuple((7, @[], @[]))
-var n = 7
-var fooSym = MyTuple((num: n, strings: @[], ints: @[]))
diff --git a/tests/tuples/tdifferent_instantiations.nim b/tests/tuples/tdifferent_instantiations.nim
deleted file mode 100644
index 93b1777b5..000000000
--- a/tests/tuples/tdifferent_instantiations.nim
+++ /dev/null
@@ -1,9 +0,0 @@
-# bug #1910
-import tables
-
-var p: OrderedTable[tuple[a:int], int]
-var q: OrderedTable[tuple[x:int], int]
-for key in p.keys:
-  echo key.a
-for key in q.keys:
-  echo key.x
diff --git a/tests/tuples/tfortupleunpack.nim b/tests/tuples/tfortupleunpack.nim
new file mode 100644
index 000000000..e222a1ae6
--- /dev/null
+++ b/tests/tuples/tfortupleunpack.nim
@@ -0,0 +1,52 @@
+discard """
+output: '''
+123
+113283
+0
+123
+1
+113283
+@[(88, 99, 11), (88, 99, 11)]
+@[(7, 6, -28), (7, 6, -28)]
+12
+110100
+'''
+"""
+
+let t1 = (1, 2, 3)
+let t2 = (11, 32, 83)
+let s = @[t1, t2]
+
+for (a, b, c) in s:
+  echo a, b, c
+
+for i, (a, b, c) in s:
+  echo i
+  echo a, b, c
+
+var x = @[(1,2,3), (4,5,6)]
+
+for (a, b, c) in x.mitems:
+  a = 88
+  b = 99
+  c = 11
+echo x
+
+for i, (a, b, c) in x.mpairs:
+  a = 7
+  b = 6
+  c = -28
+echo x
+
+proc test[n]() =
+  for (a,b) in @[(1,2)]:
+    echo a,b
+test[string]()
+
+iterator tuples: (int, (int, int)) = yield (1,(10, 100))
+
+template t11164 =
+  for i, (a, b) in tuples():
+    echo i, a , b
+
+t11164()
diff --git a/tests/tuples/tgeneric_tuple.nim b/tests/tuples/tgeneric_tuple.nim
deleted file mode 100644
index 32f081596..000000000
--- a/tests/tuples/tgeneric_tuple.nim
+++ /dev/null
@@ -1,9 +0,0 @@
-# bug #2121
-
-type
-  Item[K,V] = tuple
-    key: K
-    value: V
-
-var q = newseq[Item[int,int]](0)
-let (x,y) = q[0]
diff --git a/tests/tuples/tgeneric_tuple2.nim b/tests/tuples/tgeneric_tuple2.nim
deleted file mode 100644
index c0c292388..000000000
--- a/tests/tuples/tgeneric_tuple2.nim
+++ /dev/null
@@ -1,17 +0,0 @@
-
-# bug #2369
-
-type HashedElem[T] = tuple[num: int, storedVal: ref T]
-
-proc append[T](tab: var seq[HashedElem[T]], n: int, val: ref T) =
-    #tab.add((num: n, storedVal: val))
-    var he: HashedElem[T] = (num: n, storedVal: val)
-    #tab.add(he)
-
-var g: seq[HashedElem[int]] = @[]
-
-proc foo() =
-    var x: ref int
-    new(x)
-    x[] = 77
-    g.append(44, x)
diff --git a/tests/tuples/tinferred_generic_const.nim b/tests/tuples/tinferred_generic_const.nim
new file mode 100644
index 000000000..5ab730c38
--- /dev/null
+++ b/tests/tuples/tinferred_generic_const.nim
@@ -0,0 +1,14 @@
+discard """
+  action: run
+"""
+block:
+  proc something(a: string or int or float) =
+    const (c, d) = (default a.type, default a.type)
+
+block:
+  proc something(a: string or int) =
+    const c = default a.type
+
+block:
+  proc something(a: string or int) =
+    const (c, d, e) = (default a.type, default a.type, default a.type)
diff --git a/tests/tuples/tnimsconstunpack.nim b/tests/tuples/tnimsconstunpack.nim
new file mode 100644
index 000000000..7860fc0a4
--- /dev/null
+++ b/tests/tuples/tnimsconstunpack.nim
@@ -0,0 +1,8 @@
+discard """
+  action: compile
+  cmd: "nim e $file"
+"""
+
+import mnimsconstunpack
+
+doAssert b == "b"
diff --git a/tests/tuples/ttuples_issues.nim b/tests/tuples/ttuples_issues.nim
new file mode 100644
index 000000000..70defdfce
--- /dev/null
+++ b/tests/tuples/ttuples_issues.nim
@@ -0,0 +1,133 @@
+discard """
+  targets: "c cpp js"
+"""
+
+# targets include `cpp` because in the past, there were several cpp-specific bugs with tuples.
+
+import std/tables
+
+template main() =
+  block: # bug #4479
+    type
+      MyTuple = tuple
+        num: int
+        strings: seq[string]
+        ints: seq[int]
+
+    var foo = MyTuple((
+      num: 7,
+      strings: @[],
+      ints: @[],
+    ))
+
+    var bar = MyTuple (
+      num: 7,
+      strings: @[],
+      ints: @[],
+    )
+
+    var fooUnnamed = MyTuple((7, @[], @[]))
+    var n = 7
+    var fooSym = MyTuple((num: n, strings: @[], ints: @[]))
+
+  block: # bug #1910
+    var p = newOrderedTable[tuple[a:int], int]()
+    var q = newOrderedTable[tuple[x:int], int]()
+    for key in p.keys:
+      echo key.a
+    for key in q.keys:
+      echo key.x
+
+  block: # bug #2121
+    type
+      Item[K,V] = tuple
+        key: K
+        value: V
+
+    var q = newseq[Item[int,int]](1)
+    let (x,y) = q[0]
+
+  block: # bug #2369
+    type HashedElem[T] = tuple[num: int, storedVal: ref T]
+
+    proc append[T](tab: var seq[HashedElem[T]], n: int, val: ref T) =
+        #tab.add((num: n, storedVal: val))
+        var he: HashedElem[T] = (num: n, storedVal: val)
+        #tab.add(he)
+
+    var g: seq[HashedElem[int]] = @[]
+
+    proc foo() =
+        var x: ref int
+        new(x)
+        x[] = 77
+        g.append(44, x)
+
+  block: # bug #1986
+    proc test(): int64 =
+      return 0xdeadbeef.int64
+
+    const items = [
+      (var1: test(), var2: 100'u32),
+      (var1: test(), var2: 192'u32)
+    ]
+
+  block: # bug #14911
+    doAssert $(a: 1) == "(a: 1)" # works
+    doAssert $(`a`: 1) == "(a: 1)"  # works
+    doAssert $(`a`: 1, `b`: 2) == "(a: 1, b: 2)" # was: Error: named expression expected
+
+  block: # bug #16822
+    var scores: seq[(set[char], int)] = @{{'/'} : 10}
+
+    var x1: set[char]
+    for item in items(scores):
+      x1 = item[0]
+
+    doAssert x1 == {'/'}
+
+    var x2: set[char]
+    for (chars, value) in items(scores):
+      x2 = chars
+
+    doAssert x2 == {'/'}
+
+  block: # bug #14574
+    proc fn(): auto =
+      let a = @[("foo", (12, 13))]
+      for (k,v) in a:
+        return (k,v)
+    doAssert fn() == ("foo", (12, 13))
+
+  block: # bug #14574
+    iterator fn[T](a:T): lent T = yield a
+    let a = (10, (11,))
+    proc bar(): auto =
+      for (x,y) in fn(a):
+        return (x,y)
+    doAssert bar() == (10, (11,))
+
+  block: # bug #16331
+    type T1 = tuple[a, b: int]
+
+    proc p(b: bool): T1 =
+      var x: T1 = (10, 20)
+      x = if b: (x.b, x.a) else: (-x.b, -x.a)
+      x
+
+    doAssert p(false) == (-20, -10)
+    doAssert p(true) == (20, 10)
+
+
+proc mainProc() =
+  # other tests should be in `main`
+  block:
+    type A = tuple[x: int, y: int]
+    doAssert (x: 1, y: 2).A == A (x: 1, y: 2) # MCS => can't use a template
+
+static:
+  main()
+  mainProc()
+
+main()
+mainProc()
diff --git a/tests/tuples/ttuples_various.nim b/tests/tuples/ttuples_various.nim
new file mode 100644
index 000000000..e392731d2
--- /dev/null
+++ b/tests/tuples/ttuples_various.nim
@@ -0,0 +1,211 @@
+discard """
+output: '''
+it's nil
+@[1, 2, 3]
+'''
+"""
+
+import macros
+
+
+block anontuples:
+  proc `^` (a, b: int): int =
+    result = 1
+    for i in 1..b: result = result * a
+
+  var m = (0, 5)
+  var n = (56, 3)
+
+  m = (n[0] + m[1], m[1] ^ n[1])
+
+  doAssert m == (61, 125)
+
+  # also test we can produce unary anon tuples in a macro:
+  macro mm(): untyped =
+    result = newTree(nnkTupleConstr, newLit(13))
+
+  proc nowTuple(): (int,) =
+    result = (0,)
+
+  doAssert nowTuple() == (Field0: 0)
+  doAssert mm() == (Field0: 13)
+
+
+
+block unpack_asgn:
+  proc foobar(): (int, int) = (2, 4)
+
+  # test within a proc:
+  proc pp(x: var int) =
+    var y: int
+    (y, x) = foobar()
+
+  template pt(x) =
+    var y: int
+    (x, y) = foobar()
+
+  # test within a generic:
+  proc pg[T](x, y: var T) =
+    pt(x)
+
+  # test as a top level statement:
+  var x, y, a, b: int
+  # test for regression:
+  (x, y) = (1, 2)
+  (x, y) = fooBar()
+
+  doAssert x == 2
+  doAssert y == 4
+
+  pp(a)
+  doAssert a == 4
+
+  pg(a, b)
+  doAssert a == 2
+  doAssert b == 0
+
+
+
+block unpack_const:
+  const (a, ) = (1, )
+  doAssert a == 1
+
+  const (b, c) = (2, 3)
+  doAssert b == 2
+  doAssert c == 3
+
+  # bug #10098
+  const (x, y, z) = (4, 5, 6)
+  doAssert x == 4
+  doAssert y == 5
+  doAssert z == 6
+
+
+# bug #10724
+block unpack_const_named:
+  const (a, ) = (x: 1, )
+  doAssert a == 1
+
+  const (b, c) = (x: 2, y: 3)
+  doAssert b == 2
+  doAssert c == 3
+
+  const (d, e, f) = (x: 4, y: 5, z: 6)
+  doAssert d == 4
+  doAssert e == 5
+  doAssert f == 6
+
+block const_named:
+  const x = block:
+    (a: 1, b: 2, c: 3)
+  doAssert x.a == 1
+  doAssert x.b == 2
+  doAssert x.c == 3
+
+
+block tuple_subscript:
+  proc`[]` (t: tuple, key: string): string =
+    for name, field in fieldPairs(t):
+      if name == key:
+        return $field
+    return ""
+
+  proc`[]` [A,B](t: tuple, key: string, op: (proc(x: A): B)): B =
+    for name, field in fieldPairs(t):
+      when field is A:
+        if name == key:
+          return op(field)
+
+  proc`[]=`[T](t: var tuple, key: string, val: T) =
+    for name, field in fieldPairs(t):
+      when field is T:
+        if name == key:
+          field = val
+
+  var tt = (a: 1, b: "str1")
+
+  # test built in operator
+  tt[0] = 5
+
+  doAssert tt[0] == 5
+  doAssert `[]`(tt, 0) == 5
+
+  # test overloaded operator
+  tt["b"] = "str2"
+  doAssert tt["b"] == "str2"
+  doAssert `[]`(tt, "b") == "str2"
+  doAssert tt["b", proc(s: string): int = s.len] == 4
+
+
+
+block tuple_with_seq:
+  template foo(s: string = "") =
+    if s.len == 0:
+      echo "it's nil"
+    else:
+      echo s
+  foo
+
+  # bug #2632
+  proc takeTup(x: tuple[s: string;x: seq[int]]) =
+    discard
+  takeTup(("foo", @[]))
+
+  #proc foobar(): () =
+  proc f(xs: seq[int]) =
+    discard
+
+  proc g(t: tuple[n:int, xs:seq[int]]) =
+    discard
+
+  when true:
+    f(@[]) # OK
+    g((1,@[1])) # OK
+    g((0,@[])) # NG
+
+  # bug #2630
+  type T = tuple[a: seq[int], b: int]
+  var t: T = (@[1,2,3], 7)
+
+  proc test(s: seq[int]): T =
+    echo s
+    (s, 7)
+  t = test(t.a)
+
+block: # bug #22049
+  type A = object
+    field: tuple[a, b, c: seq[int]]
+
+  func value(v: var A): var tuple[a, b, c: seq[int]] =
+    v.field
+  template get(v: A): tuple[a, b, c: seq[int]] = v.value
+
+  var v = A(field: (@[1], @[2], @[3]))
+  var (a, b, c) = v.get()
+
+  doAssert a == @[1]
+  doAssert b == @[2]
+  doAssert c == @[3]
+
+block: # bug #22054
+  type A = object
+    field: tuple[a: int]
+
+  func value(v: var A): var tuple[a: int] =
+    v.field
+  template get(v: A): tuple[a: int] = v.value
+
+  var v = A(field: (a: 1314))
+  doAssert get(v)[0] == 1314
+
+block: # tuple unpacking assignment with underscore
+  var
+    a = 1
+    b = 2
+  doAssert (a, b) == (1, 2)
+  (a, _) = (3, 4)
+  doAssert (a, b) == (3, 2)
+  (_, a) = (5, 6)
+  doAssert (a, b) == (6, 2)
+  (b, _) = (7, 8)
+  doAssert (a, b) == (6, 7)
diff --git a/tests/tuples/ttypedesc_in_tuple_a.nim b/tests/tuples/ttypedesc_in_tuple_a.nim
new file mode 100644
index 000000000..7727bb35e
--- /dev/null
+++ b/tests/tuples/ttypedesc_in_tuple_a.nim
@@ -0,0 +1,5 @@
+discard """
+errormsg: "typedesc not allowed as tuple field."
+"""
+
+var bar = (a: int, b: 1)
diff --git a/tests/tuples/ttypedesc_in_tuple_b.nim b/tests/tuples/ttypedesc_in_tuple_b.nim
new file mode 100644
index 000000000..b393d877c
--- /dev/null
+++ b/tests/tuples/ttypedesc_in_tuple_b.nim
@@ -0,0 +1,5 @@
+discard """
+errormsg: "Mixing types and values in tuples is not allowed."
+"""
+
+var bar = (int, 1)
diff --git a/tests/tuples/tuint_tuple.nim b/tests/tuples/tuint_tuple.nim
deleted file mode 100644
index 24bcead5e..000000000
--- a/tests/tuples/tuint_tuple.nim
+++ /dev/null
@@ -1,10 +0,0 @@
-# bug #1986 found by gdmoore
-
-proc test(): int64 =
-  return 0xdeadbeef.int64
-
-const items = [
-  (var1: test(), var2: 100'u32),
-  (var1: test(), var2: 192'u32)
-]
-
diff --git a/tests/tuples/tunpack_asgn.nim b/tests/tuples/tunpack_asgn.nim
deleted file mode 100644
index a48fcff5d..000000000
--- a/tests/tuples/tunpack_asgn.nim
+++ /dev/null
@@ -1,32 +0,0 @@
-discard """
-  output: '''2 4
-4
-2 0'''
-"""
-
-proc foobar(): (int, int) = (2, 4)
-
-# test within a proc:
-proc pp(x: var int) =
-  var y: int
-  (y, x) = foobar()
-
-template pt(x) =
-  var y: int
-  (x, y) = foobar()
-
-# test within a generic:
-proc pg[T](x, y: var T) =
-  pt(x)
-
-# test as a top level statement:
-var x, y, a, b: int
-(x, y) = fooBar()
-
-echo x, " ", y
-
-pp(a)
-echo a
-
-pg(a, b)
-echo a, " ", b
diff --git a/tests/tuples/tuple_with_nil.nim b/tests/tuples/tuple_with_nil.nim
index 9b5d583d3..9cad6eccd 100644
--- a/tests/tuples/tuple_with_nil.nim
+++ b/tests/tuples/tuple_with_nil.nim
@@ -1,24 +1,16 @@
 import macros
-from strutils import IdentStartChars
 import parseutils
 import unicode
 import math
-import fenv
-#import unsigned
 import pegs
 import streams
 
 type
-  FormatError = object of Exception ## Error in the format string.
+  FormatError = object of CatchableError ## Error in the format string.
 
   Writer = concept W
     ## Writer to output a character `c`.
-    when (NimMajor, NimMinor, NimPatch) > (0, 10, 2):
-      write(W, 'c')
-    else:
-      block:
-        var x: W
-        write(x, char)
+    write(W, 'c')
 
   FmtAlign = enum ## Format alignment
     faDefault  ## default for given format type
@@ -50,7 +42,7 @@ type
     precision: int    ## floating point precision
     width: int        ## minimal width
     fill: string      ## the fill character, UTF8
-    align: FmtAlign  ## aligment
+    align: FmtAlign  ## alignment
     sign: FmtSign    ## sign notation
     baseprefix: bool  ## whether binary, octal, hex should be prefixed by 0b, 0x, 0o
     upcase: bool      ## upper case letters in hex or exponential formats
@@ -73,7 +65,7 @@ type
 
 const
   DefaultPrec = 6 ## Default precision for floating point numbers.
-  DefaultFmt: Format = (ftDefault, -1, -1, nil, faDefault, fsMinus, false, false, false, nil)
+  DefaultFmt: Format = (ftDefault, -1, -1, "", faDefault, fsMinus, false, false, false, "")
     ## Default format corresponding to the empty format string, i.e.
     ##   `x.format("") == x.format(DefaultFmt)`.
   round_nums = [0.5, 0.05, 0.005, 0.0005, 0.00005, 0.000005, 0.0000005, 0.00000005]
@@ -88,7 +80,7 @@ proc has(c: Captures; i: range[0..pegs.MaxSubpatterns-1]): bool {.nosideeffect,
   result = b.first <= b.last
 
 proc get(str: string; c: Captures; i: range[0..MaxSubpatterns-1]; def: char): char {.nosideeffect, inline.} =
-  ## If capture `i` is non-empty return that portion of `str` casted
+  ## If capture `i` is non-empty return that portion of `str` cast
   ## to `char`, otherwise return `def`.
   result = if c.has(i): str[c.bounds(i).first] else: def
 
@@ -124,7 +116,7 @@ proc parse(fmt: string): Format {.nosideeffect.} =
   if fmt.rawmatch(p, 0, caps) < 0:
     raise newException(FormatError, "Invalid format string")
 
-  result.fill = fmt.get(caps, 0, nil)
+  result.fill = fmt.get(caps, 0, "")
 
   case fmt.get(caps, 1, 0.char)
   of '<': result.align = faLeft
@@ -144,7 +136,7 @@ proc parse(fmt: string): Format {.nosideeffect.} =
   result.width = fmt.get(caps, 4, -1)
 
   if caps.has(4) and fmt[caps.bounds(4).first] == '0':
-    if result.fill != nil:
+    if result.fill != "":
       raise newException(FormatError, "Leading 0 in with not allowed with explicit fill character")
     if result.align != faDefault:
       raise newException(FormatError, "Leading 0 in with not allowed with explicit alignment")
@@ -171,7 +163,7 @@ proc parse(fmt: string): Format {.nosideeffect.} =
   of '%': result.typ = ftPercent
   else: result.typ = ftDefault
 
-  result.arysep = fmt.get(caps, 8, nil, 1)
+  result.arysep = fmt.get(caps, 8, "", 1)
 
 proc getalign(fmt: Format; defalign: FmtAlign; slen: int) : tuple[left, right:int] {.nosideeffect.} =
   ## Returns the number of left and right padding characters for a
@@ -208,7 +200,7 @@ proc writefill(o: var Writer; fmt: Format; n: int; signum: int = 0) =
   ## `add`
   ##   output function
   ## `fmt`
-  ##   format to be used (important for padding aligment)
+  ##   format to be used (important for padding alignment)
   ## `n`
   ##   the number of filling characters to be written
   ## `signum`
@@ -218,7 +210,7 @@ proc writefill(o: var Writer; fmt: Format; n: int; signum: int = 0) =
     elif fmt.sign == fsPlus: write(o, '+')
     elif fmt.sign == fsSpace: write(o, ' ')
 
-  if fmt.fill == nil:
+  if fmt.fill.len == 0:
     for i in 1..n: write(o, ' ')
   else:
     for i in 1..n:
@@ -345,7 +337,7 @@ proc writeformat(o: var Writer; p: pointer; fmt: Format) =
   ## Write pointer `i` according to format `fmt` using output object
   ## `o` and output function `add`.
   ##
-  ## Pointers are casted to unsigned int and formatted as hexadecimal
+  ## Pointers are cast to unsigned int and formatted as hexadecimal
   ## with prefix unless specified otherwise.
   var f = fmt
   if f.typ == 0.char:
@@ -353,7 +345,7 @@ proc writeformat(o: var Writer; p: pointer; fmt: Format) =
     f.baseprefix = true
   writeformat(o, add, cast[uint](p), f)
 
-proc writeformat(o: var Writer; x: SomeReal; fmt: Format) =
+proc writeformat(o: var Writer; x: SomeFloat; fmt: Format) =
   ## Write real number `x` according to format `fmt` using output
   ## object `o` and output function `add`.
   var fmt = fmt
@@ -401,8 +393,8 @@ proc writeformat(o: var Writer; x: SomeReal; fmt: Format) =
       else:
         len += 4 # exponent
       # shift y so that 1 <= abs(y) < 2
-      if exp > 0: y /= pow(10.SomeReal, abs(exp).SomeReal)
-      elif exp < 0: y *= pow(10.SomeReal, abs(exp).SomeReal)
+      if exp > 0: y /= pow(10.SomeFloat, abs(exp).SomeFloat)
+      elif exp < 0: y *= pow(10.SomeFloat, abs(exp).SomeFloat)
     elif fmt.typ == ftPercent:
       len += 1 # percent sign
 
@@ -413,7 +405,7 @@ proc writeformat(o: var Writer; x: SomeReal; fmt: Format) =
     var mult = 1'i64
     for i in 1..prec: mult *= 10
     var num = y.int64
-    var fr = ((y - num.SomeReal) * mult.SomeReal).int64
+    var fr = ((y - num.SomeFloat) * mult.SomeFloat).int64
     # build integer part string
     while num != 0:
       numstr[numlen] = ('0'.int + (num mod 10)).char
@@ -485,7 +477,7 @@ proc writeformat(o: var Writer; b: bool; fmt: Format) =
   else:
     raise newException(FormatError, "Boolean values must of one of the following types: s,b,o,x,X,d,n")
 
-proc writeformat(o: var Writer; ary: openarray[any]; fmt: Format) =
+proc writeformat(o: var Writer; ary: openArray[system.any]; fmt: Format) =
   ## Write array `ary` according to format `fmt` using output object
   ## `o` and output function `add`.
   if ary.len == 0: return
@@ -626,19 +618,19 @@ proc splitfmt(s: string): seq[Part] {.compiletime, nosideeffect.} =
       else:
         lvl.dec
     let clpos = pos
-    var fmtpart = Part(kind: pkFmt, arg: -1, fmt: s.substr(oppos+1, clpos-1), field: nil, index: int.high, nested: nested)
+    var fmtpart = Part(kind: pkFmt, arg: -1, fmt: s.substr(oppos+1, clpos-1), field: "", index: int.high, nested: nested)
     if fmtpart.fmt.len > 0:
       var m: array[0..3, string]
       if not fmtpart.fmt.match(subpeg, m):
         error("invalid format string")
 
-      if m[1] != nil and m[1].len > 0:
+      if m[1].len > 0:
         fmtpart.field = m[1].substr(1)
-      if m[2] != nil and m[2].len > 0:
+      if m[2].len > 0:
         discard parseInt(m[2].substr(1, m[2].len-2), fmtpart.index)
 
       if m[0].len > 0: discard parseInt(m[0], fmtpart.arg)
-      if m[3] == nil or m[3].len == 0:
+      if m[3].len == 0:
         fmtpart.fmt = ""
       elif m[3][0] == ':':
         fmtpart.fmt = m[3].substr(1)
@@ -650,7 +642,7 @@ proc splitfmt(s: string): seq[Part] {.compiletime, nosideeffect.} =
 proc literal(s: string): NimNode {.compiletime, nosideeffect.} =
   ## Return the nim literal of string `s`. This handles the case if
   ## `s` is nil.
-  result = if s == nil: newNilLit() else: newLit(s)
+  result = newLit(s)
 
 proc literal(b: bool): NimNode {.compiletime, nosideeffect.} =
   ## Return the nim literal of boolean `b`. This is either `true`
@@ -665,7 +657,7 @@ proc literal[T](x: T): NimNode {.compiletime, nosideeffect.} =
     result = newLit(x)
 
 proc generatefmt(fmtstr: string;
-                 args: var openarray[tuple[arg:NimNode, cnt:int]];
+                 args: var openArray[tuple[arg:NimNode, cnt:int]];
                  arg: var int;): seq[tuple[val, fmt:NimNode]] {.compiletime.} =
   ## fmtstr
   ##   the format string
@@ -713,7 +705,7 @@ proc generatefmt(fmtstr: string;
           args[arg].cnt = args[arg].cnt + 1
           arg.inc
         # possible field access
-        if part.field != nil and part.field.len > 0:
+        if part.field.len > 0:
           argexpr = newDotExpr(argexpr, part.field.ident)
         # possible array access
         if part.index < int.high:
@@ -724,7 +716,7 @@ proc generatefmt(fmtstr: string;
           # nested format string. Compute the format string by
           # concatenating the parts of the substring.
           for e in generatefmt(part.fmt, args, arg):
-            var newexpr = if part.fmt == nil: e.val else: newCall(bindsym"format", e.val, e.fmt)
+            var newexpr = if part.fmt.len == 0: e.val else: newCall(bindsym"format", e.val, e.fmt)
             if fmtexpr != nil and fmtexpr.kind != nnkNilLit:
               fmtexpr = infix(fmtexpr, "&", newexpr)
             else:
@@ -758,7 +750,7 @@ proc addfmtfmt(fmtstr: string; args: NimNode; retvar: NimNode): NimNode {.compil
     if arg.cnt == 0:
       warning("Argument " & $(i+1) & " `" & args[i].repr & "` is not used in format string")
 
-macro addfmt(s: var string, fmtstr: string{lit}, args: varargs[expr]): expr =
+macro addfmt(s: var string, fmtstr: string{lit}, args: varargs[typed]): untyped =
   ## The same as `s.add(fmtstr.fmt(args...))` but faster.
   result = addfmtfmt($fmtstr, args, s)
 
diff --git a/tests/tuples/tuple_with_seq.nim b/tests/tuples/tuple_with_seq.nim
deleted file mode 100644
index 39edb500f..000000000
--- a/tests/tuples/tuple_with_seq.nim
+++ /dev/null
@@ -1,46 +0,0 @@
-discard """
-  output: '''it's nil
-@[1, 2, 3]'''
-"""
-
-template foo(s: string = nil) =
-  if isNil(s):
-    echo "it's nil"
-  else:
-    echo s
-
-foo
-
-
-# bug #2632
-
-proc takeTup(x: tuple[s: string;x: seq[int]]) =
-  discard
-
-takeTup(("foo", @[]))
-
-
-#proc foobar(): () =
-
-proc f(xs: seq[int]) =
-  discard
-
-proc g(t: tuple[n:int, xs:seq[int]]) =
-  discard
-
-when isMainModule:
-  f(@[]) # OK
-  g((1,@[1])) # OK
-  g((0,@[])) # NG
-
-
-# bug #2630
-type T = tuple[a: seq[int], b: int]
-
-var t: T = (@[1,2,3], 7)
-
-proc test(s: seq[int]): T =
-  echo s
-  (s, 7)
-
-t = test(t.a)
diff --git a/tests/tuples/twrong_generic_caching.nim b/tests/tuples/twrong_generic_caching.nim
new file mode 100644
index 000000000..32ef344d2
--- /dev/null
+++ b/tests/tuples/twrong_generic_caching.nim
@@ -0,0 +1,4 @@
+
+import parsecfg
+
+import asynchttpserver
diff --git a/tests/tuples/twrongtupleaccess.nim b/tests/tuples/twrongtupleaccess.nim
index b1684b097..591716a2e 100644
--- a/tests/tuples/twrongtupleaccess.nim
+++ b/tests/tuples/twrongtupleaccess.nim
@@ -1,10 +1,9 @@
 discard """
+  errormsg: "attempting to call undeclared routine: \'setBLAH\'"
   file: "twrongtupleaccess.nim"
   line: 9
-  errormsg: "attempting to call undeclared routine: \'setBLAH\'"
 """
 # Bugfix
 
 var v = (5.0, 10.0)
 v.setBLAH(10)
-