summary refs log tree commit diff stats
path: root/compiler
diff options
context:
space:
mode:
Diffstat (limited to 'compiler')
-rw-r--r--compiler/astalgo.nim28
-rw-r--r--compiler/ccgexprs.nim2
-rw-r--r--compiler/ccgutils.nim58
-rw-r--r--compiler/extccomp.nim3
-rw-r--r--compiler/filter_tmpl.nim18
-rw-r--r--compiler/importer.nim2
-rw-r--r--compiler/jsgen.nim2
-rw-r--r--compiler/msgs.nim2
-rw-r--r--compiler/nimlexbase.nim2
-rw-r--r--compiler/renderer.nim6
-rw-r--r--compiler/sem.nim46
-rw-r--r--compiler/semcall.nim119
-rw-r--r--compiler/sigmatch.nim279
-rw-r--r--compiler/types.nim484
-rw-r--r--compiler/vm.nim46
15 files changed, 549 insertions, 548 deletions
diff --git a/compiler/astalgo.nim b/compiler/astalgo.nim
index 8d132ab26..c53e53b88 100644
--- a/compiler/astalgo.nim
+++ b/compiler/astalgo.nim
@@ -203,9 +203,9 @@ proc mustRehash(length, counter: int): bool =
   assert(length > counter)
   result = (length * 2 < counter * 3) or (length - counter < 4)
 
-proc spaces(x: int): PRope = 
+proc rspaces(x: int): PRope = 
   # returns x spaces
-  result = toRope(repeatChar(x))
+  result = toRope(spaces(x))
 
 proc toYamlChar(c: char): string = 
   case c
@@ -253,7 +253,7 @@ proc typeToYamlAux(n: PType, marker: var IntSet,
                    indent, maxRecDepth: int): PRope
 proc strTableToYaml(n: TStrTable, marker: var IntSet, indent: int, 
                     maxRecDepth: int): PRope = 
-  var istr = spaces(indent + 2)
+  var istr = rspaces(indent + 2)
   result = toRope("[")
   var mycount = 0
   for i in countup(0, high(n.data)): 
@@ -262,20 +262,20 @@ proc strTableToYaml(n: TStrTable, marker: var IntSet, indent: int,
       appf(result, "$N$1$2", 
            [istr, symToYamlAux(n.data[i], marker, indent + 2, maxRecDepth - 1)])
       inc(mycount)
-  if mycount > 0: appf(result, "$N$1", [spaces(indent)])
+  if mycount > 0: appf(result, "$N$1", [rspaces(indent)])
   app(result, "]")
   assert(mycount == n.counter)
 
 proc ropeConstr(indent: int, c: openArray[PRope]): PRope = 
   # array of (name, value) pairs
-  var istr = spaces(indent + 2)
+  var istr = rspaces(indent + 2)
   result = toRope("{")
   var i = 0
   while i <= high(c): 
     if i > 0: app(result, ",")
     appf(result, "$N$1\"$2\": $3", [istr, c[i], c[i + 1]])
     inc(i, 2)
-  appf(result, "$N$1}", [spaces(indent)])
+  appf(result, "$N$1}", [rspaces(indent)])
 
 proc symToYamlAux(n: PSym, marker: var IntSet, indent: int, 
                   maxRecDepth: int): PRope = 
@@ -310,9 +310,9 @@ proc typeToYamlAux(n: PType, marker: var IntSet, indent: int,
       result = toRope("[")
       for i in countup(0, sonsLen(n) - 1): 
         if i > 0: app(result, ",")
-        appf(result, "$N$1$2", [spaces(indent + 4), typeToYamlAux(n.sons[i], 
+        appf(result, "$N$1$2", [rspaces(indent + 4), typeToYamlAux(n.sons[i], 
             marker, indent + 4, maxRecDepth - 1)])
-      appf(result, "$N$1]", [spaces(indent + 2)])
+      appf(result, "$N$1]", [rspaces(indent + 2)])
     else: 
       result = toRope("null")
     result = ropeConstr(indent, [toRope("kind"), 
@@ -331,7 +331,7 @@ proc treeToYamlAux(n: PNode, marker: var IntSet, indent: int,
   if n == nil: 
     result = toRope("null")
   else: 
-    var istr = spaces(indent + 2)
+    var istr = rspaces(indent + 2)
     result = ropef("{$N$1\"kind\": $2", [istr, makeYamlString($n.kind)])
     if maxRecDepth != 0: 
       appf(result, ",$N$1\"info\": $2", [istr, lineInfoToStr(n.info)])
@@ -359,12 +359,12 @@ proc treeToYamlAux(n: PNode, marker: var IntSet, indent: int,
           appf(result, ",$N$1\"sons\": [", [istr])
           for i in countup(0, sonsLen(n) - 1): 
             if i > 0: app(result, ",")
-            appf(result, "$N$1$2", [spaces(indent + 4), treeToYamlAux(n.sons[i], 
+            appf(result, "$N$1$2", [rspaces(indent + 4), treeToYamlAux(n.sons[i], 
                 marker, indent + 4, maxRecDepth - 1)])
           appf(result, "$N$1]", [istr])
       appf(result, ",$N$1\"typ\": $2", 
            [istr, typeToYamlAux(n.typ, marker, indent + 2, maxRecDepth)])
-    appf(result, "$N$1}", [spaces(indent)])
+    appf(result, "$N$1}", [rspaces(indent)])
 
 proc treeToYaml(n: PNode, indent: int = 0, maxRecDepth: int = - 1): PRope = 
   var marker = initIntSet()
@@ -408,7 +408,7 @@ proc debugTree(n: PNode, indent: int, maxRecDepth: int;
   if n == nil: 
     result = toRope("null")
   else: 
-    var istr = spaces(indent + 2)
+    var istr = rspaces(indent + 2)
     result = ropef("{$N$1\"kind\": $2", 
                    [istr, makeYamlString($n.kind)])
     if maxRecDepth != 0: 
@@ -440,11 +440,11 @@ proc debugTree(n: PNode, indent: int, maxRecDepth: int;
           appf(result, ",$N$1\"sons\": [", [istr])
           for i in countup(0, sonsLen(n) - 1): 
             if i > 0: app(result, ",")
-            appf(result, "$N$1$2", [spaces(indent + 4), debugTree(n.sons[i], 
+            appf(result, "$N$1$2", [rspaces(indent + 4), debugTree(n.sons[i], 
                 indent + 4, maxRecDepth - 1, renderType)])
           appf(result, "$N$1]", [istr])
     appf(result, ",$N$1\"info\": $2", [istr, lineInfoToStr(n.info)])
-    appf(result, "$N$1}", [spaces(indent)])
+    appf(result, "$N$1}", [rspaces(indent)])
 
 proc debug(n: PSym) =
   if n == nil:
diff --git a/compiler/ccgexprs.nim b/compiler/ccgexprs.nim
index 5f5aa6308..564d1fd36 100644
--- a/compiler/ccgexprs.nim
+++ b/compiler/ccgexprs.nim
@@ -949,7 +949,7 @@ proc genEcho(p: BProc, n: PNode) =
     initLocExpr(p, n.sons[i], a)
     appf(args, ", $1? ($1)->data:\"nil\"", [rdLoc(a)])
   linefmt(p, cpsStmts, "printf($1$2);$n",
-          makeCString(repeatStr(n.len, "%s") & tnl), args)
+          makeCString(repeat("%s", n.len) & tnl), args)
 
 proc gcUsage(n: PNode) =
   if gSelectedGC == gcNone: message(n.info, warnGcMem, n.renderTree)
diff --git a/compiler/ccgutils.nim b/compiler/ccgutils.nim
index 59b9611fc..25c1a12e5 100644
--- a/compiler/ccgutils.nim
+++ b/compiler/ccgutils.nim
@@ -9,31 +9,31 @@
 
 # This module declares some helpers for the C code generator.
 
-import 
-  ast, astalgo, ropes, lists, hashes, strutils, types, msgs, wordrecg, 
+import
+  ast, astalgo, ropes, lists, hashes, strutils, types, msgs, wordrecg,
   platform, trees
 
 proc getPragmaStmt*(n: PNode, w: TSpecialWord): PNode =
   case n.kind
-  of nkStmtList: 
-    for i in 0 .. < n.len: 
+  of nkStmtList:
+    for i in 0 .. < n.len:
       result = getPragmaStmt(n[i], w)
       if result != nil: break
   of nkPragma:
-    for i in 0 .. < n.len: 
+    for i in 0 .. < n.len:
       if whichPragma(n[i]) == w: return n[i]
   else: discard
 
 proc stmtsContainPragma*(n: PNode, w: TSpecialWord): bool =
   result = getPragmaStmt(n, w) != nil
 
-proc hashString*(s: string): BiggestInt = 
+proc hashString*(s: string): BiggestInt =
   # has to be the same algorithm as system.hashString!
-  if CPU[targetCPU].bit == 64: 
+  if CPU[targetCPU].bit == 64:
     # we have to use the same bitwidth
     # as the target CPU
     var b = 0'i64
-    for i in countup(0, len(s) - 1): 
+    for i in countup(0, len(s) - 1):
       b = b +% ord(s[i])
       b = b +% `shl`(b, 10)
       b = b xor `shr`(b, 6)
@@ -41,9 +41,9 @@ proc hashString*(s: string): BiggestInt =
     b = b xor `shr`(b, 11)
     b = b +% `shl`(b, 15)
     result = b
-  else: 
+  else:
     var a = 0'i32
-    for i in countup(0, len(s) - 1): 
+    for i in countup(0, len(s) - 1):
       a = a +% ord(s[i]).int32
       a = a +% `shl`(a, 10'i32)
       a = a xor `shr`(a, 6'i32)
@@ -52,11 +52,11 @@ proc hashString*(s: string): BiggestInt =
     a = a +% `shl`(a, 15'i32)
     result = a
 
-var 
+var
   gTypeTable: array[TTypeKind, TIdTable]
   gCanonicalTypes: array[TTypeKind, PType]
 
-proc initTypeTables() = 
+proc initTypeTables() =
   for i in countup(low(TTypeKind), high(TTypeKind)): initIdTable(gTypeTable[i])
 
 proc resetCaches* =
@@ -67,7 +67,7 @@ proc resetCaches* =
 
 when false:
   proc echoStats*() =
-    for i in countup(low(TTypeKind), high(TTypeKind)): 
+    for i in countup(low(TTypeKind), high(TTypeKind)):
       echo i, " ", gTypeTable[i].counter
 
 proc slowSearch(key: PType; k: TTypeKind): PType =
@@ -78,21 +78,21 @@ proc slowSearch(key: PType; k: TTypeKind): PType =
   if idTableHasObjectAsKey(gTypeTable[k], key): return key
   for h in countup(0, high(gTypeTable[k].data)):
     var t = PType(gTypeTable[k].data[h].key)
-    if t != nil and sameBackendType(t, key): 
+    if t != nil and sameBackendType(t, key):
       return t
   idTablePut(gTypeTable[k], key, key)
   result = key
 
-proc getUniqueType*(key: PType): PType = 
+proc getUniqueType*(key: PType): PType =
   # this is a hotspot in the compiler!
-  if key == nil: return 
+  if key == nil: return
   var k = key.kind
   case k
   of tyBool, tyChar, tyInt..tyUInt64:
     # no canonicalization for integral types, so that e.g. ``pid_t`` is
     # produced instead of ``NI``.
     result = key
-  of  tyEmpty, tyNil, tyExpr, tyStmt, tyPointer, tyString, 
+  of  tyEmpty, tyNil, tyExpr, tyStmt, tyPointer, tyString,
       tyCString, tyNone, tyBigNum:
     result = gCanonicalTypes[k]
     if result == nil:
@@ -127,7 +127,7 @@ proc getUniqueType*(key: PType): PType =
     if tfFromGeneric notin key.flags:
       # fast case; lookup per id suffices:
       result = PType(idTableGet(gTypeTable[k], key))
-      if result == nil: 
+      if result == nil:
         idTablePut(gTypeTable[k], key, key)
         result = key
     else:
@@ -138,10 +138,10 @@ proc getUniqueType*(key: PType): PType =
         if t != nil and sameBackendType(t, key):
           return t
       idTablePut(gTypeTable[k], key, key)
-      result = key    
+      result = key
   of tyEnum:
     result = PType(idTableGet(gTypeTable[k], key))
-    if result == nil: 
+    if result == nil:
       idTablePut(gTypeTable[k], key, key)
       result = key
   of tyProc:
@@ -151,16 +151,16 @@ proc getUniqueType*(key: PType): PType =
       # ugh, we need the canon here:
       result = slowSearch(key, k)
 
-proc tableGetType*(tab: TIdTable, key: PType): RootRef = 
+proc tableGetType*(tab: TIdTable, key: PType): RootRef =
   # returns nil if we need to declare this type
   result = idTableGet(tab, key)
-  if (result == nil) and (tab.counter > 0): 
+  if (result == nil) and (tab.counter > 0):
     # we have to do a slow linear search because types may need
     # to be compared by their structure:
-    for h in countup(0, high(tab.data)): 
+    for h in countup(0, high(tab.data)):
       var t = PType(tab.data[h].key)
-      if t != nil: 
-        if sameType(t, key): 
+      if t != nil:
+        if sameType(t, key):
           return tab.data[h].val
 
 proc makeSingleLineCString*(s: string): string =
@@ -193,16 +193,16 @@ proc mangle*(name: string): string =
     else:
       add(result, "HEX" & toHex(ord(c), 2))
 
-proc makeLLVMString*(s: string): PRope = 
+proc makeLLVMString*(s: string): PRope =
   const MaxLineLength = 64
   result = nil
   var res = "c\""
-  for i in countup(0, len(s) - 1): 
-    if (i + 1) mod MaxLineLength == 0: 
+  for i in countup(0, len(s) - 1):
+    if (i + 1) mod MaxLineLength == 0:
       app(result, toRope(res))
       setLen(res, 0)
     case s[i]
-    of '\0'..'\x1F', '\x80'..'\xFF', '\"', '\\': 
+    of '\0'..'\x1F', '\x80'..'\xFF', '\"', '\\':
       add(res, '\\')
       add(res, toHex(ord(s[i]), 2))
     else: add(res, s[i])
diff --git a/compiler/extccomp.nim b/compiler/extccomp.nim
index 5f6033e57..8888632b9 100644
--- a/compiler/extccomp.nim
+++ b/compiler/extccomp.nim
@@ -572,6 +572,9 @@ proc footprint(filename: string): TCrc32 =
       getCompileCFileCmd(filename, true)
 
 proc externalFileChanged(filename: string): bool = 
+  if gCmd notin {cmdCompileToC, cmdCompileToCpp, cmdCompileToOC, cmdCompileToLLVM}:
+    return false
+
   var crcFile = toGeneratedFile(filename.withPackageName, "crc")
   var currentCrc = int(footprint(filename))
   var f: File
diff --git a/compiler/filter_tmpl.nim b/compiler/filter_tmpl.nim
index 7b975dbaa..5d1f73be4 100644
--- a/compiler/filter_tmpl.nim
+++ b/compiler/filter_tmpl.nim
@@ -37,11 +37,11 @@ const
   PatternChars = {'a'..'z', 'A'..'Z', '0'..'9', '\x80'..'\xFF', '.', '_'}
 
 proc newLine(p: var TTmplParser) = 
-  llStreamWrite(p.outp, repeatChar(p.emitPar, ')'))
+  llStreamWrite(p.outp, repeat(')', p.emitPar))
   p.emitPar = 0
   if p.info.line > int16(1): llStreamWrite(p.outp, "\n")
   if p.pendingExprLine:
-    llStreamWrite(p.outp, repeatChar(2))
+    llStreamWrite(p.outp, spaces(2))
     p.pendingExprLine = false
   
 proc scanPar(p: var TTmplParser, d: int) = 
@@ -88,24 +88,24 @@ proc parseLine(p: var TTmplParser) =
       else: 
         p.info.col = int16(j)
         localError(p.info, errXNotAllowedHere, "end")
-      llStreamWrite(p.outp, repeatChar(p.indent))
+      llStreamWrite(p.outp, spaces(p.indent))
       llStreamWrite(p.outp, "#end")
     of wIf, wWhen, wTry, wWhile, wFor, wBlock, wCase, wProc, wIterator, 
        wConverter, wMacro, wTemplate, wMethod: 
-      llStreamWrite(p.outp, repeatChar(p.indent))
+      llStreamWrite(p.outp, spaces(p.indent))
       llStreamWrite(p.outp, substr(p.x, d))
       inc(p.indent, 2)
     of wElif, wOf, wElse, wExcept, wFinally: 
-      llStreamWrite(p.outp, repeatChar(p.indent - 2))
+      llStreamWrite(p.outp, spaces(p.indent - 2))
       llStreamWrite(p.outp, substr(p.x, d))
     of wLet, wVar, wConst, wType:
-      llStreamWrite(p.outp, repeatChar(p.indent))
+      llStreamWrite(p.outp, spaces(p.indent))
       llStreamWrite(p.outp, substr(p.x, d))
       if not p.x.contains({':', '='}):
         # no inline element --> treat as block:
         inc(p.indent, 2)
     else:
-      llStreamWrite(p.outp, repeatChar(p.indent))
+      llStreamWrite(p.outp, spaces(p.indent))
       llStreamWrite(p.outp, substr(p.x, d))
     p.state = psDirective
   else: 
@@ -120,11 +120,11 @@ proc parseLine(p: var TTmplParser) =
       # next line of string literal:
       llStreamWrite(p.outp, p.conc)
       llStreamWrite(p.outp, "\n")
-      llStreamWrite(p.outp, repeatChar(p.indent + 2))
+      llStreamWrite(p.outp, spaces(p.indent + 2))
       llStreamWrite(p.outp, "\"")
     of psDirective: 
       newLine(p)
-      llStreamWrite(p.outp, repeatChar(p.indent))
+      llStreamWrite(p.outp, spaces(p.indent))
       llStreamWrite(p.outp, p.emit)
       llStreamWrite(p.outp, "(\"")
       inc(p.emitPar)
diff --git a/compiler/importer.nim b/compiler/importer.nim
index fbf3be4f2..57a1e542b 100644
--- a/compiler/importer.nim
+++ b/compiler/importer.nim
@@ -27,7 +27,7 @@ proc getModuleName*(n: PNode): string =
     result = n.ident.s
   of nkSym:
     result = n.sym.name.s
-  of nkInfix:
+  of nkInfix, nkPrefix:
     if n.sons[0].kind == nkIdent and n.sons[0].ident.id == getIdent("as").id:
       # XXX hack ahead:
       n.kind = nkImportAs
diff --git a/compiler/jsgen.nim b/compiler/jsgen.nim
index 34f842d4a..87847204f 100644
--- a/compiler/jsgen.nim
+++ b/compiler/jsgen.nim
@@ -780,7 +780,7 @@ proc genIf(p: PProc, n: PNode, r: var TCompRes) =
     moveInto(p, stmt, r)
     appf(p.body, "}$n" | "end$n")
   if p.target == targetJS:
-    app(p.body, repeatChar(toClose, '}') & tnl)
+    app(p.body, repeat('}', toClose) & tnl)
   else:
     for i in 1..toClose: appf(p.body, "end$n")
 
diff --git a/compiler/msgs.nim b/compiler/msgs.nim
index a72dedf57..e15cdc86d 100644
--- a/compiler/msgs.nim
+++ b/compiler/msgs.nim
@@ -784,7 +784,7 @@ proc rawMessage*(msg: TMsgKind, arg: string) =
 proc writeSurroundingSrc(info: TLineInfo) =
   const indent = "  "
   msgWriteln(indent & info.sourceLine.ropeToStr)
-  msgWriteln(indent & repeatChar(info.col, ' ') & '^')
+  msgWriteln(indent & spaces(info.col) & '^')
 
 proc formatMsg*(info: TLineInfo, msg: TMsgKind, arg: string): string =
   let frmt = case msg
diff --git a/compiler/nimlexbase.nim b/compiler/nimlexbase.nim
index e18e1c22a..f5db5ca4f 100644
--- a/compiler/nimlexbase.nim
+++ b/compiler/nimlexbase.nim
@@ -166,4 +166,4 @@ proc getCurrentLine(L: TBaseLexer, marker: bool = true): string =
     inc(i)
   result.add("\n")
   if marker: 
-    result.add(repeatChar(getColNumber(L, L.bufpos)) & '^' & "\n")
+    result.add(spaces(getColNumber(L, L.bufpos)) & '^' & "\n")
diff --git a/compiler/renderer.nim b/compiler/renderer.nim
index 204bfbf94..f5cabb4bc 100644
--- a/compiler/renderer.nim
+++ b/compiler/renderer.nim
@@ -92,7 +92,7 @@ proc addTok(g: var TSrcGen, kind: TTokType, s: string) =
 
 proc addPendingNL(g: var TSrcGen) = 
   if g.pendingNL >= 0: 
-    addTok(g, tkSpaces, "\n" & repeatChar(g.pendingNL))
+    addTok(g, tkSpaces, "\n" & spaces(g.pendingNL))
     g.lineLen = g.pendingNL
     g.pendingNL = - 1
 
@@ -190,7 +190,7 @@ proc putComment(g: var TSrcGen, s: string) =
       if not isCode and (g.lineLen + (j - i) > MaxLineLen): 
         put(g, tkComment, com)
         optNL(g, ind)
-        com = '#' & repeatChar(comIndent)
+        com = '#' & spaces(comIndent)
       while s[i] > ' ': 
         add(com, s[i])
         inc(i)
@@ -280,7 +280,7 @@ proc gcom(g: var TSrcGen, n: PNode) =
         (g.lineLen < LineCommentColumn): 
       var ml = maxLineLength(n.comment)
       if ml + LineCommentColumn <= MaxLineLen: 
-        put(g, tkSpaces, repeatChar(LineCommentColumn - g.lineLen))
+        put(g, tkSpaces, spaces(LineCommentColumn - g.lineLen))
     putComment(g, n.comment)  #assert(g.comStack[high(g.comStack)] = n);
   
 proc gcoms(g: var TSrcGen) = 
diff --git a/compiler/sem.nim b/compiler/sem.nim
index a90948245..36c0342cd 100644
--- a/compiler/sem.nim
+++ b/compiler/sem.nim
@@ -65,8 +65,8 @@ template semIdeForTemplateOrGeneric(c: PContext; n: PNode;
         echo "passing to safeSemExpr: ", renderTree(n)
       discard safeSemExpr(c, n)
 
-proc typeMismatch(n: PNode, formal, actual: PType) = 
-  if formal.kind != tyError and actual.kind != tyError: 
+proc typeMismatch(n: PNode, formal, actual: PType) =
+  if formal.kind != tyError and actual.kind != tyError:
     localError(n.info, errGenerated, msgKindToString(errTypeMismatch) &
         typeToString(actual) & ") " &
         `%`(msgKindToString(errButExpectedX), [typeToString(formal)]))
@@ -113,7 +113,7 @@ proc commonType*(x, y: PType): PType =
     else:
       result = newType(tyTypeDesc, a.owner)
       rawAddSon(result, newType(tyNone, a.owner))
-  elif b.kind in {tyArray, tyArrayConstr, tySet, tySequence} and 
+  elif b.kind in {tyArray, tyArrayConstr, tySet, tySequence} and
       a.kind == b.kind:
     # check for seq[empty] vs. seq[int]
     let idx = ord(b.kind in {tyArray, tyArrayConstr})
@@ -163,7 +163,7 @@ proc commonType*(x, y: PType): PType =
         result = newType(k, r.owner)
         result.addSonSkipIntLit(r)
 
-proc newSymS(kind: TSymKind, n: PNode, c: PContext): PSym = 
+proc newSymS(kind: TSymKind, n: PNode, c: PContext): PSym =
   result = newSym(kind, considerQuotedIdent(n), getCurrOwner(), n.info)
 
 proc newSymG*(kind: TSymKind, n: PNode, c: PContext): PSym =
@@ -182,7 +182,7 @@ proc newSymG*(kind: TSymKind, n: PNode, c: PContext): PSym =
 proc semIdentVis(c: PContext, kind: TSymKind, n: PNode,
                  allowed: TSymFlags): PSym
   # identifier with visability
-proc semIdentWithPragma(c: PContext, kind: TSymKind, n: PNode, 
+proc semIdentWithPragma(c: PContext, kind: TSymKind, n: PNode,
                         allowed: TSymFlags): PSym
 proc semStmtScope(c: PContext, n: PNode): PNode
 
@@ -190,7 +190,7 @@ proc typeAllowedCheck(info: TLineInfo; typ: PType; kind: TSymKind) =
   let t = typeAllowed(typ, kind)
   if t != nil:
     if t == typ: localError(info, "invalid type: '" & typeToString(typ) & "'")
-    else: localError(info, "invalid type: '" & typeToString(t) & 
+    else: localError(info, "invalid type: '" & typeToString(t) &
                            "' in this context: '" & typeToString(typ) & "'")
 
 proc paramsTypeCheck(c: PContext, typ: PType) {.inline.} =
@@ -226,7 +226,7 @@ when false:
         result = newSymNode(getSysSym"void")
       else:
         result.typ = makeTypeDesc(c, result.typ)
-    
+
     result.handleIsOperator = proc (n: PNode): PNode =
       result = isOpImpl(c, n)
 
@@ -248,7 +248,7 @@ proc fixupTypeAfterEval(c: PContext, evaluated, eOrig: PNode): PNode =
     if result == nil:
       result = arg
       # for 'tcnstseq' we support [] to become 'seq'
-      if eOrig.typ.skipTypes(abstractInst).kind == tySequence and 
+      if eOrig.typ.skipTypes(abstractInst).kind == tySequence and
          arg.typ.skipTypes(abstractInst).kind == tyArrayConstr:
         arg.typ = eOrig.typ
 
@@ -320,7 +320,7 @@ proc semAfterMacroCall(c: PContext, n: PNode, s: PSym,
   else:
     case s.typ.sons[0].kind
     of tyExpr:
-      # BUGFIX: we cannot expect a type here, because module aliases would not 
+      # BUGFIX: we cannot expect a type here, because module aliases would not
       # work then (see the ``tmodulealias`` test)
       # semExprWithType(c, result)
       result = semExpr(c, result, flags)
@@ -355,18 +355,18 @@ proc semMacroExpr(c: PContext, n, nOrig: PNode, sym: PSym,
     result = semAfterMacroCall(c, result, sym, flags)
   popInfoContext()
 
-proc forceBool(c: PContext, n: PNode): PNode = 
+proc forceBool(c: PContext, n: PNode): PNode =
   result = fitNode(c, getSysType(tyBool), n)
   if result == nil: result = n
 
-proc semConstBoolExpr(c: PContext, n: PNode): PNode = 
+proc semConstBoolExpr(c: PContext, n: PNode): PNode =
   let nn = semExprWithType(c, n)
   result = fitNode(c, getSysType(tyBool), nn)
   if result == nil:
     localError(n.info, errConstExprExpected)
     return nn
   result = getConstExpr(c.module, result)
-  if result == nil: 
+  if result == nil:
     localError(n.info, errConstExprExpected)
     result = nn
 
@@ -403,9 +403,9 @@ proc myOpen(module: PSym): PPassContext =
   pushOwner(c.module)
   c.importTable = openScope(c)
   c.importTable.addSym(module) # a module knows itself
-  if sfSystemModule in module.flags: 
+  if sfSystemModule in module.flags:
     magicsys.systemModule = module # set global variable!
-  else: 
+  else:
     c.importTable.addSym magicsys.systemModule # import the "System" identifier
     importAllSymbols(c, magicsys.systemModule)
   c.topLevelScope = openScope(c)
@@ -415,13 +415,13 @@ proc myOpenCached(module: PSym, rd: PRodReader): PPassContext =
   result = myOpen(module)
   for m in items(rd.methods): methodDef(m, true)
 
-proc semStmtAndGenerateGenerics(c: PContext, n: PNode): PNode = 
+proc semStmtAndGenerateGenerics(c: PContext, n: PNode): PNode =
   result = semStmt(c, n)
   # BUGFIX: process newly generated generics here, not at the end!
   if c.lastGenericIdx < c.generics.len:
     var a = newNodeI(nkStmtList, n.info)
     addCodeForGenerics(c, a)
-    if sonsLen(a) > 0: 
+    if sonsLen(a) > 0:
       # a generic has been added to `a`:
       if result.kind != nkEmpty: addSon(a, result)
       result = a
@@ -429,17 +429,17 @@ proc semStmtAndGenerateGenerics(c: PContext, n: PNode): PNode =
   if gCmd == cmdInteractive and not isEmptyType(result.typ):
     result = buildEchoStmt(c, result)
   result = transformStmt(c.module, result)
-    
-proc recoverContext(c: PContext) = 
+
+proc recoverContext(c: PContext) =
   # clean up in case of a semantic error: We clean up the stacks, etc. This is
-  # faster than wrapping every stack operation in a 'try finally' block and 
+  # faster than wrapping every stack operation in a 'try finally' block and
   # requires far less code.
   c.currentScope = c.topLevelScope
   while getCurrOwner().kind != skModule: popOwner()
   while c.p != nil and c.p.owner.kind != skModule: c.p = c.p.next
 
-proc myProcess(context: PPassContext, n: PNode): PNode = 
-  var c = PContext(context)    
+proc myProcess(context: PPassContext, n: PNode): PNode =
+  var c = PContext(context)
   # no need for an expensive 'try' if we stop after the first error anyway:
   if msgs.gErrorMax <= 1:
     result = semStmtAndGenerateGenerics(c, n)
@@ -455,8 +455,8 @@ proc myProcess(context: PPassContext, n: PNode): PNode =
       if getCurrentException() of ESuggestDone: result = nil
       else: result = ast.emptyNode
       #if gCmd == cmdIdeTools: findSuggest(c, n)
-    
-proc myClose(context: PPassContext, n: PNode): PNode = 
+
+proc myClose(context: PPassContext, n: PNode): PNode =
   var c = PContext(context)
   closeScope(c)         # close module's scope
   rawCloseScope(c)      # imported symbols; don't check for unused ones!
diff --git a/compiler/semcall.nim b/compiler/semcall.nim
index d92e1ab20..647e75b3a 100644
--- a/compiler/semcall.nim
+++ b/compiler/semcall.nim
@@ -7,16 +7,16 @@
 #    distribution, for details about the copyright.
 #
 
-## This module implements semantic checking for calls. 
+## This module implements semantic checking for calls.
 # included from sem.nim
 
 proc sameMethodDispatcher(a, b: PSym): bool =
   result = false
-  if a.kind == skMethod and b.kind == skMethod: 
+  if a.kind == skMethod and b.kind == skMethod:
     var aa = lastSon(a.ast)
     var bb = lastSon(b.ast)
     if aa.kind == nkSym and bb.kind == nkSym:
-      if aa.sym == bb.sym: 
+      if aa.sym == bb.sym:
         result = true
     else:
       discard
@@ -31,7 +31,7 @@ proc sameMethodDispatcher(a, b: PSym): bool =
       # to avoid subtle problems, the call remains ambiguous and needs to
       # be disambiguated by the programmer; this way the right generic is
       # instantiated.
-  
+
 proc determineType(c: PContext, s: PSym)
 
 proc pickBestCandidate(c: PContext, headSymbol: PNode,
@@ -41,73 +41,80 @@ proc pickBestCandidate(c: PContext, headSymbol: PNode,
                        best, alt: var TCandidate,
                        errors: var CandidateErrors) =
   var o: TOverloadIter
-  var sym = initOverloadIter(o, c, headSymbol)
+  # thanks to the lazy semchecking for operands, we need to iterate over the
+  # symbol table *before* any call to 'initCandidate' which might invoke
+  # semExpr which might modify the symbol table in cases like
+  # 'init(a, 1, (var b = new(Type2); b))'.
+  var symx = initOverloadIter(o, c, headSymbol)
   let symScope = o.lastOverloadScope
 
+  var syms: seq[tuple[a: PSym, b: int]] = @[]
+  while symx != nil:
+    if symx.kind in filter: syms.add((symx, o.lastOverloadScope))
+    symx = nextOverloadIter(o, c, headSymbol)
+  if syms.len == 0: return
+
   var z: TCandidate
-  
-  if sym == nil: return
-  initCandidate(c, best, sym, initialBinding, symScope)
-  initCandidate(c, alt, sym, initialBinding, symScope)
+  initCandidate(c, best, syms[0][0], initialBinding, symScope)
+  initCandidate(c, alt, syms[0][0], initialBinding, symScope)
   best.state = csNoMatch
-  
-  while sym != nil:
-    if sym.kind in filter:
-      determineType(c, sym)
-      initCandidate(c, z, sym, initialBinding, o.lastOverloadScope)
-      z.calleeSym = sym
 
+  for i in 0 .. <syms.len:
+    let sym = syms[i][0]
+    determineType(c, sym)
+    initCandidate(c, z, sym, initialBinding, syms[i][1])
+    z.calleeSym = sym
+
+    #if sym.name.s == "*" and (n.info ?? "temp5.nim") and n.info.line == 140:
+    #  gDebug = true
+    matches(c, n, orig, z)
+    if errors != nil:
+      errors.safeAdd(sym)
+      if z.errors != nil:
+        for err in z.errors:
+          errors.add(err)
+    if z.state == csMatch:
+      # little hack so that iterators are preferred over everything else:
+      if sym.kind in skIterators: inc(z.exactMatches, 200)
+      case best.state
+      of csEmpty, csNoMatch: best = z
+      of csMatch:
+        var cmp = cmpCandidates(best, z)
+        if cmp < 0: best = z   # x is better than the best so far
+        elif cmp == 0: alt = z # x is as good as the best so far
+        else: discard
       #if sym.name.s == "*" and (n.info ?? "temp5.nim") and n.info.line == 140:
-      #  gDebug = true
-      matches(c, n, orig, z)
-      if errors != nil:
-        errors.safeAdd(sym)
-        if z.errors != nil:
-          for err in z.errors:
-            errors.add(err)
-      if z.state == csMatch:
-        # little hack so that iterators are preferred over everything else:
-        if sym.kind in skIterators: inc(z.exactMatches, 200)
-        case best.state
-        of csEmpty, csNoMatch: best = z
-        of csMatch:
-          var cmp = cmpCandidates(best, z)
-          if cmp < 0: best = z   # x is better than the best so far
-          elif cmp == 0: alt = z # x is as good as the best so far
-          else: discard
-        #if sym.name.s == "*" and (n.info ?? "temp5.nim") and n.info.line == 140:
-        #  echo "Matches ", n.info, " ", typeToString(sym.typ)
-        #  debug sym
-        #  writeMatches(z)
-        #  for i in 1 .. <len(z.call):
-        #    z.call[i].typ.debug
-        #  quit 1
-    sym = nextOverloadIter(o, c, headSymbol)
+      #  echo "Matches ", n.info, " ", typeToString(sym.typ)
+      #  debug sym
+      #  writeMatches(z)
+      #  for i in 1 .. <len(z.call):
+      #    z.call[i].typ.debug
+      #  quit 1
 
 proc notFoundError*(c: PContext, n: PNode, errors: CandidateErrors) =
   # Gives a detailed error message; this is separated from semOverloadedCall,
   # as semOverlodedCall is already pretty slow (and we need this information
   # only in case of an error).
-  if c.inCompilesContext > 0: 
+  if c.inCompilesContext > 0:
     # fail fast:
     globalError(n.info, errTypeMismatch, "")
   if errors.isNil or errors.len == 0:
     localError(n.info, errExprXCannotBeCalled, n[0].renderTree)
     return
 
-  # to avoid confusing errors like: 
+  # to avoid confusing errors like:
   #   got (SslPtr, SocketHandle)
-  #   but expected one of: 
+  #   but expected one of:
   #   openssl.SSL_set_fd(ssl: SslPtr, fd: SocketHandle): cint
   # we do a pre-analysis. If all types produce the same string, we will add
   # module information.
   let proto = describeArgs(c, n, 1, preferName)
-  
+
   var prefer = preferName
   for err in errors:
     var errProto = ""
     let n = err.typ.n
-    for i in countup(1, n.len - 1): 
+    for i in countup(1, n.len - 1):
       var p = n.sons[i]
       if p.kind == nkSym:
         add(errProto, typeToString(p.sym.typ, preferName))
@@ -159,9 +166,9 @@ proc resolveOverloads(c: PContext, n, orig: PNode,
 
     n.sons.insert(hiddenArg, 1)
     orig.sons.insert(hiddenArg, 1)
-    
+
     pickBest(f)
- 
+
     if result.state != csMatch:
       n.sons.delete(1)
       orig.sons.delete(1)
@@ -179,7 +186,7 @@ proc resolveOverloads(c: PContext, n, orig: PNode,
       # we are going to try multiple variants
       n.sons[0..1] = [nil, n[1], calleeName]
       orig.sons[0..1] = [nil, orig[1], calleeName]
-      
+
       template tryOp(x) =
         let op = newIdentNode(getIdent(x), n.info)
         n.sons[0] = op
@@ -188,7 +195,7 @@ proc resolveOverloads(c: PContext, n, orig: PNode,
 
       if nfExplicitCall in n.flags:
         tryOp ".()"
-   
+
       if result.state in {csEmpty, csNoMatch}:
         tryOp "."
 
@@ -199,7 +206,7 @@ proc resolveOverloads(c: PContext, n, orig: PNode,
       n.sons[0..1] = [callOp, n[1], calleeName]
       orig.sons[0..1] = [callOp, orig[1], calleeName]
       pickBest(callOp)
-   
+
     if overloadsState == csEmpty and result.state == csEmpty:
       localError(n.info, errUndeclaredIdentifier, considerQuotedIdent(f).s)
       return
@@ -224,7 +231,7 @@ proc resolveOverloads(c: PContext, n, orig: PNode,
     internalAssert result.state == csMatch
     #writeMatches(result)
     #writeMatches(alt)
-    if c.inCompilesContext > 0: 
+    if c.inCompilesContext > 0:
       # quick error message for performance of 'compiles' built-in:
       globalError(n.info, errGenerated, "ambiguous call")
     elif gErrorCounter == 0:
@@ -254,7 +261,7 @@ proc instGenericConvertersSons*(c: PContext, n: PNode, x: TCandidate) =
     for i in 1 .. <n.len:
       instGenericConvertersArg(c, n.sons[i], x)
 
-proc indexTypesMatch(c: PContext, f, a: PType, arg: PNode): PNode = 
+proc indexTypesMatch(c: PContext, f, a: PType, arg: PNode): PNode =
   var m: TCandidate
   initCandidate(c, m, f)
   result = paramTypesMatch(m, f, a, arg, nil)
@@ -325,7 +332,7 @@ proc semOverloadedCall(c: PContext, n, nOrig: PNode,
       # get rid of the deref again for a better error message:
       n.sons[1] = n.sons[1].sons[0]
       notFoundError(c, n, errors)
-  else: 
+  else:
     notFoundError(c, n, errors)
   # else: result = errorNode(c, n)
 
@@ -341,7 +348,7 @@ proc explicitGenericSym(c: PContext, n: PNode, s: PSym): PNode =
   styleCheckUse(n.info, s)
   result = newSymNode(newInst, n.info)
 
-proc explicitGenericInstantiation(c: PContext, n: PNode, s: PSym): PNode = 
+proc explicitGenericInstantiation(c: PContext, n: PNode, s: PSym): PNode =
   assert n.kind == nkBracketExpr
   for i in 1..sonsLen(n)-1:
     n.sons[i].typ = semTypeNode(c, n.sons[i], nil)
@@ -361,11 +368,11 @@ proc explicitGenericInstantiation(c: PContext, n: PNode, s: PSym): PNode =
     # XXX I think this could be improved by reusing sigmatch.paramTypesMatch.
     # It's good enough for now.
     result = newNodeI(a.kind, n.info)
-    for i in countup(0, len(a)-1): 
+    for i in countup(0, len(a)-1):
       var candidate = a.sons[i].sym
       if candidate.kind in {skProc, skMethod, skConverter,
                             skIterator, skClosureIterator}:
-        # it suffices that the candidate has the proper number of generic 
+        # it suffices that the candidate has the proper number of generic
         # type parameters:
         if safeLen(candidate.ast.sons[genericParamsPos]) == n.len-1:
           result.add(explicitGenericSym(c, n, candidate))
diff --git a/compiler/sigmatch.nim b/compiler/sigmatch.nim
index a1b5c8dc9..f34bdd3da 100644
--- a/compiler/sigmatch.nim
+++ b/compiler/sigmatch.nim
@@ -10,7 +10,7 @@
 ## This module implements the signature matching for resolving
 ## the call to overloaded procs, generic procs and operators.
 
-import 
+import
   intsets, ast, astalgo, semdata, types, msgs, renderer, lookups, semtypinst,
   magicsys, condsyms, idents, lexer, options, parampatterns, strutils, trees,
   nimfix.pretty
@@ -19,7 +19,7 @@ when not defined(noDocgen):
   import docgen
 
 type
-  TCandidateState* = enum 
+  TCandidateState* = enum
     csEmpty, csMatch, csNoMatch
 
   CandidateErrors* = seq[PSym]
@@ -62,10 +62,10 @@ type
     isGeneric,
     isFromIntLit,            # conversion *from* int literal; proven safe
     isEqual
-  
+
 const
   isNilConversion = isConvertible # maybe 'isIntConv' fits better?
-    
+
 proc markUsed*(info: TLineInfo, s: PSym)
 
 template hasFauxMatch*(c: TCandidate): bool = c.fauxMatch != tyNone
@@ -128,7 +128,7 @@ proc newCandidate*(ctx: PContext, callee: PSym,
 proc newCandidate*(ctx: PContext, callee: PType): TCandidate =
   initCandidate(ctx, result, callee)
 
-proc copyCandidate(a: var TCandidate, b: TCandidate) = 
+proc copyCandidate(a: var TCandidate, b: TCandidate) =
   a.c = b.c
   a.exactMatches = b.exactMatches
   a.subtypeMatches = b.subtypeMatches
@@ -176,7 +176,7 @@ proc complexDisambiguation(a, b: PType): int =
       let bb = b.sons[1].sumGeneric
       var a = a
       var b = b
-      
+
       if aa < bb: swap(a, b)
       # all must be better
       for i in 2 .. <min(a.len, b.len):
@@ -203,7 +203,7 @@ proc cmpCandidates*(a, b: TCandidate): int =
   # prefer more specialized generic over more general generic:
   result = complexDisambiguation(a.callee, b.callee)
 
-proc writeMatches*(c: TCandidate) = 
+proc writeMatches*(c: TCandidate) =
   writeln(stdout, "exact matches: " & $c.exactMatches)
   writeln(stdout, "generic matches: " & $c.genericMatches)
   writeln(stdout, "subtype matches: " & $c.subtypeMatches)
@@ -225,7 +225,7 @@ proc describeArgs*(c: PContext, n: PNode, startIdx = 1;
   result = ""
   for i in countup(startIdx, n.len - 1):
     var arg = n.sons[i]
-    if n.sons[i].kind == nkExprEqExpr: 
+    if n.sons[i].kind == nkExprEqExpr:
       add(result, renderTree(n.sons[i].sons[0]))
       add(result, ": ")
       if arg.typ.isNil:
@@ -241,9 +241,9 @@ proc describeArgs*(c: PContext, n: PNode, startIdx = 1;
     if i != sonsLen(n) - 1: add(result, ", ")
 
 proc typeRel*(c: var TCandidate, f, aOrig: PType, doBind = true): TTypeRelation
-proc concreteType(c: TCandidate, t: PType): PType = 
+proc concreteType(c: TCandidate, t: PType): PType =
   case t.kind
-  of tyArrayConstr: 
+  of tyArrayConstr:
     # make it an array
     result = newType(tyArray, t.owner)
     addSonSkipIntLit(result, t.sons[0]) # XXX: t.owner is wrong for ID!
@@ -255,7 +255,7 @@ proc concreteType(c: TCandidate, t: PType): PType =
     else: result = t
   of tyGenericParam, tyAnything:
     result = t
-    while true: 
+    while true:
       result = PType(idTableGet(c.bindings, t))
       if result == nil:
         break # it's ok, no match
@@ -267,15 +267,15 @@ proc concreteType(c: TCandidate, t: PType): PType =
     result = t
   else:
     result = t                # Note: empty is valid here
-  
-proc handleRange(f, a: PType, min, max: TTypeKind): TTypeRelation = 
-  if a.kind == f.kind: 
+
+proc handleRange(f, a: PType, min, max: TTypeKind): TTypeRelation =
+  if a.kind == f.kind:
     result = isEqual
   else:
     let ab = skipTypes(a, {tyRange})
     let k = ab.kind
     if k == f.kind: result = isSubrange
-    elif k == tyInt and f.kind in {tyRange, tyInt8..tyInt64, 
+    elif k == tyInt and f.kind in {tyRange, tyInt8..tyInt64,
                                    tyUInt..tyUInt64} and
         isIntLit(ab) and ab.n.intVal >= firstOrd(f) and
                          ab.n.intVal <= lastOrd(f):
@@ -286,7 +286,7 @@ proc handleRange(f, a: PType, min, max: TTypeKind): TTypeRelation =
       result = isIntConv
     elif k >= min and k <= max:
       result = isConvertible
-    elif a.kind == tyRange and a.sons[0].kind in {tyInt..tyInt64, 
+    elif a.kind == tyRange and a.sons[0].kind in {tyInt..tyInt64,
                                                   tyUInt8..tyUInt32} and
                          a.n[0].intVal >= firstOrd(f) and
                          a.n[1].intVal <= lastOrd(f):
@@ -318,12 +318,12 @@ proc handleFloatRange(f, a: PType): TTypeRelation =
       if f.kind == tyFloat32: result = isConvertible
       else: result = isIntConv
     else: result = isNone
-  
+
 proc isObjectSubtype(a, f: PType): int =
   var t = a
   assert t.kind == tyObject
   var depth = 0
-  while t != nil and not sameObjectTypes(f, t): 
+  while t != nil and not sameObjectTypes(f, t):
     assert t.kind == tyObject
     t = t.sons[0]
     if t == nil: break
@@ -332,17 +332,17 @@ proc isObjectSubtype(a, f: PType): int =
   if t != nil:
     result = depth
 
-proc minRel(a, b: TTypeRelation): TTypeRelation = 
+proc minRel(a, b: TTypeRelation): TTypeRelation =
   if a <= b: result = a
   else: result = b
-  
+
 proc recordRel(c: var TCandidate, f, a: PType): TTypeRelation =
   result = isNone
   if sameType(f, a): result = isEqual
   elif sonsLen(a) == sonsLen(f):
     result = isEqual
     let firstField = if f.kind == tyTuple: 0
-                     else: 1 
+                     else: 1
     for i in countup(firstField, sonsLen(f) - 1):
       var m = typeRel(c, f.sons[i], a.sons[i])
       if m < isSubtype: return isNone
@@ -373,7 +373,7 @@ proc procParamTypeRel(c: var TCandidate, f, a: PType): TTypeRelation =
       # We are matching a generic proc (as proc param)
       # to another generic type appearing in the proc
       # signature. There is a change that the target
-      # type is already fully-determined, so we are 
+      # type is already fully-determined, so we are
       # going to try resolve it
       f = generateTypeInstance(c.c, c.bindings, c.call.info, f)
       if f == nil or f.isMetaType:
@@ -388,17 +388,17 @@ proc procParamTypeRel(c: var TCandidate, f, a: PType): TTypeRelation =
 
   if result <= isSubtype or inconsistentVarTypes(f, a):
     result = isNone
- 
+
   if result == isEqual:
     inc c.exactMatches
-    
+
 proc procTypeRel(c: var TCandidate, f, a: PType): TTypeRelation =
   case a.kind
   of tyProc:
     if sonsLen(f) != sonsLen(a): return
     result = isEqual      # start with maximum; also correct for no
                           # params at all
-    
+
     template checkParam(f, a) =
       result = minRel(result, procParamTypeRel(c, f, a))
       if result == isNone: return
@@ -407,7 +407,7 @@ proc procTypeRel(c: var TCandidate, f, a: PType): TTypeRelation =
     # return type!
     for i in 1 .. <f.sonsLen:
       checkParam(f.sons[i], a.sons[i])
-    
+
     if f.sons[0] != nil:
       if a.sons[0] != nil:
         checkParam(f.sons[0], a.sons[0])
@@ -487,14 +487,14 @@ proc matchUserTypeClass*(c: PContext, m: var TCandidate,
       else:
         param = paramSym skType
         param.typ = makeTypeDesc(c, typ)
-      
+
       addDecl(c, param)
 
   for param in body.n[0]:
     var
       dummyName: PNode
       dummyType: PType
-    
+
     if param.kind == nkVarTy:
       dummyName = param[0]
       dummyType = if a.kind != tyVar: makeVarType(c, a)
@@ -520,7 +520,7 @@ proc matchUserTypeClass*(c: PContext, m: var TCandidate,
       of nkTypeSection: discard
       of nkConstDef: discard
       else: discard
-    
+
   return isGeneric
 
 proc shouldSkipDistinct(rules: PNode, callIdent: PIdent): bool =
@@ -554,7 +554,7 @@ proc typeRel(c: var TCandidate, f, aOrig: PType, doBind = true): TTypeRelation =
   # typeRel can be used to establish various relationships between types:
   #
   # 1) When used with concrete types, it will check for type equivalence
-  # or a subtype relationship. 
+  # or a subtype relationship.
   #
   # 2) When used with a concrete type against a type class (such as generic
   # signature of a proc), it will check whether the concrete type is a member
@@ -569,7 +569,7 @@ proc typeRel(c: var TCandidate, f, aOrig: PType, doBind = true): TTypeRelation =
 
   result = isNone
   assert(f != nil)
-  
+
   if f.kind == tyExpr:
     if aOrig != nil: put(c.bindings, f, aOrig)
     return isGeneric
@@ -582,7 +582,7 @@ proc typeRel(c: var TCandidate, f, aOrig: PType, doBind = true): TTypeRelation =
   # start the param matching process. This could be done in `prepareOperand`
   # for example, but unfortunately `prepareOperand` is not called in certain
   # situation when nkDotExpr are rotated to nkDotCalls
-  
+
   if a.kind == tyGenericInst and
       skipTypes(f, {tyVar}).kind notin {
         tyGenericBody, tyGenericInvocation,
@@ -626,9 +626,9 @@ proc typeRel(c: var TCandidate, f, aOrig: PType, doBind = true): TTypeRelation =
       # seq[!int] vs seq[!number]
       # seq[float] matches the first, but not the second
       # we must turn the problem around:
-      # is number a subset of int? 
+      # is number a subset of int?
       return typeRel(c, a.lastSon, f.lastSon)
- 
+
     else:
       # negative type classes are essentially infinite,
       # so only the `any` type class is their superset
@@ -727,20 +727,20 @@ proc typeRel(c: var TCandidate, f, aOrig: PType, doBind = true): TTypeRelation =
     of tyOpenArray, tyVarargs:
       result = typeRel(c, base(f), base(a))
       if result < isGeneric: result = isNone
-    of tyArrayConstr: 
-      if (f.sons[0].kind != tyGenericParam) and (a.sons[1].kind == tyEmpty): 
+    of tyArrayConstr:
+      if (f.sons[0].kind != tyGenericParam) and (a.sons[1].kind == tyEmpty):
         result = isSubtype    # [] is allowed here
-      elif typeRel(c, base(f), a.sons[1]) >= isGeneric: 
+      elif typeRel(c, base(f), a.sons[1]) >= isGeneric:
         result = isSubtype
-    of tyArray: 
-      if (f.sons[0].kind != tyGenericParam) and (a.sons[1].kind == tyEmpty): 
+    of tyArray:
+      if (f.sons[0].kind != tyGenericParam) and (a.sons[1].kind == tyEmpty):
         result = isSubtype
-      elif typeRel(c, base(f), a.sons[1]) >= isGeneric: 
+      elif typeRel(c, base(f), a.sons[1]) >= isGeneric:
         result = isConvertible
-    of tySequence: 
-      if (f.sons[0].kind != tyGenericParam) and (a.sons[0].kind == tyEmpty): 
+    of tySequence:
+      if (f.sons[0].kind != tyGenericParam) and (a.sons[0].kind == tyEmpty):
         result = isConvertible
-      elif typeRel(c, base(f), a.sons[0]) >= isGeneric: 
+      elif typeRel(c, base(f), a.sons[0]) >= isGeneric:
         result = isConvertible
     else: discard
   of tySequence:
@@ -768,7 +768,7 @@ proc typeRel(c: var TCandidate, f, aOrig: PType, doBind = true): TTypeRelation =
   of tyForward: internalError("forward type in typeRel()")
   of tyNil:
     if a.kind == f.kind: result = isEqual
-  of tyTuple: 
+  of tyTuple:
     if a.kind == tyTuple: result = recordRel(c, f, a)
   of tyObject:
     if a.kind == tyObject:
@@ -783,13 +783,13 @@ proc typeRel(c: var TCandidate, f, aOrig: PType, doBind = true): TTypeRelation =
   of tyDistinct:
     if (a.kind == tyDistinct) and sameDistinctTypes(f, a): result = isEqual
     elif c.coerceDistincts: result = typeRel(c, f.base, a)
-  of tySet: 
-    if a.kind == tySet: 
-      if (f.sons[0].kind != tyGenericParam) and (a.sons[0].kind == tyEmpty): 
+  of tySet:
+    if a.kind == tySet:
+      if (f.sons[0].kind != tyGenericParam) and (a.sons[0].kind == tyEmpty):
         result = isSubtype
-      else: 
+      else:
         result = typeRel(c, f.sons[0], a.sons[0])
-        if result <= isConvertible: 
+        if result <= isConvertible:
           result = isNone     # BUGFIX!
   of tyPtr, tyRef:
     if a.kind == f.kind:
@@ -823,9 +823,9 @@ proc typeRel(c: var TCandidate, f, aOrig: PType, doBind = true): TTypeRelation =
       if a.len == 1: result = isConvertible
     of tyCString: result = isConvertible
     else: discard
-  of tyString: 
+  of tyString:
     case a.kind
-    of tyString: 
+    of tyString:
       if tfNotNil in f.flags and tfNotNil notin a.flags:
         result = isNilConversion
       else:
@@ -848,7 +848,7 @@ proc typeRel(c: var TCandidate, f, aOrig: PType, doBind = true): TTypeRelation =
     of tyArray:
       if (firstOrd(a.sons[0]) == 0) and
           (skipTypes(a.sons[0], {tyRange}).kind in {tyInt..tyInt64}) and
-          (a.sons[1].kind == tyChar): 
+          (a.sons[1].kind == tyChar):
         result = isConvertible
     else: discard
 
@@ -863,7 +863,7 @@ proc typeRel(c: var TCandidate, f, aOrig: PType, doBind = true): TTypeRelation =
         let ff = rootf.sons[i]
         let aa = roota.sons[i]
         result = typeRel(c, ff, aa)
-        if result == isNone: return        
+        if result == isNone: return
         if ff.kind == tyRange and result != isEqual: return isNone
       result = isGeneric
       # XXX See bug #2220. A[int] should match A[int] better than some generic X
@@ -883,13 +883,13 @@ proc typeRel(c: var TCandidate, f, aOrig: PType, doBind = true): TTypeRelation =
       #InternalError("typeRel: tyGenericInvocation -> tyGenericInvocation")
       # simply no match for now:
       discard
-    elif x.kind == tyGenericInst and 
+    elif x.kind == tyGenericInst and
           (f.sons[0] == x.sons[0]) and
           (sonsLen(x) - 1 == sonsLen(f)):
       for i in countup(1, sonsLen(f) - 1):
         if x.sons[i].kind == tyGenericParam:
           internalError("wrong instantiated type!")
-        elif typeRel(c, f.sons[i], x.sons[i]) <= isSubtype: return 
+        elif typeRel(c, f.sons[i], x.sons[i]) <= isSubtype: return
       result = isGeneric
     else:
       result = typeRel(c, f.sons[0], x)
@@ -900,7 +900,7 @@ proc typeRel(c: var TCandidate, f, aOrig: PType, doBind = true): TTypeRelation =
           if x == nil or x.kind in {tyGenericInvocation, tyGenericParam}:
             internalError("wrong instantiated type!")
           put(c.bindings, f.sons[i], x)
-  
+
   of tyAnd:
     considerPreviousT:
       for branch in f.sons:
@@ -914,7 +914,7 @@ proc typeRel(c: var TCandidate, f, aOrig: PType, doBind = true): TTypeRelation =
       for branch in f.sons:
         if typeRel(c, branch, aOrig) >= isSubtype:
           bindingRet isGeneric
-       
+
       return isNone
 
   of tyNot:
@@ -922,7 +922,7 @@ proc typeRel(c: var TCandidate, f, aOrig: PType, doBind = true): TTypeRelation =
       for branch in f.sons:
         if typeRel(c, branch, aOrig) != isNone:
           return isNone
-      
+
       bindingRet isGeneric
 
   of tyAnything:
@@ -961,7 +961,7 @@ proc typeRel(c: var TCandidate, f, aOrig: PType, doBind = true): TTypeRelation =
     if x == nil:
       if c.callee.kind == tyGenericBody and
          f.kind == tyGenericParam and not c.typedescMatched:
-        # XXX: The fact that generic types currently use tyGenericParam for 
+        # XXX: The fact that generic types currently use tyGenericParam for
         # their parameters is really a misnomer. tyGenericParam means "match
         # any value" and what we need is "match any type", which can be encoded
         # by a tyTypeDesc params. Unfortunately, this requires more substantial
@@ -1004,7 +1004,7 @@ proc typeRel(c: var TCandidate, f, aOrig: PType, doBind = true): TTypeRelation =
       result = isGeneric
     else:
       result = typeRel(c, x, a) # check if it fits
-  
+
   of tyStatic:
     let prev = PType(idTableGet(c.bindings, f))
     if prev == nil:
@@ -1034,12 +1034,12 @@ proc typeRel(c: var TCandidate, f, aOrig: PType, doBind = true): TTypeRelation =
       # when `f` is an unresolved typedesc, `a` could be any
       # type, so we should not perform this check earlier
       if a.kind != tyTypeDesc: return isNone
-    
+
       if f.base.kind == tyNone:
         result = isGeneric
       else:
         result = typeRel(c, f.base, a.base)
-      
+
       if result != isNone:
         put(c.bindings, f, a)
     else:
@@ -1049,9 +1049,9 @@ proc typeRel(c: var TCandidate, f, aOrig: PType, doBind = true): TTypeRelation =
         result = typeRel(c, prev.base, a.base)
       else:
         result = isNone
- 
+
   of tyIter:
-    if a.kind == tyIter or 
+    if a.kind == tyIter or
       (a.kind == tyProc and tfIterator in a.flags):
       result = typeRel(c, f.base, a.base)
     else:
@@ -1059,7 +1059,7 @@ proc typeRel(c: var TCandidate, f, aOrig: PType, doBind = true): TTypeRelation =
 
   of tyStmt:
     result = isGeneric
-  
+
   of tyProxy:
     result = isEqual
 
@@ -1078,11 +1078,11 @@ proc typeRel(c: var TCandidate, f, aOrig: PType, doBind = true): TTypeRelation =
     else:
       localError(f.n.info, errTypeExpected)
       result = isNone
-  
+
   else:
     internalAssert false
-  
-proc cmpTypes*(c: PContext, f, a: PType): TTypeRelation = 
+
+proc cmpTypes*(c: PContext, f, a: PType): TTypeRelation =
   var m: TCandidate
   initCandidate(c, m, f)
   result = typeRel(m, f, a)
@@ -1095,9 +1095,9 @@ proc getInstantiatedType(c: PContext, arg: PNode, m: TCandidate,
   if result == nil:
     internalError(arg.info, "getInstantiatedType")
     result = errorType(c)
-  
-proc implicitConv(kind: TNodeKind, f: PType, arg: PNode, m: TCandidate, 
-                  c: PContext): PNode = 
+
+proc implicitConv(kind: TNodeKind, f: PType, arg: PNode, m: TCandidate,
+                  c: PContext): PNode =
   result = newNodeI(kind, arg.info)
   if containsGenericType(f):
     if not m.hasFauxMatch:
@@ -1110,10 +1110,10 @@ proc implicitConv(kind: TNodeKind, f: PType, arg: PNode, m: TCandidate,
   addSon(result, ast.emptyNode)
   addSon(result, arg)
 
-proc userConvMatch(c: PContext, m: var TCandidate, f, a: PType, 
-                   arg: PNode): PNode = 
+proc userConvMatch(c: PContext, m: var TCandidate, f, a: PType,
+                   arg: PNode): PNode =
   result = nil
-  for i in countup(0, len(c.converters) - 1): 
+  for i in countup(0, len(c.converters) - 1):
     var src = c.converters[i].typ.sons[1]
     var dest = c.converters[i].typ.sons[0]
     # for generic type converters we need to check 'src <- a' before
@@ -1121,12 +1121,12 @@ proc userConvMatch(c: PContext, m: var TCandidate, f, a: PType,
     # see tests/tgenericconverter:
     let srca = typeRel(m, src, a)
     if srca notin {isEqual, isGeneric}: continue
-    
+
     let destIsGeneric = containsGenericType(dest)
     if destIsGeneric:
       dest = generateTypeInstance(c, m.bindings, arg, dest)
     let fdest = typeRel(m, f, dest)
-    if fdest in {isEqual, isGeneric}: 
+    if fdest in {isEqual, isGeneric}:
       markUsed(arg.info, c.converters[i])
       var s = newSymNode(c.converters[i])
       s.typ = c.converters[i].typ
@@ -1138,8 +1138,8 @@ proc userConvMatch(c: PContext, m: var TCandidate, f, a: PType,
       m.genericConverter = srca == isGeneric or destIsGeneric
       return result
 
-proc localConvMatch(c: PContext, m: var TCandidate, f, a: PType, 
-                    arg: PNode): PNode = 
+proc localConvMatch(c: PContext, m: var TCandidate, f, a: PType,
+                    arg: PNode): PNode =
   # arg.typ can be nil in 'suggest':
   if isNil(arg.typ): return nil
 
@@ -1181,12 +1181,12 @@ proc paramTypesMatchAux(m: var TCandidate, f, argType: PType,
     arg = argSemantized
     argType = argType
     c = m.c
-  
+
   if tfHasStatic in fMaybeStatic.flags:
     # XXX: When implicit statics are the default
     # this will be done earlier - we just have to
     # make sure that static types enter here
-     
+
     # XXX: weaken tyGenericParam and call it tyGenericPlaceholder
     # and finally start using tyTypedesc for generic types properly.
     if argType.kind == tyGenericParam and tfWildcard in argType.flags:
@@ -1205,11 +1205,11 @@ proc paramTypesMatchAux(m: var TCandidate, f, argType: PType,
         arg.typ.sons = @[evaluated.typ]
         arg.typ.n = evaluated
         argType = arg.typ
- 
+
   var
     a = if c.inTypeClass > 0: argType.skipTypes({tyTypeDesc, tyFieldAccessor})
         else: argType
- 
+
     r = typeRel(m, f, a)
 
   if r != isNone and m.calleeSym != nil and
@@ -1244,19 +1244,18 @@ proc paramTypesMatchAux(m: var TCandidate, f, argType: PType,
   case r
   of isConvertible:
     inc(m.convMatches)
-    result = implicitConv(nkHiddenStdConv, f, copyTree(arg), m, c)
+    result = implicitConv(nkHiddenStdConv, f, arg, m, c)
   of isIntConv:
     # I'm too lazy to introduce another ``*matches`` field, so we conflate
     # ``isIntConv`` and ``isIntLit`` here:
     inc(m.intConvMatches)
-    result = implicitConv(nkHiddenStdConv, f, copyTree(arg), m, c)
-  of isSubtype: 
+    result = implicitConv(nkHiddenStdConv, f, arg, m, c)
+  of isSubtype:
     inc(m.subtypeMatches)
-    result = implicitConv(nkHiddenSubConv, f, copyTree(arg), m, c)
+    result = implicitConv(nkHiddenSubConv, f, arg, m, c)
   of isSubrange:
     inc(m.subtypeMatches)
-    #result = copyTree(arg)
-    result = implicitConv(nkHiddenStdConv, f, copyTree(arg), m, c)
+    result = implicitConv(nkHiddenStdConv, f, arg, m, c)
   of isInferred, isInferredConvertible:
     inc(m.genericMatches)
     if arg.kind in {nkProcDef, nkIteratorDef} + nkLambdaKinds:
@@ -1269,42 +1268,32 @@ proc paramTypesMatchAux(m: var TCandidate, f, argType: PType,
       result = implicitConv(nkHiddenStdConv, f, result, m, c)
   of isGeneric:
     inc(m.genericMatches)
-    when true:
-      if arg.typ == nil:
-        result = arg
-      elif skipTypes(arg.typ, abstractVar-{tyTypeDesc}).kind == tyTuple:
-        result = implicitConv(nkHiddenStdConv, f, copyTree(arg), m, c)
-      elif arg.typ.isEmptyContainer:
-        result = arg.copyTree
-        result.typ = getInstantiatedType(c, arg, m, f)
-      else:
-        result = arg
-    else:
-      # XXX Why is this ever necessary? arg's type should not be retrofitted
-      # to match formal's type in this way!
-      result = copyTree(arg)
+    if arg.typ == nil:
+      result = arg
+    elif skipTypes(arg.typ, abstractVar-{tyTypeDesc}).kind == tyTuple:
+      result = implicitConv(nkHiddenStdConv, f, copyTree(arg), m, c)
+    elif arg.typ.isEmptyContainer:
+      result = arg.copyTree
       result.typ = getInstantiatedType(c, arg, m, f)
-      # BUG: f may not be the right key!
-      if skipTypes(result.typ, abstractVar-{tyTypeDesc}).kind in {tyTuple}:
-        result = implicitConv(nkHiddenStdConv, f, copyTree(arg), m, c)
-        # BUGFIX: use ``result.typ`` and not `f` here
+    else:
+      result = arg
   of isFromIntLit:
     # too lazy to introduce another ``*matches`` field, so we conflate
     # ``isIntConv`` and ``isIntLit`` here:
     inc(m.intConvMatches, 256)
-    result = implicitConv(nkHiddenStdConv, f, copyTree(arg), m, c)
-  of isEqual: 
+    result = implicitConv(nkHiddenStdConv, f, arg, m, c)
+  of isEqual:
     inc(m.exactMatches)
-    result = copyTree(arg)
+    result = arg
     if skipTypes(f, abstractVar-{tyTypeDesc}).kind in {tyTuple}:
-      result = implicitConv(nkHiddenStdConv, f, copyTree(arg), m, c)
+      result = implicitConv(nkHiddenStdConv, f, arg, m, c)
   of isNone:
     # do not do this in ``typeRel`` as it then can't infere T in ``ref T``:
     if a.kind in {tyProxy, tyUnknown}:
       inc(m.genericMatches)
       m.fauxMatch = a.kind
-      return copyTree(arg)
-    result = userConvMatch(c, m, f, a, arg) 
+      return arg
+    result = userConvMatch(c, m, f, a, arg)
     # check for a base type match, which supports varargs[T] without []
     # constructor in a call:
     if result == nil and f.kind == tyVarargs:
@@ -1325,7 +1314,7 @@ proc paramTypesMatch*(m: var TCandidate, f, a: PType,
                       arg, argOrig: PNode): PNode =
   if arg == nil or arg.kind notin nkSymChoices:
     result = paramTypesMatchAux(m, f, a, arg, argOrig)
-  else: 
+  else:
     # CAUTION: The order depends on the used hashing scheme. Thus it is
     # incorrect to simply use the first fitting match. However, to implement
     # this correctly is inefficient. We have to copy `m` here to be able to
@@ -1339,28 +1328,28 @@ proc paramTypesMatch*(m: var TCandidate, f, a: PType,
     y.calleeSym = m.calleeSym
     z.calleeSym = m.calleeSym
     var best = -1
-    for i in countup(0, sonsLen(arg) - 1): 
+    for i in countup(0, sonsLen(arg) - 1):
       if arg.sons[i].sym.kind in {skProc, skMethod, skConverter}+skIterators:
         copyCandidate(z, m)
         var r = typeRel(z, f, arg.sons[i].typ)
-        if r != isNone: 
+        if r != isNone:
           case x.state
-          of csEmpty, csNoMatch: 
+          of csEmpty, csNoMatch:
             x = z
             best = i
             x.state = csMatch
-          of csMatch: 
+          of csMatch:
             var cmp = cmpCandidates(x, z)
             if cmp < 0:
               best = i
               x = z
             elif cmp == 0:
               y = z           # z is as good as x
-    if x.state == csEmpty: 
+    if x.state == csEmpty:
       result = nil
-    elif y.state == csMatch and cmpCandidates(x, y) == 0: 
-      if x.state != csMatch: 
-        internalError(arg.info, "x.state is not csMatch") 
+    elif y.state == csMatch and cmpCandidates(x, y) == 0:
+      if x.state != csMatch:
+        internalError(arg.info, "x.state is not csMatch")
       # ambiguous: more than one symbol fits!
       # See tsymchoice_for_expr as an example. 'f.kind == tyExpr' should match
       # anyway:
@@ -1373,7 +1362,7 @@ proc paramTypesMatch*(m: var TCandidate, f, a: PType,
       result = paramTypesMatchAux(m, f, arg.sons[best].typ, arg.sons[best],
                                   argOrig)
 
-proc setSon(father: PNode, at: int, son: PNode) = 
+proc setSon(father: PNode, at: int, son: PNode) =
   if sonsLen(father) <= at: setLen(father.sons, at + 1)
   father.sons[at] = son
 
@@ -1417,7 +1406,7 @@ proc incrIndexType(t: PType) =
   inc t.sons[0].n.sons[1].intVal
 
 proc matchesAux(c: PContext, n, nOrig: PNode,
-                m: var TCandidate, marker: var IntSet) = 
+                m: var TCandidate, marker: var IntSet) =
   template checkConstraint(n: expr) {.immediate, dirty.} =
     if not formal.constraint.isNil:
       if matchNodeKinds(formal.constraint, n):
@@ -1447,20 +1436,20 @@ proc matchesAux(c: PContext, n, nOrig: PNode,
       # named param
       # check if m.callee has such a param:
       prepareNamedParam(n.sons[a])
-      if n.sons[a].sons[0].kind != nkIdent: 
+      if n.sons[a].sons[0].kind != nkIdent:
         localError(n.sons[a].info, errNamedParamHasToBeIdent)
         m.state = csNoMatch
-        return 
+        return
       formal = getSymFromList(m.callee.n, n.sons[a].sons[0].ident, 1)
-      if formal == nil: 
+      if formal == nil:
         # no error message!
         m.state = csNoMatch
-        return 
-      if containsOrIncl(marker, formal.position): 
+        return
+      if containsOrIncl(marker, formal.position):
         # already in namedParams:
         localError(n.sons[a].info, errCannotBindXTwice, formal.name.s)
         m.state = csNoMatch
-        return 
+        return
       m.baseTypeMatch = false
       n.sons[a].sons[1] = prepareOperand(c, formal.typ, n.sons[a].sons[1])
       n.sons[a].typ = n.sons[a].sons[1].typ
@@ -1470,7 +1459,7 @@ proc matchesAux(c: PContext, n, nOrig: PNode,
         m.state = csNoMatch
         return
       checkConstraint(n.sons[a].sons[1])
-      if m.baseTypeMatch: 
+      if m.baseTypeMatch:
         #assert(container == nil)
         container = newNodeIT(nkBracket, n.sons[a].info, arrayConstr(c, arg))
         addSon(container, arg)
@@ -1507,7 +1496,7 @@ proc matchesAux(c: PContext, n, nOrig: PNode,
           m.state = csNoMatch
           return
       else:
-        if m.callee.n.sons[f].kind != nkSym: 
+        if m.callee.n.sons[f].kind != nkSym:
           internalError(n.sons[a].info, "matches")
           return
         formal = m.callee.n.sons[f].sym
@@ -1515,7 +1504,7 @@ proc matchesAux(c: PContext, n, nOrig: PNode,
           # already in namedParams:
           localError(n.sons[a].info, errCannotBindXTwice, formal.name.s)
           m.state = csNoMatch
-          return 
+          return
         m.baseTypeMatch = false
         n.sons[a] = prepareOperand(c, formal.typ, n.sons[a])
         var arg = paramTypesMatch(m, formal.typ, n.sons[a].typ,
@@ -1528,7 +1517,7 @@ proc matchesAux(c: PContext, n, nOrig: PNode,
           if container.isNil:
             container = newNodeIT(nkBracket, n.sons[a].info, arrayConstr(c, arg))
           addSon(container, arg)
-          setSon(m.call, formal.position + 1, 
+          setSon(m.call, formal.position + 1,
                  implicitConv(nkHiddenStdConv, formal.typ, container, m, c))
           #if f != formalLen - 1: container = nil
 
@@ -1603,7 +1592,7 @@ when not declared(tests):
 
 tests:
   var dummyOwner = newSym(skModule, getIdent("test_module"), nil, UnknownLineInfo())
-  
+
   proc `|` (t1, t2: PType): PType =
     result = newType(tyOr, dummyOwner)
     result.rawAddSon(t1)
@@ -1624,12 +1613,12 @@ tests:
 
   proc array(x: int, t: PType): PType =
     result = newType(tyArray, dummyOwner)
-    
+
     var n = newNodeI(nkRange, UnknownLineInfo())
     addSon(n, newIntNode(nkIntLit, 0))
     addSon(n, newIntNode(nkIntLit, x))
     let range = newType(tyRange, dummyOwner)
-    
+
     result.rawAddSon(range)
     result.rawAddSon(t)
 
@@ -1664,7 +1653,7 @@ tests:
     template no(x, y) =
       test astToStr(x) & " is not " & astToStr(y):
         check typeRel(c, y, x) == isNone
-    
+
     yes seq(any), array(10, int) | seq(any)
     # Sure, seq[any] is directly included
 
@@ -1672,16 +1661,16 @@ tests:
     yes seq(int), seq(number)
     # Sure, the int sequence is certainly
     # part of the number sequences (and all sequences)
-    
+
     no seq(any), seq(float)
     # Nope, seq[any] includes types that are not seq[float] (e.g. seq[int])
 
     yes seq(int|string), seq(any)
     # Sure
- 
+
     yes seq(int&string), seq(any)
     # Again
-    
+
     yes seq(int&string), seq(int)
     # A bit more complicated
     # seq[int&string] is not a real type, but it's analogous to
@@ -1690,23 +1679,23 @@ tests:
     no seq(int|string), seq(int|float)
     # Nope, seq[string] is not included in not included in
     # the seq[int|float] set
-    
+
     no seq(!(int|string)), seq(string)
     # A sequence that is neither seq[int] or seq[string]
     # is obviously not seq[string]
-     
+
     no seq(!int), seq(number)
     # Now your head should start to hurt a bit
     # A sequence that is not seq[int] is not necessarily a number sequence
     # it could well be seq[string] for example
-    
+
     yes seq(!(int|string)), seq(!string)
     # all sequnece types besides seq[int] and seq[string]
     # are subset of all sequence types that are not seq[string]
 
     no seq(!(int|string)), seq(!(string|TFoo))
     # Nope, seq[TFoo] is included in the first set, but not in the second
-    
+
     no seq(!string), seq(!number)
     # Nope, seq[int] in included in the first set, but not in the second
 
@@ -1714,7 +1703,7 @@ tests:
     yes seq(!int), seq(any)
     no seq(any), seq(!any)
     no seq(!int), seq(!any)
-    
+
     yes int, ordinal
     no  string, ordinal
 
diff --git a/compiler/types.nim b/compiler/types.nim
index 5c3be7553..0cc5a212b 100644
--- a/compiler/types.nim
+++ b/compiler/types.nim
@@ -9,20 +9,20 @@
 
 # this module contains routines for accessing and iterating over types
 
-import 
+import
   intsets, ast, astalgo, trees, msgs, strutils, platform, renderer
 
 proc firstOrd*(t: PType): BiggestInt
 proc lastOrd*(t: PType): BiggestInt
 proc lengthOrd*(t: PType): BiggestInt
-type 
+type
   TPreferedDesc* = enum
     preferName, preferDesc, preferExported, preferModuleInfo, preferGenericArg
 
 proc typeToString*(typ: PType; prefer: TPreferedDesc = preferName): string
 proc base*(t: PType): PType
   # ------------------- type iterator: ----------------------------------------
-type 
+type
   TTypeIter* = proc (t: PType, closure: RootRef): bool {.nimcall.} # true if iteration should stop
   TTypeMutator* = proc (t: PType, closure: RootRef): PType {.nimcall.} # copy t and mutate it
   TTypePredicate* = proc (t: PType): bool {.nimcall.}
@@ -32,7 +32,7 @@ proc iterOverType*(t: PType, iter: TTypeIter, closure: RootRef): bool
 proc mutateType*(t: PType, iter: TTypeMutator, closure: RootRef): PType
   # Returns result of `iter`.
 
-type 
+type
   TParamsEquality* = enum     # they are equal, but their
                               # identifiers or their return
                               # type differ (i.e. they cannot be
@@ -59,7 +59,7 @@ const
   abstractInst* = {tyGenericInst, tyDistinct, tyConst, tyMutable, tyOrdinal,
                    tyTypeDesc}
 
-  skipPtrs* = {tyVar, tyPtr, tyRef, tyGenericInst, tyConst, tyMutable, 
+  skipPtrs* = {tyVar, tyPtr, tyRef, tyGenericInst, tyConst, tyMutable,
                tyTypeDesc}
   typedescPtrs* = abstractPtrs + {tyTypeDesc}
   typedescInst* = abstractInst + {tyTypeDesc}
@@ -75,9 +75,9 @@ proc getSize*(typ: PType): BiggestInt
 proc isPureObject*(typ: PType): bool
 proc invalidGenericInst*(f: PType): bool
   # for debugging
-type 
-  TTypeFieldResult* = enum 
-    frNone,                   # type has no object type field 
+type
+  TTypeFieldResult* = enum
+    frNone,                   # type has no object type field
     frHeader,                 # type has an object type field only in the header
     frEmbedded                # type has an object type field somewhere embedded
 
@@ -86,15 +86,15 @@ proc analyseObjectWithTypeField*(t: PType): TTypeFieldResult
   # made or intializing of the type field suffices or if there is no type field
   # at all in this type.
 
-proc invalidGenericInst(f: PType): bool = 
+proc invalidGenericInst(f: PType): bool =
   result = f.kind == tyGenericInst and lastSon(f) == nil
 
-proc isPureObject(typ: PType): bool = 
+proc isPureObject(typ: PType): bool =
   var t = typ
   while t.kind == tyObject and t.sons[0] != nil: t = t.sons[0]
   result = t.sym != nil and sfPure in t.sym.flags
 
-proc getOrdValue(n: PNode): BiggestInt = 
+proc getOrdValue(n: PNode): BiggestInt =
   case n.kind
   of nkCharLit..nkUInt64Lit: result = n.intVal
   of nkNilLit: result = 0
@@ -109,21 +109,21 @@ proc isIntLit*(t: PType): bool {.inline.} =
 proc isFloatLit*(t: PType): bool {.inline.} =
   result = t.kind == tyFloat and t.n != nil and t.n.kind == nkFloatLit
 
-proc isCompatibleToCString(a: PType): bool = 
-  if a.kind == tyArray: 
+proc isCompatibleToCString(a: PType): bool =
+  if a.kind == tyArray:
     if (firstOrd(a.sons[0]) == 0) and
-        (skipTypes(a.sons[0], {tyRange, tyConst, 
-                               tyMutable, tyGenericInst}).kind in 
+        (skipTypes(a.sons[0], {tyRange, tyConst,
+                               tyMutable, tyGenericInst}).kind in
             {tyInt..tyInt64, tyUInt..tyUInt64}) and
-        (a.sons[1].kind == tyChar): 
+        (a.sons[1].kind == tyChar):
       result = true
-  
-proc getProcHeader*(sym: PSym; prefer: TPreferedDesc = preferName): string = 
+
+proc getProcHeader*(sym: PSym; prefer: TPreferedDesc = preferName): string =
   result = sym.owner.name.s & '.' & sym.name.s & '('
   var n = sym.typ.n
-  for i in countup(1, sonsLen(n) - 1): 
+  for i in countup(1, sonsLen(n) - 1):
     var p = n.sons[i]
-    if p.kind == nkSym: 
+    if p.kind == nkSym:
       add(result, p.sym.name.s)
       add(result, ": ")
       add(result, typeToString(p.sym.typ, prefer))
@@ -134,7 +134,7 @@ proc getProcHeader*(sym: PSym; prefer: TPreferedDesc = preferName): string =
   if n.sons[0].typ != nil:
     result.add(": " & typeToString(n.sons[0].typ, prefer))
 
-proc elemType*(t: PType): PType = 
+proc elemType*(t: PType): PType =
   assert(t != nil)
   case t.kind
   of tyGenericInst, tyDistinct: result = elemType(lastSon(t))
@@ -142,10 +142,10 @@ proc elemType*(t: PType): PType =
   else: result = t.lastSon
   assert(result != nil)
 
-proc skipGeneric(t: PType): PType = 
+proc skipGeneric(t: PType): PType =
   result = t
   while result.kind == tyGenericInst: result = lastSon(result)
-      
+
 proc isOrdinalType(t: PType): bool =
   assert(t != nil)
   # caution: uint, uint64 are no ordinal types!
@@ -153,134 +153,134 @@ proc isOrdinalType(t: PType): bool =
       (t.kind in {tyRange, tyOrdinal, tyConst, tyMutable, tyGenericInst}) and
        isOrdinalType(t.sons[0])
 
-proc enumHasHoles(t: PType): bool = 
+proc enumHasHoles(t: PType): bool =
   var b = t
   while b.kind in {tyConst, tyMutable, tyRange, tyGenericInst}: b = b.sons[0]
   result = b.kind == tyEnum and tfEnumHasHoles in b.flags
 
-proc iterOverTypeAux(marker: var IntSet, t: PType, iter: TTypeIter, 
+proc iterOverTypeAux(marker: var IntSet, t: PType, iter: TTypeIter,
                      closure: RootRef): bool
-proc iterOverNode(marker: var IntSet, n: PNode, iter: TTypeIter, 
-                  closure: RootRef): bool = 
-  if n != nil: 
+proc iterOverNode(marker: var IntSet, n: PNode, iter: TTypeIter,
+                  closure: RootRef): bool =
+  if n != nil:
     case n.kind
-    of nkNone..nkNilLit: 
+    of nkNone..nkNilLit:
       # a leaf
       result = iterOverTypeAux(marker, n.typ, iter, closure)
-    else: 
-      for i in countup(0, sonsLen(n) - 1): 
+    else:
+      for i in countup(0, sonsLen(n) - 1):
         result = iterOverNode(marker, n.sons[i], iter, closure)
-        if result: return 
-  
-proc iterOverTypeAux(marker: var IntSet, t: PType, iter: TTypeIter, 
-                     closure: RootRef): bool = 
+        if result: return
+
+proc iterOverTypeAux(marker: var IntSet, t: PType, iter: TTypeIter,
+                     closure: RootRef): bool =
   result = false
-  if t == nil: return 
+  if t == nil: return
   result = iter(t, closure)
-  if result: return 
-  if not containsOrIncl(marker, t.id): 
+  if result: return
+  if not containsOrIncl(marker, t.id):
     case t.kind
-    of tyGenericInst, tyGenericBody: 
+    of tyGenericInst, tyGenericBody:
       result = iterOverTypeAux(marker, lastSon(t), iter, closure)
-    else: 
-      for i in countup(0, sonsLen(t) - 1): 
+    else:
+      for i in countup(0, sonsLen(t) - 1):
         result = iterOverTypeAux(marker, t.sons[i], iter, closure)
-        if result: return 
+        if result: return
       if t.n != nil: result = iterOverNode(marker, t.n, iter, closure)
-  
-proc iterOverType(t: PType, iter: TTypeIter, closure: RootRef): bool = 
+
+proc iterOverType(t: PType, iter: TTypeIter, closure: RootRef): bool =
   var marker = initIntSet()
   result = iterOverTypeAux(marker, t, iter, closure)
 
-proc searchTypeForAux(t: PType, predicate: TTypePredicate, 
+proc searchTypeForAux(t: PType, predicate: TTypePredicate,
                       marker: var IntSet): bool
 
-proc searchTypeNodeForAux(n: PNode, p: TTypePredicate, 
-                          marker: var IntSet): bool = 
+proc searchTypeNodeForAux(n: PNode, p: TTypePredicate,
+                          marker: var IntSet): bool =
   result = false
   case n.kind
-  of nkRecList: 
-    for i in countup(0, sonsLen(n) - 1): 
+  of nkRecList:
+    for i in countup(0, sonsLen(n) - 1):
       result = searchTypeNodeForAux(n.sons[i], p, marker)
-      if result: return 
-  of nkRecCase: 
+      if result: return
+  of nkRecCase:
     assert(n.sons[0].kind == nkSym)
     result = searchTypeNodeForAux(n.sons[0], p, marker)
-    if result: return 
-    for i in countup(1, sonsLen(n) - 1): 
+    if result: return
+    for i in countup(1, sonsLen(n) - 1):
       case n.sons[i].kind
-      of nkOfBranch, nkElse: 
+      of nkOfBranch, nkElse:
         result = searchTypeNodeForAux(lastSon(n.sons[i]), p, marker)
-        if result: return 
+        if result: return
       else: internalError("searchTypeNodeForAux(record case branch)")
-  of nkSym: 
+  of nkSym:
     result = searchTypeForAux(n.sym.typ, p, marker)
   else: internalError(n.info, "searchTypeNodeForAux()")
-  
-proc searchTypeForAux(t: PType, predicate: TTypePredicate, 
-                      marker: var IntSet): bool = 
+
+proc searchTypeForAux(t: PType, predicate: TTypePredicate,
+                      marker: var IntSet): bool =
   # iterates over VALUE types!
   result = false
-  if t == nil: return 
-  if containsOrIncl(marker, t.id): return 
+  if t == nil: return
+  if containsOrIncl(marker, t.id): return
   result = predicate(t)
-  if result: return 
+  if result: return
   case t.kind
-  of tyObject: 
+  of tyObject:
     result = searchTypeForAux(t.sons[0], predicate, marker)
     if not result: result = searchTypeNodeForAux(t.n, predicate, marker)
-  of tyGenericInst, tyDistinct: 
+  of tyGenericInst, tyDistinct:
     result = searchTypeForAux(lastSon(t), predicate, marker)
-  of tyArray, tyArrayConstr, tySet, tyTuple: 
-    for i in countup(0, sonsLen(t) - 1): 
+  of tyArray, tyArrayConstr, tySet, tyTuple:
+    for i in countup(0, sonsLen(t) - 1):
       result = searchTypeForAux(t.sons[i], predicate, marker)
-      if result: return 
-  else: 
+      if result: return
+  else:
     discard
 
-proc searchTypeFor(t: PType, predicate: TTypePredicate): bool = 
+proc searchTypeFor(t: PType, predicate: TTypePredicate): bool =
   var marker = initIntSet()
   result = searchTypeForAux(t, predicate, marker)
 
-proc isObjectPredicate(t: PType): bool = 
+proc isObjectPredicate(t: PType): bool =
   result = t.kind == tyObject
 
-proc containsObject(t: PType): bool = 
+proc containsObject(t: PType): bool =
   result = searchTypeFor(t, isObjectPredicate)
 
-proc isObjectWithTypeFieldPredicate(t: PType): bool = 
+proc isObjectWithTypeFieldPredicate(t: PType): bool =
   result = t.kind == tyObject and t.sons[0] == nil and
       not (t.sym != nil and {sfPure, sfInfixCall} * t.sym.flags != {}) and
       tfFinal notin t.flags
 
-proc analyseObjectWithTypeFieldAux(t: PType, 
-                                   marker: var IntSet): TTypeFieldResult = 
+proc analyseObjectWithTypeFieldAux(t: PType,
+                                   marker: var IntSet): TTypeFieldResult =
   var res: TTypeFieldResult
   result = frNone
-  if t == nil: return 
+  if t == nil: return
   case t.kind
-  of tyObject: 
-    if (t.n != nil): 
-      if searchTypeNodeForAux(t.n, isObjectWithTypeFieldPredicate, marker): 
+  of tyObject:
+    if (t.n != nil):
+      if searchTypeNodeForAux(t.n, isObjectWithTypeFieldPredicate, marker):
         return frEmbedded
-    for i in countup(0, sonsLen(t) - 1): 
+    for i in countup(0, sonsLen(t) - 1):
       res = analyseObjectWithTypeFieldAux(t.sons[i], marker)
-      if res == frEmbedded: 
+      if res == frEmbedded:
         return frEmbedded
       if res == frHeader: result = frHeader
-    if result == frNone: 
+    if result == frNone:
       if isObjectWithTypeFieldPredicate(t): result = frHeader
-  of tyGenericInst, tyDistinct, tyConst, tyMutable: 
+  of tyGenericInst, tyDistinct, tyConst, tyMutable:
     result = analyseObjectWithTypeFieldAux(lastSon(t), marker)
-  of tyArray, tyArrayConstr, tyTuple: 
-    for i in countup(0, sonsLen(t) - 1): 
+  of tyArray, tyArrayConstr, tyTuple:
+    for i in countup(0, sonsLen(t) - 1):
       res = analyseObjectWithTypeFieldAux(t.sons[i], marker)
-      if res != frNone: 
+      if res != frNone:
         return frEmbedded
-  else: 
+  else:
     discard
 
-proc analyseObjectWithTypeField(t: PType): TTypeFieldResult = 
+proc analyseObjectWithTypeField(t: PType): TTypeFieldResult =
   var marker = initIntSet()
   result = analyseObjectWithTypeFieldAux(t, marker)
 
@@ -288,7 +288,7 @@ proc isGCRef(t: PType): bool =
   result = t.kind in GcTypeKinds or
     (t.kind == tyProc and t.callConv == ccClosure)
 
-proc containsGarbageCollectedRef(typ: PType): bool = 
+proc containsGarbageCollectedRef(typ: PType): bool =
   # returns true if typ contains a reference, sequence or string (all the
   # things that are garbage-collected)
   result = searchTypeFor(typ, isGCRef)
@@ -296,47 +296,47 @@ proc containsGarbageCollectedRef(typ: PType): bool =
 proc isTyRef(t: PType): bool =
   result = t.kind == tyRef or (t.kind == tyProc and t.callConv == ccClosure)
 
-proc containsTyRef*(typ: PType): bool = 
+proc containsTyRef*(typ: PType): bool =
   # returns true if typ contains a 'ref'
   result = searchTypeFor(typ, isTyRef)
 
-proc isHiddenPointer(t: PType): bool = 
+proc isHiddenPointer(t: PType): bool =
   result = t.kind in {tyString, tySequence}
 
-proc containsHiddenPointer(typ: PType): bool = 
+proc containsHiddenPointer(typ: PType): bool =
   # returns true if typ contains a string, table or sequence (all the things
   # that need to be copied deeply)
   result = searchTypeFor(typ, isHiddenPointer)
 
 proc canFormAcycleAux(marker: var IntSet, typ: PType, startId: int): bool
-proc canFormAcycleNode(marker: var IntSet, n: PNode, startId: int): bool = 
+proc canFormAcycleNode(marker: var IntSet, n: PNode, startId: int): bool =
   result = false
-  if n != nil: 
+  if n != nil:
     result = canFormAcycleAux(marker, n.typ, startId)
-    if not result: 
+    if not result:
       case n.kind
-      of nkNone..nkNilLit: 
+      of nkNone..nkNilLit:
         discard
-      else: 
-        for i in countup(0, sonsLen(n) - 1): 
+      else:
+        for i in countup(0, sonsLen(n) - 1):
           result = canFormAcycleNode(marker, n.sons[i], startId)
-          if result: return 
-  
-proc canFormAcycleAux(marker: var IntSet, typ: PType, startId: int): bool = 
+          if result: return
+
+proc canFormAcycleAux(marker: var IntSet, typ: PType, startId: int): bool =
   result = false
-  if typ == nil: return 
-  if tfAcyclic in typ.flags: return 
+  if typ == nil: return
+  if tfAcyclic in typ.flags: return
   var t = skipTypes(typ, abstractInst-{tyTypeDesc})
-  if tfAcyclic in t.flags: return 
+  if tfAcyclic in t.flags: return
   case t.kind
   of tyTuple, tyObject, tyRef, tySequence, tyArray, tyArrayConstr, tyOpenArray,
      tyVarargs:
-    if not containsOrIncl(marker, t.id): 
-      for i in countup(0, sonsLen(t) - 1): 
+    if not containsOrIncl(marker, t.id):
+      for i in countup(0, sonsLen(t) - 1):
         result = canFormAcycleAux(marker, t.sons[i], startId)
-        if result: return 
+        if result: return
       if t.n != nil: result = canFormAcycleNode(marker, t.n, startId)
-    else: 
+    else:
       result = t.id == startId
     # Inheritance can introduce cyclic types, however this is not relevant
     # as the type that is passed to 'new' is statically known!
@@ -351,29 +351,29 @@ proc canFormAcycle(typ: PType): bool =
   var marker = initIntSet()
   result = canFormAcycleAux(marker, typ, typ.id)
 
-proc mutateTypeAux(marker: var IntSet, t: PType, iter: TTypeMutator, 
+proc mutateTypeAux(marker: var IntSet, t: PType, iter: TTypeMutator,
                    closure: RootRef): PType
-proc mutateNode(marker: var IntSet, n: PNode, iter: TTypeMutator, 
-                closure: RootRef): PNode = 
+proc mutateNode(marker: var IntSet, n: PNode, iter: TTypeMutator,
+                closure: RootRef): PNode =
   result = nil
-  if n != nil: 
+  if n != nil:
     result = copyNode(n)
     result.typ = mutateTypeAux(marker, n.typ, iter, closure)
     case n.kind
-    of nkNone..nkNilLit: 
+    of nkNone..nkNilLit:
       # a leaf
       discard
-    else: 
-      for i in countup(0, sonsLen(n) - 1): 
+    else:
+      for i in countup(0, sonsLen(n) - 1):
         addSon(result, mutateNode(marker, n.sons[i], iter, closure))
-  
-proc mutateTypeAux(marker: var IntSet, t: PType, iter: TTypeMutator, 
-                   closure: RootRef): PType = 
+
+proc mutateTypeAux(marker: var IntSet, t: PType, iter: TTypeMutator,
+                   closure: RootRef): PType =
   result = nil
-  if t == nil: return 
+  if t == nil: return
   result = iter(t, closure)
-  if not containsOrIncl(marker, t.id): 
-    for i in countup(0, sonsLen(t) - 1): 
+  if not containsOrIncl(marker, t.id):
+    for i in countup(0, sonsLen(t) - 1):
       result.sons[i] = mutateTypeAux(marker, result.sons[i], iter, closure)
     if t.n != nil: result.n = mutateNode(marker, t.n, iter, closure)
   assert(result != nil)
@@ -393,7 +393,7 @@ proc rangeToStr(n: PNode): string =
   assert(n.kind == nkRange)
   result = valueToString(n.sons[0]) & ".." & valueToString(n.sons[1])
 
-const 
+const
   typeToStr: array[TTypeKind, string] = ["None", "bool", "Char", "empty",
     "Array Constructor [$1]", "nil", "expr", "stmt", "typeDesc",
     "GenericInvocation", "GenericBody", "GenericInst", "GenericParam",
@@ -414,7 +414,7 @@ const preferToResolveSymbols = {preferName, preferModuleInfo, preferGenericArg}
 proc typeToString(typ: PType, prefer: TPreferedDesc = preferName): string =
   var t = typ
   result = ""
-  if t == nil: return 
+  if t == nil: return
   if prefer in preferToResolveSymbols and t.sym != nil and
        sfAnon notin t.sym.flags:
     if t.kind == tyInt and isIntLit(t):
@@ -484,47 +484,47 @@ proc typeToString(typ: PType, prefer: TPreferedDesc = preferName): string =
     result = "expr"
   of tyFromExpr, tyFieldAccessor:
     result = renderTree(t.n)
-  of tyArray: 
-    if t.sons[0].kind == tyRange: 
+  of tyArray:
+    if t.sons[0].kind == tyRange:
       result = "array[" & rangeToStr(t.sons[0].n) & ", " &
           typeToString(t.sons[1]) & ']'
-    else: 
+    else:
       result = "array[" & typeToString(t.sons[0]) & ", " &
           typeToString(t.sons[1]) & ']'
-  of tyArrayConstr: 
+  of tyArrayConstr:
     result = "Array constructor[" & rangeToStr(t.sons[0].n) & ", " &
         typeToString(t.sons[1]) & ']'
-  of tySequence: 
+  of tySequence:
     result = "seq[" & typeToString(t.sons[0]) & ']'
-  of tyOrdinal: 
+  of tyOrdinal:
     result = "ordinal[" & typeToString(t.sons[0]) & ']'
-  of tySet: 
+  of tySet:
     result = "set[" & typeToString(t.sons[0]) & ']'
-  of tyOpenArray: 
+  of tyOpenArray:
     result = "openarray[" & typeToString(t.sons[0]) & ']'
   of tyDistinct:
     result = "distinct " & typeToString(t.sons[0],
       if prefer == preferModuleInfo: preferModuleInfo else: preferName)
-  of tyTuple: 
+  of tyTuple:
     # we iterate over t.sons here, because t.n may be nil
     result = "tuple["
-    if t.n != nil: 
+    if t.n != nil:
       assert(sonsLen(t.n) == sonsLen(t))
-      for i in countup(0, sonsLen(t.n) - 1): 
+      for i in countup(0, sonsLen(t.n) - 1):
         assert(t.n.sons[i].kind == nkSym)
         add(result, t.n.sons[i].sym.name.s & ": " & typeToString(t.sons[i]))
         if i < sonsLen(t.n) - 1: add(result, ", ")
-    else: 
-      for i in countup(0, sonsLen(t) - 1): 
+    else:
+      for i in countup(0, sonsLen(t) - 1):
         add(result, typeToString(t.sons[i]))
         if i < sonsLen(t) - 1: add(result, ", ")
     add(result, ']')
-  of tyPtr, tyRef, tyVar, tyMutable, tyConst: 
+  of tyPtr, tyRef, tyVar, tyMutable, tyConst:
     result = typeToStr[t.kind]
     if t.len >= 2:
       setLen(result, result.len-1)
       result.add '['
-      for i in countup(0, sonsLen(t) - 1): 
+      for i in countup(0, sonsLen(t) - 1):
         add(result, typeToString(t.sons[i]))
         if i < sonsLen(t) - 1: add(result, ", ")
       result.add ']'
@@ -536,7 +536,7 @@ proc typeToString(typ: PType, prefer: TPreferedDesc = preferName): string =
       result.add("(" & typeToString(t.sons[0]) & ")")
   of tyProc:
     result = if tfIterator in t.flags: "iterator (" else: "proc ("
-    for i in countup(1, sonsLen(t) - 1): 
+    for i in countup(1, sonsLen(t) - 1):
       add(result, typeToString(t.sons[i]))
       if i < sonsLen(t) - 1: add(result, ", ")
     add(result, ')')
@@ -554,29 +554,29 @@ proc typeToString(typ: PType, prefer: TPreferedDesc = preferName): string =
     if len(prag) != 0: add(result, "{." & prag & ".}")
   of tyVarargs, tyIter:
     result = typeToStr[t.kind] % typeToString(t.sons[0])
-  else: 
+  else:
     result = typeToStr[t.kind]
   if tfShared in t.flags: result = "shared " & result
   if tfNotNil in t.flags: result.add(" not nil")
 
-proc resultType(t: PType): PType = 
+proc resultType(t: PType): PType =
   assert(t.kind == tyProc)
   result = t.sons[0]          # nil is allowed
-  
-proc base(t: PType): PType = 
+
+proc base(t: PType): PType =
   result = t.sons[0]
 
-proc firstOrd(t: PType): BiggestInt = 
+proc firstOrd(t: PType): BiggestInt =
   case t.kind
   of tyBool, tyChar, tySequence, tyOpenArray, tyString, tyVarargs, tyProxy:
     result = 0
   of tySet, tyVar: result = firstOrd(t.sons[0])
   of tyArray, tyArrayConstr: result = firstOrd(t.sons[0])
-  of tyRange: 
+  of tyRange:
     assert(t.n != nil)        # range directly given:
     assert(t.n.kind == nkRange)
     result = getOrdValue(t.n.sons[0])
-  of tyInt: 
+  of tyInt:
     if platform.intSize == 4: result = - (2147483646) - 2
     else: result = 0x8000000000000000'i64
   of tyInt8: result = - 128
@@ -584,11 +584,11 @@ proc firstOrd(t: PType): BiggestInt =
   of tyInt32: result = - 2147483646 - 2
   of tyInt64: result = 0x8000000000000000'i64
   of tyUInt..tyUInt64: result = 0
-  of tyEnum: 
+  of tyEnum:
     # if basetype <> nil then return firstOrd of basetype
-    if (sonsLen(t) > 0) and (t.sons[0] != nil): 
+    if (sonsLen(t) > 0) and (t.sons[0] != nil):
       result = firstOrd(t.sons[0])
-    else: 
+    else:
       assert(t.n.sons[0].kind == nkSym)
       result = t.n.sons[0].sym.position
   of tyGenericInst, tyDistinct, tyConst, tyMutable, tyTypeDesc, tyFieldAccessor:
@@ -600,31 +600,31 @@ proc firstOrd(t: PType): BiggestInt =
     internalError("invalid kind for first(" & $t.kind & ')')
     result = 0
 
-proc lastOrd(t: PType): BiggestInt = 
+proc lastOrd(t: PType): BiggestInt =
   case t.kind
   of tyBool: result = 1
   of tyChar: result = 255
   of tySet, tyVar: result = lastOrd(t.sons[0])
   of tyArray, tyArrayConstr: result = lastOrd(t.sons[0])
-  of tyRange: 
+  of tyRange:
     assert(t.n != nil)        # range directly given:
     assert(t.n.kind == nkRange)
     result = getOrdValue(t.n.sons[1])
-  of tyInt: 
+  of tyInt:
     if platform.intSize == 4: result = 0x7FFFFFFF
     else: result = 0x7FFFFFFFFFFFFFFF'i64
   of tyInt8: result = 0x0000007F
   of tyInt16: result = 0x00007FFF
   of tyInt32: result = 0x7FFFFFFF
   of tyInt64: result = 0x7FFFFFFFFFFFFFFF'i64
-  of tyUInt: 
+  of tyUInt:
     if platform.intSize == 4: result = 0xFFFFFFFF
     else: result = 0x7FFFFFFFFFFFFFFF'i64
   of tyUInt8: result = 0xFF
   of tyUInt16: result = 0xFFFF
   of tyUInt32: result = 0xFFFFFFFF
   of tyUInt64: result = 0x7FFFFFFFFFFFFFFF'i64
-  of tyEnum: 
+  of tyEnum:
     assert(t.n.sons[sonsLen(t.n) - 1].kind == nkSym)
     result = t.n.sons[sonsLen(t.n) - 1].sym.position
   of tyGenericInst, tyDistinct, tyConst, tyMutable,
@@ -638,7 +638,7 @@ proc lastOrd(t: PType): BiggestInt =
     internalError("invalid kind for last(" & $t.kind & ')')
     result = 0
 
-proc lengthOrd(t: PType): BiggestInt = 
+proc lengthOrd(t: PType): BiggestInt =
   case t.kind
   of tyInt64, tyInt32, tyInt: result = lastOrd(t)
   of tyDistinct, tyConst, tyMutable: result = lengthOrd(t.sons[0])
@@ -654,7 +654,7 @@ type
     dcEqOrDistinctOf       ## a equals b or a is distinct of b
 
   TTypeCmpFlag* = enum
-    IgnoreTupleFields
+    IgnoreTupleFields      ## NOTE: Only set this flag for backends!
     IgnoreCC
     ExactTypeDescValues
     ExactGenericParams
@@ -673,7 +673,7 @@ type
 proc initSameTypeClosure: TSameTypeClosure =
   # we do the initialization lazily for performance (avoids memory allocations)
   discard
-  
+
 proc containsOrIncl(c: var TSameTypeClosure, a, b: PType): bool =
   result = not isNil(c.s) and c.s.contains((a.id, b.id))
   if not result:
@@ -700,17 +700,17 @@ proc sameTypeOrNil*(a, b: PType, flags: TTypeCmpFlags = {}): bool =
     if a == nil or b == nil: result = false
     else: result = sameType(a, b, flags)
 
-proc equalParam(a, b: PSym): TParamsEquality = 
+proc equalParam(a, b: PSym): TParamsEquality =
   if sameTypeOrNil(a.typ, b.typ, {ExactTypeDescValues}) and
       exprStructuralEquivalent(a.constraint, b.constraint):
-    if a.ast == b.ast: 
+    if a.ast == b.ast:
       result = paramsEqual
-    elif a.ast != nil and b.ast != nil: 
+    elif a.ast != nil and b.ast != nil:
       if exprStructuralEquivalent(a.ast, b.ast): result = paramsEqual
       else: result = paramsIncompatible
-    elif a.ast != nil: 
+    elif a.ast != nil:
       result = paramsEqual
-    elif b.ast != nil: 
+    elif b.ast != nil:
       result = paramsIncompatible
   else:
     result = paramsNotEqual
@@ -723,70 +723,70 @@ proc sameConstraints(a, b: PNode): bool =
       return false
   return true
 
-proc equalParams(a, b: PNode): TParamsEquality = 
+proc equalParams(a, b: PNode): TParamsEquality =
   result = paramsEqual
   var length = sonsLen(a)
-  if length != sonsLen(b): 
+  if length != sonsLen(b):
     result = paramsNotEqual
-  else: 
-    for i in countup(1, length - 1): 
+  else:
+    for i in countup(1, length - 1):
       var m = a.sons[i].sym
       var n = b.sons[i].sym
       assert((m.kind == skParam) and (n.kind == skParam))
       case equalParam(m, n)
-      of paramsNotEqual: 
+      of paramsNotEqual:
         return paramsNotEqual
-      of paramsEqual: 
+      of paramsEqual:
         discard
-      of paramsIncompatible: 
+      of paramsIncompatible:
         result = paramsIncompatible
-      if (m.name.id != n.name.id): 
+      if (m.name.id != n.name.id):
         # BUGFIX
         return paramsNotEqual # paramsIncompatible;
       # continue traversal! If not equal, we can return immediately; else
       # it stays incompatible
     if not sameTypeOrNil(a.sons[0].typ, b.sons[0].typ, {ExactTypeDescValues}):
-      if (a.sons[0].typ == nil) or (b.sons[0].typ == nil): 
+      if (a.sons[0].typ == nil) or (b.sons[0].typ == nil):
         result = paramsNotEqual # one proc has a result, the other not is OK
-      else: 
+      else:
         result = paramsIncompatible # overloading by different
                                     # result types does not work
-  
-proc sameLiteral(x, y: PNode): bool = 
-  if x.kind == y.kind: 
+
+proc sameLiteral(x, y: PNode): bool =
+  if x.kind == y.kind:
     case x.kind
     of nkCharLit..nkInt64Lit: result = x.intVal == y.intVal
     of nkFloatLit..nkFloat64Lit: result = x.floatVal == y.floatVal
     of nkNilLit: result = true
     else: assert(false)
-  
-proc sameRanges(a, b: PNode): bool = 
+
+proc sameRanges(a, b: PNode): bool =
   result = sameLiteral(a.sons[0], b.sons[0]) and
            sameLiteral(a.sons[1], b.sons[1])
 
-proc sameTuple(a, b: PType, c: var TSameTypeClosure): bool = 
+proc sameTuple(a, b: PType, c: var TSameTypeClosure): bool =
   # two tuples are equivalent iff the names, types and positions are the same;
   # however, both types may not have any field names (t.n may be nil) which
   # complicates the matter a bit.
   if sonsLen(a) == sonsLen(b):
     result = true
-    for i in countup(0, sonsLen(a) - 1): 
+    for i in countup(0, sonsLen(a) - 1):
       var x = a.sons[i]
       var y = b.sons[i]
       if IgnoreTupleFields in c.flags:
-        x = skipTypes(x, {tyRange})
-        y = skipTypes(y, {tyRange})
-      
+        x = skipTypes(x, {tyRange, tyGenericInst})
+        y = skipTypes(y, {tyRange, tyGenericInst})
+
       result = sameTypeAux(x, y, c)
-      if not result: return 
+      if not result: return
     if a.n != nil and b.n != nil and IgnoreTupleFields notin c.flags:
-      for i in countup(0, sonsLen(a.n) - 1): 
-        # check field names: 
+      for i in countup(0, sonsLen(a.n) - 1):
+        # check field names:
         if a.n.sons[i].kind == nkSym and b.n.sons[i].kind == nkSym:
           var x = a.n.sons[i].sym
           var y = b.n.sons[i].sym
           result = x.name.id == y.name.id
-          if not result: break 
+          if not result: break
         else: internalError(a.n.info, "sameTuple")
 
 template ifFastObjectTypeCheckFailed(a, b: PType, body: stmt) {.immediate.} =
@@ -797,7 +797,7 @@ template ifFastObjectTypeCheckFailed(a, b: PType, body: stmt) {.immediate.} =
     # expensive structural equality test; however due to the way generic and
     # objects work, if one of the types does **not** contain tfFromGeneric,
     # they cannot be equal. The check ``a.sym.id == b.sym.id`` checks
-    # for the same origin and is essential because we don't want "pure" 
+    # for the same origin and is essential because we don't want "pure"
     # structural type equivalence:
     #
     # type
@@ -835,9 +835,9 @@ proc sameObjectTree(a, b: PNode, c: var TSameTypeClosure): bool =
       of nkStrLit..nkTripleStrLit: result = a.strVal == b.strVal
       of nkEmpty, nkNilLit, nkType: result = true
       else:
-        if sonsLen(a) == sonsLen(b): 
-          for i in countup(0, sonsLen(a) - 1): 
-            if not sameObjectTree(a.sons[i], b.sons[i], c): return 
+        if sonsLen(a) == sonsLen(b):
+          for i in countup(0, sonsLen(a) - 1):
+            if not sameObjectTree(a.sons[i], b.sons[i], c): return
           result = true
 
 proc sameObjectStructures(a, b: PType, c: var TSameTypeClosure): bool =
@@ -853,7 +853,7 @@ proc sameChildrenAux(a, b: PType, c: var TSameTypeClosure): bool =
   result = true
   for i in countup(0, sonsLen(a) - 1):
     result = sameTypeOrNilAux(a.sons[i], b.sons[i], c)
-    if not result: return 
+    if not result: return
 
 proc isGenericAlias*(t: PType): bool =
   return t.kind == tyGenericInst and t.lastSon.kind == tyGenericInst
@@ -866,7 +866,7 @@ proc sameTypeAux(x, y: PType, c: var TSameTypeClosure): bool =
     # believe it or not, the direct check for ``containsOrIncl(c, a, b)``
     # increases bootstrapping time from 2.4s to 3.3s on my laptop! So we cheat
     # again: Since the recursion check is only to not get caught in an endless
-    # recursion, we use a counter and only if it's value is over some 
+    # recursion, we use a counter and only if it's value is over some
     # threshold we perform the expensive exact cycle check:
     if c.recCheck < 3:
       inc c.recCheck
@@ -874,11 +874,11 @@ proc sameTypeAux(x, y: PType, c: var TSameTypeClosure): bool =
       if containsOrIncl(c, a, b): return true
 
   proc sameFlags(a, b: PType): bool {.inline.} =
-    result = eqTypeFlags*a.flags == eqTypeFlags*b.flags   
+    result = eqTypeFlags*a.flags == eqTypeFlags*b.flags
 
   if x == y: return true
   var a = skipTypes(x, {tyGenericInst})
-  var b = skipTypes(y, {tyGenericInst})  
+  var b = skipTypes(y, {tyGenericInst})
   assert(a != nil)
   assert(b != nil)
   if a.kind != b.kind:
@@ -891,7 +891,7 @@ proc sameTypeAux(x, y: PType, c: var TSameTypeClosure): bool =
     of dcEqOrDistinctOf:
       while a.kind == tyDistinct: a = a.sons[0]
       if a.kind != b.kind: return false
-  
+
   if x.kind == tyGenericInst:
     let
       lhs = x.skipGenericAlias
@@ -916,11 +916,11 @@ proc sameTypeAux(x, y: PType, c: var TSameTypeClosure): bool =
       result = sameObjectStructures(a, b, c) and sameFlags(a, b)
   of tyDistinct:
     cycleCheck()
-    if c.cmp == dcEq:      
+    if c.cmp == dcEq:
       if sameFlags(a, b):
         ifFastObjectTypeCheckFailed(a, b):
-          result = sameTypeAux(a.sons[0], b.sons[0], c)     
-    else: 
+          result = sameTypeAux(a.sons[0], b.sons[0], c)
+    else:
       result = sameTypeAux(a.sons[0], b.sons[0], c) and sameFlags(a, b)
   of tyEnum, tyForward:
     # XXX generic enums do not make much sense, but require structural checking
@@ -957,13 +957,13 @@ proc sameTypeAux(x, y: PType, c: var TSameTypeClosure): bool =
         sameValue(a.n.sons[0], b.n.sons[0]) and
         sameValue(a.n.sons[1], b.n.sons[1])
   of tyGenericInst: discard
-  of tyNone: result = false  
+  of tyNone: result = false
 
 proc sameBackendType*(x, y: PType): bool =
   var c = initSameTypeClosure()
   c.flags.incl IgnoreTupleFields
   result = sameTypeAux(x, y, c)
-  
+
 proc compareTypes*(x, y: PType,
                    cmp: TDistinctCompare = dcEq,
                    flags: TTypeCmpFlags = {}): bool =
@@ -972,8 +972,8 @@ proc compareTypes*(x, y: PType,
   c.cmp = cmp
   c.flags = flags
   result = sameTypeAux(x, y, c)
-  
-proc inheritanceDiff*(a, b: PType): int = 
+
+proc inheritanceDiff*(a, b: PType): int =
   # | returns: 0 iff `a` == `b`
   # | returns: -x iff `a` is the x'th direct superclass of `b`
   # | returns: +x iff `a` is the x'th direct subclass of `b`
@@ -985,14 +985,14 @@ proc inheritanceDiff*(a, b: PType): int =
   result = 0
   while x != nil:
     x = skipTypes(x, skipPtrs)
-    if sameObjectTypes(x, b): return 
+    if sameObjectTypes(x, b): return
     x = x.sons[0]
     dec(result)
   var y = b
   result = 0
   while y != nil:
     y = skipTypes(y, skipPtrs)
-    if sameObjectTypes(y, a): return 
+    if sameObjectTypes(y, a): return
     y = y.sons[0]
     inc(result)
   result = high(int)
@@ -1066,7 +1066,7 @@ proc typeAllowedAux(marker: var IntSet, typ: PType, kind: TSymKind,
     if kind == skConst: return t
     var t2 = skipTypes(t.sons[0], abstractInst-{tyTypeDesc})
     case t2.kind
-    of tyVar: 
+    of tyVar:
       if taHeap notin flags: result = t2 # ``var var`` is illegal on the heap
     of tyOpenArray:
       if kind != skParam: result = t
@@ -1075,9 +1075,9 @@ proc typeAllowedAux(marker: var IntSet, typ: PType, kind: TSymKind,
       if kind notin {skParam, skResult}: result = t
       else: result = typeAllowedAux(marker, t2, kind, flags)
   of tyProc:
-    for i in countup(1, sonsLen(t) - 1): 
+    for i in countup(1, sonsLen(t) - 1):
       result = typeAllowedAux(marker, t.sons[i], skParam, flags)
-      if result != nil: break 
+      if result != nil: break
     if result.isNil and t.sons[0] != nil:
       result = typeAllowedAux(marker, t.sons[0], skResult, flags)
   of tyExpr, tyStmt, tyTypeDesc, tyStatic:
@@ -1092,7 +1092,7 @@ proc typeAllowedAux(marker: var IntSet, typ: PType, kind: TSymKind,
     result = t
   of tyNil:
     if kind != skConst: result = t
-  of tyString, tyBool, tyChar, tyEnum, tyInt..tyBigNum, tyCString, tyPointer: 
+  of tyString, tyBool, tyChar, tyEnum, tyInt..tyBigNum, tyCString, tyPointer:
     result = nil
   of tyOrdinal:
     if kind != skParam: result = t
@@ -1132,13 +1132,13 @@ proc typeAllowedAux(marker: var IntSet, typ: PType, kind: TSymKind,
     # prevent cascading errors:
     result = nil
 
-proc typeAllowed*(t: PType, kind: TSymKind): PType = 
+proc typeAllowed*(t: PType, kind: TSymKind): PType =
   # returns 'nil' on success and otherwise the part of the type that is
   # wrong!
   var marker = initIntSet()
   result = typeAllowedAux(marker, t, kind, {})
 
-proc align(address, alignment: BiggestInt): BiggestInt = 
+proc align(address, alignment: BiggestInt): BiggestInt =
   result = (address + (alignment - 1)) and not (alignment - 1)
 
 const
@@ -1147,17 +1147,17 @@ const
   szUnknownSize* = -1
 
 proc computeSizeAux(typ: PType, a: var BiggestInt): BiggestInt
-proc computeRecSizeAux(n: PNode, a, currOffset: var BiggestInt): BiggestInt = 
+proc computeRecSizeAux(n: PNode, a, currOffset: var BiggestInt): BiggestInt =
   var maxAlign, maxSize, b, res: BiggestInt
   case n.kind
-  of nkRecCase: 
+  of nkRecCase:
     assert(n.sons[0].kind == nkSym)
     result = computeRecSizeAux(n.sons[0], a, currOffset)
     maxSize = 0
     maxAlign = 1
-    for i in countup(1, sonsLen(n) - 1): 
+    for i in countup(1, sonsLen(n) - 1):
       case n.sons[i].kind
-      of nkOfBranch, nkElse: 
+      of nkOfBranch, nkElse:
         res = computeRecSizeAux(lastSon(n.sons[i]), b, currOffset)
         if res < 0: return res
         maxSize = max(maxSize, res)
@@ -1166,17 +1166,17 @@ proc computeRecSizeAux(n: PNode, a, currOffset: var BiggestInt): BiggestInt =
     currOffset = align(currOffset, maxAlign) + maxSize
     result = align(result, maxAlign) + maxSize
     a = maxAlign
-  of nkRecList: 
+  of nkRecList:
     result = 0
     maxAlign = 1
-    for i in countup(0, sonsLen(n) - 1): 
+    for i in countup(0, sonsLen(n) - 1):
       res = computeRecSizeAux(n.sons[i], b, currOffset)
       if res < 0: return res
       currOffset = align(currOffset, b) + res
       result = align(result, b) + res
       if b > maxAlign: maxAlign = b
     a = maxAlign
-  of nkSym: 
+  of nkSym:
     result = computeSizeAux(n.sym.typ, a)
     n.sym.offset = int(currOffset)
   else:
@@ -1193,31 +1193,31 @@ proc computeSizeAux(typ: PType, a: var BiggestInt): BiggestInt =
     # size already computed
     result = typ.size
     a = typ.align
-    return 
+    return
   typ.size = szIllegalRecursion # mark as being computed
   case typ.kind
-  of tyInt, tyUInt: 
+  of tyInt, tyUInt:
     result = intSize
     a = result
-  of tyInt8, tyUInt8, tyBool, tyChar: 
+  of tyInt8, tyUInt8, tyBool, tyChar:
     result = 1
     a = result
-  of tyInt16, tyUInt16: 
+  of tyInt16, tyUInt16:
     result = 2
     a = result
-  of tyInt32, tyUInt32, tyFloat32: 
+  of tyInt32, tyUInt32, tyFloat32:
     result = 4
     a = result
-  of tyInt64, tyUInt64, tyFloat64: 
+  of tyInt64, tyUInt64, tyFloat64:
     result = 8
     a = result
   of tyFloat128:
     result = 16
     a = result
-  of tyFloat: 
+  of tyFloat:
     result = floatSize
     a = result
-  of tyProc: 
+  of tyProc:
     if typ.callConv == ccClosure: result = 2 * ptrSize
     else: result = ptrSize
     a = ptrSize
@@ -1232,17 +1232,17 @@ proc computeSizeAux(typ: PType, a: var BiggestInt): BiggestInt =
     let elemSize = computeSizeAux(typ.sons[1], a)
     if elemSize < 0: return elemSize
     result = lengthOrd(typ.sons[0]) * elemSize
-  of tyEnum: 
-    if firstOrd(typ) < 0: 
+  of tyEnum:
+    if firstOrd(typ) < 0:
       result = 4              # use signed int32
-    else: 
+    else:
       length = lastOrd(typ)   # BUGFIX: use lastOrd!
       if length + 1 < `shl`(1, 8): result = 1
       elif length + 1 < `shl`(1, 16): result = 2
       elif length + 1 < `shl`(BiggestInt(1), 32): result = 4
       else: result = 8
     a = result
-  of tySet: 
+  of tySet:
     length = lengthOrd(typ.sons[0])
     if length <= 8: result = 1
     elif length <= 16: result = 2
@@ -1251,32 +1251,32 @@ proc computeSizeAux(typ: PType, a: var BiggestInt): BiggestInt =
     elif align(length, 8) mod 8 == 0: result = align(length, 8) div 8
     else: result = align(length, 8) div 8 + 1
     a = result
-  of tyRange: 
+  of tyRange:
     result = computeSizeAux(typ.sons[0], a)
-  of tyTuple: 
+  of tyTuple:
     result = 0
     maxAlign = 1
-    for i in countup(0, sonsLen(typ) - 1): 
+    for i in countup(0, sonsLen(typ) - 1):
       res = computeSizeAux(typ.sons[i], a)
       if res < 0: return res
       maxAlign = max(maxAlign, a)
       result = align(result, a) + res
     result = align(result, maxAlign)
     a = maxAlign
-  of tyObject: 
-    if typ.sons[0] != nil: 
+  of tyObject:
+    if typ.sons[0] != nil:
       result = computeSizeAux(typ.sons[0], a)
-      if result < 0: return 
+      if result < 0: return
       maxAlign = a
-    elif isObjectWithTypeFieldPredicate(typ): 
+    elif isObjectWithTypeFieldPredicate(typ):
       result = intSize
       maxAlign = result
-    else: 
+    else:
       result = 0
       maxAlign = 1
     currOffset = result
     result = computeRecSizeAux(typ.n, a, currOffset)
-    if result < 0: return 
+    if result < 0: return
     if a < maxAlign: a = maxAlign
     result = align(result, a)
   of tyGenericInst, tyDistinct, tyGenericBody, tyMutable, tyConst, tyIter:
@@ -1290,7 +1290,7 @@ proc computeSizeAux(typ: PType, a: var BiggestInt): BiggestInt =
   typ.size = result
   typ.align = int16(a)
 
-proc computeSize(typ: PType): BiggestInt = 
+proc computeSize(typ: PType): BiggestInt =
   var a: BiggestInt = 1
   result = computeSizeAux(typ, a)
 
@@ -1299,7 +1299,7 @@ proc getReturnType*(s: PSym): PType =
   assert s.kind in skProcKinds
   result = s.typ.sons[0]
 
-proc getSize(typ: PType): BiggestInt = 
+proc getSize(typ: PType): BiggestInt =
   result = computeSize(typ)
   if result < 0: internalError("getSize: " & $typ.kind)
 
@@ -1317,7 +1317,7 @@ proc containsGenericTypeIter(t: PType, closure: RootRef): bool =
 
   return false
 
-proc containsGenericType*(t: PType): bool = 
+proc containsGenericType*(t: PType): bool =
   result = iterOverType(t, containsGenericTypeIter, nil)
 
 proc baseOfDistinct*(t: PType): PType =
@@ -1336,7 +1336,7 @@ proc baseOfDistinct*(t: PType): PType =
 
 proc safeInheritanceDiff*(a, b: PType): int =
   # same as inheritanceDiff but checks for tyError:
-  if a.kind == tyError or b.kind == tyError: 
+  if a.kind == tyError or b.kind == tyError:
     result = -1
   else:
     result = inheritanceDiff(a, b)
@@ -1356,7 +1356,7 @@ proc compatibleEffects*(formal, actual: PType): bool =
   assert formal.kind == tyProc and actual.kind == tyProc
   internalAssert formal.n.sons[0].kind == nkEffectList
   internalAssert actual.n.sons[0].kind == nkEffectList
-  
+
   var spec = formal.n.sons[0]
   if spec.len != 0:
     var real = actual.n.sons[0]
diff --git a/compiler/vm.nim b/compiler/vm.nim
index a36de1c20..f0a0135e8 100644
--- a/compiler/vm.nim
+++ b/compiler/vm.nim
@@ -239,7 +239,7 @@ proc pushSafePoint(f: PStackFrame; pc: int) =
 
 proc popSafePoint(f: PStackFrame) = discard f.safePoints.pop()
 
-proc cleanUpOnException(c: PCtx; tos: PStackFrame): 
+proc cleanUpOnException(c: PCtx; tos: PStackFrame):
                                               tuple[pc: int, f: PStackFrame] =
   let raisedType = c.currentExceptionA.typ.skipTypes(abstractPtrs)
   var f = tos
@@ -257,7 +257,7 @@ proc cleanUpOnException(c: PCtx; tos: PStackFrame):
       let exceptType = c.types[c.code[pc2].regBx-wordExcess].skipTypes(
                           abstractPtrs)
       if inheritanceDiff(exceptType, raisedType) <= 0:
-        # mark exception as handled but keep it in B for 
+        # mark exception as handled but keep it in B for
         # the getCurrentException() builtin:
         c.currentExceptionB = c.currentExceptionA
         c.currentExceptionA = nil
@@ -349,14 +349,14 @@ proc opConv*(dest: var TFullReg, src: TFullReg, desttyp, srctyp: PType): bool =
       if dest.kind != rkFloat:
         myreset(dest); dest.kind = rkFloat
       case skipTypes(srctyp, abstractRange).kind
-      of tyInt..tyInt64, tyUInt..tyUInt64, tyEnum, tyBool, tyChar: 
+      of tyInt..tyInt64, tyUInt..tyUInt64, tyEnum, tyBool, tyChar:
         dest.floatVal = toFloat(src.intVal.int)
       else:
         dest.floatVal = src.floatVal
     else:
       asgnComplex(dest, src)
 
-proc compile(c: PCtx, s: PSym): int = 
+proc compile(c: PCtx, s: PSym): int =
   result = vmgen.genProc(c, s)
   when debugEchoCode: c.echoCode result
   #c.echoCode
@@ -396,10 +396,10 @@ proc rawExecute(c: PCtx, start: int, tos: PStackFrame): TFullReg =
       pc = tos.comesFrom
       tos = tos.next
       let retVal = regs[0]
-      if tos.isNil: 
+      if tos.isNil:
         #echo "RET ", retVal.rendertree
         return retVal
-      
+
       move(regs, tos.slots)
       assert c.code[pc].opcode in {opcIndCall, opcIndCallAsgn}
       if c.code[pc].opcode == opcIndCallAsgn:
@@ -653,7 +653,7 @@ proc rawExecute(c: PCtx, start: int, tos: PStackFrame): TFullReg =
     of opcSubu:
       decodeBC(rkInt)
       regs[ra].intVal = regs[rb].intVal -% regs[rc].intVal
-    of opcMulu: 
+    of opcMulu:
       decodeBC(rkInt)
       regs[ra].intVal = regs[rb].intVal *% regs[rc].intVal
     of opcDivu:
@@ -726,7 +726,7 @@ proc rawExecute(c: PCtx, start: int, tos: PStackFrame): TFullReg =
     of opcLeSet:
       decodeBC(rkInt)
       regs[ra].intVal = ord(containsSets(regs[rb].node, regs[rc].node))
-    of opcEqSet: 
+    of opcEqSet:
       decodeBC(rkInt)
       regs[ra].intVal = ord(equalSets(regs[rb].node, regs[rc].node))
     of opcLtSet:
@@ -737,9 +737,9 @@ proc rawExecute(c: PCtx, start: int, tos: PStackFrame): TFullReg =
     of opcMulSet:
       decodeBC(rkNode)
       createSet(regs[ra])
-      move(regs[ra].node.sons, 
+      move(regs[ra].node.sons,
             nimsets.intersectSets(regs[rb].node, regs[rc].node).sons)
-    of opcPlusSet: 
+    of opcPlusSet:
       decodeBC(rkNode)
       createSet(regs[ra])
       move(regs[ra].node.sons,
@@ -753,7 +753,7 @@ proc rawExecute(c: PCtx, start: int, tos: PStackFrame): TFullReg =
       decodeBC(rkNode)
       createSet(regs[ra])
       move(regs[ra].node.sons,
-           nimsets.symdiffSets(regs[rb].node, regs[rc].node).sons)    
+           nimsets.symdiffSets(regs[rb].node, regs[rc].node).sons)
     of opcConcatStr:
       decodeBC(rkNode)
       createStr regs[ra]
@@ -793,7 +793,7 @@ proc rawExecute(c: PCtx, start: int, tos: PStackFrame): TFullReg =
       assert c.code[pc].opcode == opcSubStr
       let rd = c.code[pc].regA
       createStr regs[ra]
-      regs[ra].node.strVal = substr(regs[rb].node.strVal, 
+      regs[ra].node.strVal = substr(regs[rb].node.strVal,
                                     regs[rc].intVal.int, regs[rd].intVal.int)
     of opcParseFloat:
       decodeBC(rkInt)
@@ -896,12 +896,12 @@ proc rawExecute(c: PCtx, start: int, tos: PStackFrame): TFullReg =
       # we know the next instruction is a 'fjmp':
       let branch = c.constants[instr.regBx-wordExcess]
       var cond = false
-      for j in countup(0, sonsLen(branch) - 2): 
-        if overlap(regs[ra].regToNode, branch.sons[j]): 
+      for j in countup(0, sonsLen(branch) - 2):
+        if overlap(regs[ra].regToNode, branch.sons[j]):
           cond = true
           break
       assert c.code[pc+1].opcode == opcFJmp
-      inc pc 
+      inc pc
       # we skip this instruction so that the final 'inc(pc)' skips
       # the following jump
       if not cond:
@@ -1273,7 +1273,7 @@ proc rawExecute(c: PCtx, start: int, tos: PStackFrame): TFullReg =
     of opcNSetIntVal:
       decodeB(rkNode)
       var dest = regs[ra].node
-      if dest.kind in {nkCharLit..nkInt64Lit} and 
+      if dest.kind in {nkCharLit..nkInt64Lit} and
          regs[rb].kind in {rkInt}:
         dest.intVal = regs[rb].intVal
       else:
@@ -1281,24 +1281,24 @@ proc rawExecute(c: PCtx, start: int, tos: PStackFrame): TFullReg =
     of opcNSetFloatVal:
       decodeB(rkNode)
       var dest = regs[ra].node
-      if dest.kind in {nkFloatLit..nkFloat64Lit} and 
+      if dest.kind in {nkFloatLit..nkFloat64Lit} and
          regs[rb].kind in {rkFloat}:
         dest.floatVal = regs[rb].floatVal
-      else: 
+      else:
         stackTrace(c, tos, pc, errFieldXNotFound, "floatVal")
     of opcNSetSymbol:
       decodeB(rkNode)
       var dest = regs[ra].node
       if dest.kind == nkSym and regs[rb].node.kind == nkSym:
         dest.sym = regs[rb].node.sym
-      else: 
+      else:
         stackTrace(c, tos, pc, errFieldXNotFound, "symbol")
     of opcNSetIdent:
       decodeB(rkNode)
       var dest = regs[ra].node
       if dest.kind == nkIdent and regs[rb].node.kind == nkIdent:
         dest.ident = regs[rb].node.ident
-      else: 
+      else:
         stackTrace(c, tos, pc, errFieldXNotFound, "ident")
     of opcNSetType:
       decodeB(rkNode)
@@ -1309,7 +1309,7 @@ proc rawExecute(c: PCtx, start: int, tos: PStackFrame): TFullReg =
     of opcNSetStrVal:
       decodeB(rkNode)
       var dest = regs[ra].node
-      if dest.kind in {nkStrLit..nkTripleStrLit} and 
+      if dest.kind in {nkStrLit..nkTripleStrLit} and
          regs[rb].kind in {rkNode}:
         dest.strVal = regs[rb].node.strVal
       else:
@@ -1435,8 +1435,9 @@ proc evalConstExprAux(module, prc: PSym, n: PNode, mode: TEvalMode): PNode =
   newSeq(tos.slots, c.prc.maxSlots)
   #for i in 0 .. <c.prc.maxSlots: tos.slots[i] = newNode(nkEmpty)
   result = rawExecute(c, start, tos).regToNode
+  if result.info.line < 0: result.info = n.info
 
-proc evalConstExpr*(module: PSym, e: PNode): PNode = 
+proc evalConstExpr*(module: PSym, e: PNode): PNode =
   result = evalConstExprAux(module, nil, e, emConst)
 
 proc evalStaticExpr*(module: PSym, e: PNode, prc: PSym): PNode =
@@ -1496,6 +1497,7 @@ proc evalMacroCall*(module: PSym, n, nOrig: PNode, sym: PSym): PNode =
   # temporary storage:
   #for i in L .. <maxSlots: tos.slots[i] = newNode(nkEmpty)
   result = rawExecute(c, start, tos).regToNode
+  if result.info.line < 0: result.info = n.info
   if cyclicTree(result): globalError(n.info, errCyclicTree)
   dec(evalMacroCounter)
   c.callsite = nil