summary refs log tree commit diff stats
diff options
context:
space:
mode:
-rw-r--r--changelog.md15
-rw-r--r--compiler/ast.nim9
-rw-r--r--compiler/ccgcalls.nim36
-rw-r--r--compiler/ccgexprs.nim24
-rw-r--r--compiler/ccgstmts.nim45
-rw-r--r--compiler/ccgtypes.nim10
-rw-r--r--compiler/cgen.nim6
-rw-r--r--compiler/cgendata.nim9
-rw-r--r--compiler/commands.nim2
-rw-r--r--compiler/destroyer.nim158
-rw-r--r--compiler/lambdalifting.nim8
-rw-r--r--compiler/lookups.nim3
-rw-r--r--compiler/msgs.nim9
-rw-r--r--compiler/options.nim7
-rw-r--r--compiler/parampatterns.nim32
-rw-r--r--compiler/parser.nim13
-rw-r--r--compiler/pragmas.nim8
-rw-r--r--compiler/semcall.nim6
-rw-r--r--compiler/semexprs.nim56
-rw-r--r--compiler/seminst.nim34
-rw-r--r--compiler/semobjconstr.nim2
-rw-r--r--compiler/semtypes.nim8
-rw-r--r--compiler/semtypinst.nim4
-rw-r--r--compiler/sighashes.nim2
-rw-r--r--compiler/sigmatch.nim5
-rw-r--r--compiler/types.nim2
-rw-r--r--compiler/vmdef.nim2
-rw-r--r--compiler/wordrecg.nim4
-rw-r--r--config/nimdoc.cfg2
-rw-r--r--doc/lib.rst33
-rw-r--r--doc/manual/lexing.txt6
-rw-r--r--doc/manual/stmts.txt4
-rw-r--r--doc/nimc.rst2
-rw-r--r--lib/core/macros.nim4
-rw-r--r--lib/js/dom.nim44
-rw-r--r--lib/pure/algorithm.nim2
-rw-r--r--lib/pure/asyncfile.nim4
-rw-r--r--lib/pure/collections/tables.nim93
-rw-r--r--lib/pure/dynlib.nim43
-rw-r--r--lib/pure/json.nim12
-rw-r--r--lib/pure/net.nim3
-rw-r--r--lib/pure/times.nim12
-rw-r--r--lib/pure/unittest.nim7
-rw-r--r--lib/pure/xmlparser.nim25
-rw-r--r--lib/system.nim21
-rw-r--r--lib/system/alloc.nim81
-rw-r--r--lib/system/chcks.nim5
-rw-r--r--lib/wrappers/mysql.nim4
-rw-r--r--lib/wrappers/openssl.nim2
-rw-r--r--nimsuggest/nimsuggest.nim6
-rw-r--r--readme.md11
-rw-r--r--tests/async/hello.txt1
-rw-r--r--tests/async/tasyncfile.nim11
-rw-r--r--tests/ccgbugs/mymodule.nim14
-rw-r--r--tests/ccgbugs/tforward_decl_only.nim34
-rw-r--r--tests/ccgbugs/tresult_of_array.nim29
-rw-r--r--tests/concepts/tseqofconcept.nim19
-rw-r--r--tests/cpp/tcovariancerules.nim2
-rw-r--r--tests/cpp/tvector_iterator.nim2
-rw-r--r--tests/errmsgs/twrong_at_operator.nim15
-rw-r--r--tests/exception/tfinally.nim22
-rw-r--r--tests/fragmentation/tfragment_gc.nim1
-rw-r--r--tests/macros/tdumpastgen.nim28
-rw-r--r--tests/metatype/tstaticparammacro.nim13
-rw-r--r--tests/metatype/ttypeselectors.nim64
-rw-r--r--tests/metatype/typeclassinference.nim3
-rw-r--r--tests/misc/tidentconcatenations.nim32
-rw-r--r--tests/statictypes/tcryptodigest.nim44
-rw-r--r--tests/statictypes/tstaticimportcpp.nim10
-rw-r--r--tests/stdlib/tjsonmacro.nim15
-rw-r--r--tests/stdlib/ttimes.nim10
-rw-r--r--tests/system/talloc.nim (renamed from tests/system/alloc.nim)15
-rw-r--r--tests/system/talloc2.nim37
-rw-r--r--tests/system/tio.nim (renamed from tests/system/io.nim)0
-rw-r--r--tests/system/tparams.nim (renamed from tests/system/params.nim)0
-rw-r--r--tests/system/tsystem_misc.nim29
-rw-r--r--tests/varres/tvarres1.nim2
-rw-r--r--tests/varres/tvarres_via_forwarding.nim12
-rw-r--r--tests/varres/twrong_parameter.nim16
-rw-r--r--todo.txt71
-rw-r--r--web/website.ini2
81 files changed, 1182 insertions, 316 deletions
diff --git a/changelog.md b/changelog.md
index 6844d3791..b8d28b633 100644
--- a/changelog.md
+++ b/changelog.md
@@ -13,6 +13,8 @@
 
 - ``re.split`` now also supports the ``maxsplit`` parameter for consistency
   with ``strutils.split``.
+- Added ``system.toOpenArray`` in order to support zero-copy slicing
+  operations. This is currently not yet available for the JavaScript target.
 
 ### Library changes
 
@@ -20,6 +22,11 @@
 
 ### Language changes
 
+- The `importcpp` pragma now allows importing the listed fields of generic
+  C++ types. Support for numeric parameters have also been added through
+  the use of `static[T]` types.
+  (#6415)
+
 ### Tool changes
 
 - ``jsondoc2`` has been renamed ``jsondoc``, similar to how ``doc2`` was renamed
@@ -27,9 +34,5 @@
 
 ### Compiler changes
 
-### Bugfixes
-
-- The `importcpp` pragma now allows importing the listed fields of generic
-  C++ types. Support for numeric parameters have also been added through
-  the use of `static[T]` types.
-  (#6415)
+- The VM's instruction count limit was raised to 1 billion instructions in order
+  to support more complex computations at compile-time.
diff --git a/compiler/ast.nim b/compiler/ast.nim
index 8286e3bb7..a28a7e7e3 100644
--- a/compiler/ast.nim
+++ b/compiler/ast.nim
@@ -981,6 +981,7 @@ const
 
   nkPragmaCallKinds* = {nkExprColonExpr, nkCall, nkCallStrLit}
   nkLiterals* = {nkCharLit..nkTripleStrLit}
+  nkFloatLiterals* = {nkFloatLit..nkFloat128Lit}
   nkLambdaKinds* = {nkLambda, nkDo}
   declarativeDefs* = {nkProcDef, nkFuncDef, nkMethodDef, nkIteratorDef, nkConverterDef}
   procDefs* = nkLambdaKinds + declarativeDefs
@@ -1476,7 +1477,7 @@ proc copyNode*(src: PNode): PNode =
       echo "COMES FROM ", src.id
   case src.kind
   of nkCharLit..nkUInt64Lit: result.intVal = src.intVal
-  of nkFloatLit..nkFloat128Lit: result.floatVal = src.floatVal
+  of nkFloatLiterals: result.floatVal = src.floatVal
   of nkSym: result.sym = src.sym
   of nkIdent: result.ident = src.ident
   of nkStrLit..nkTripleStrLit: result.strVal = src.strVal
@@ -1495,7 +1496,7 @@ proc shallowCopy*(src: PNode): PNode =
       echo "COMES FROM ", src.id
   case src.kind
   of nkCharLit..nkUInt64Lit: result.intVal = src.intVal
-  of nkFloatLit..nkFloat128Lit: result.floatVal = src.floatVal
+  of nkFloatLiterals: result.floatVal = src.floatVal
   of nkSym: result.sym = src.sym
   of nkIdent: result.ident = src.ident
   of nkStrLit..nkTripleStrLit: result.strVal = src.strVal
@@ -1515,7 +1516,7 @@ proc copyTree*(src: PNode): PNode =
       echo "COMES FROM ", src.id
   case src.kind
   of nkCharLit..nkUInt64Lit: result.intVal = src.intVal
-  of nkFloatLit..nkFloat128Lit: result.floatVal = src.floatVal
+  of nkFloatLiterals: result.floatVal = src.floatVal
   of nkSym: result.sym = src.sym
   of nkIdent: result.ident = src.ident
   of nkStrLit..nkTripleStrLit: result.strVal = src.strVal
@@ -1564,7 +1565,7 @@ proc getInt*(a: PNode): BiggestInt =
 
 proc getFloat*(a: PNode): BiggestFloat =
   case a.kind
-  of nkFloatLit..nkFloat128Lit: result = a.floatVal
+  of nkFloatLiterals: result = a.floatVal
   else:
     internalError(a.info, "getFloat")
     result = 0.0
diff --git a/compiler/ccgcalls.nim b/compiler/ccgcalls.nim
index 18741732c..5f14b6804 100644
--- a/compiler/ccgcalls.nim
+++ b/compiler/ccgcalls.nim
@@ -83,6 +83,8 @@ proc isInCurrentFrame(p: BProc, n: PNode): bool =
     result = isInCurrentFrame(p, n.sons[0])
   else: discard
 
+proc genIndexCheck(p: BProc; arr, idx: TLoc)
+
 proc openArrayLoc(p: BProc, n: PNode): Rope =
   var a: TLoc
 
@@ -93,18 +95,28 @@ proc openArrayLoc(p: BProc, n: PNode): Rope =
     initLocExpr(p, q[1], a)
     initLocExpr(p, q[2], b)
     initLocExpr(p, q[3], c)
-    let fmt =
-      case skipTypes(a.t, abstractVar+{tyPtr}).kind
-      of tyOpenArray, tyVarargs, tyArray:
-        "($1)+($2), ($3)-($2)+1"
-      of tyString, tySequence:
-        if skipTypes(n.typ, abstractInst).kind == tyVar and
-            not compileToCpp(p.module):
-          "(*$1)->data+($2), ($3)-($2)+1"
-        else:
-          "$1->data+($2), ($3)-($2)+1"
-      else: (internalError("openArrayLoc: " & typeToString(a.t)); "")
-    result = fmt % [rdLoc(a), rdLoc(b), rdLoc(c)]
+    # but first produce the required index checks:
+    if optBoundsCheck in p.options:
+      genIndexCheck(p, a, b)
+      genIndexCheck(p, a, c)
+    let ty = skipTypes(a.t, abstractVar+{tyPtr})
+    case ty.kind
+    of tyArray:
+      let first = firstOrd(ty)
+      if first == 0:
+        result = "($1)+($2), ($3)-($2)+1" % [rdLoc(a), rdLoc(b), rdLoc(c)]
+      else:
+        result = "($1)+(($2)-($4)), ($3)-($2)+1" % [rdLoc(a), rdLoc(b), rdLoc(c), intLiteral(first)]
+    of tyOpenArray, tyVarargs:
+      result = "($1)+($2), ($3)-($2)+1" % [rdLoc(a), rdLoc(b), rdLoc(c)]
+    of tyString, tySequence:
+      if skipTypes(n.typ, abstractInst).kind == tyVar and
+          not compileToCpp(p.module):
+        result = "(*$1)->data+($2), ($3)-($2)+1" % [rdLoc(a), rdLoc(b), rdLoc(c)]
+      else:
+        result = "$1->data+($2), ($3)-($2)+1" % [rdLoc(a), rdLoc(b), rdLoc(c)]
+    else:
+      internalError("openArrayLoc: " & typeToString(a.t))
   else:
     initLocExpr(p, n, a)
     case skipTypes(a.t, abstractVar).kind
diff --git a/compiler/ccgexprs.nim b/compiler/ccgexprs.nim
index ba0820e93..dc06c8482 100644
--- a/compiler/ccgexprs.nim
+++ b/compiler/ccgexprs.nim
@@ -880,6 +880,23 @@ proc genCStringElem(p: BProc, n, x, y: PNode, d: var TLoc) =
   putIntoDest(p, d, n,
               rfmt(nil, "$1[$2]", rdLoc(a), rdCharLoc(b)), a.storage)
 
+proc genIndexCheck(p: BProc; arr, idx: TLoc) =
+  let ty = skipTypes(arr.t, abstractVarRange)
+  case ty.kind
+  of tyOpenArray, tyVarargs:
+    linefmt(p, cpsStmts, "if ((NU)($1) >= (NU)($2Len_0)) #raiseIndexError();$n",
+            rdLoc(idx), rdLoc(arr))
+  of tyArray:
+    let first = intLiteral(firstOrd(ty))
+    if tfUncheckedArray notin ty.flags:
+      linefmt(p, cpsStmts, "if ($1 < $2 || $1 > $3) #raiseIndexError();$n",
+              rdCharLoc(idx), first, intLiteral(lastOrd(ty)))
+  of tySequence, tyString:
+    linefmt(p, cpsStmts,
+          "if ((NU)($1) >= (NU)($2->$3)) #raiseIndexError();$n",
+          rdLoc(idx), rdLoc(arr), lenField(p))
+  else: discard
+
 proc genOpenArrayElem(p: BProc, n, x, y: PNode, d: var TLoc) =
   var a, b: TLoc
   initLocExpr(p, x, a)
@@ -1364,6 +1381,7 @@ proc genOf(p: BProc, x: PNode, typ: PType, d: var TLoc) =
     if t.kind notin {tyVar, tyLent} or not p.module.compileToCpp:
       r = rfmt(nil, "(*$1)", r)
     t = skipTypes(t.lastSon, typedescInst)
+  discard getTypeDesc(p.module, t)
   if not p.module.compileToCpp:
     while t.kind == tyObject and t.sons[0] != nil:
       add(r, ~".Sup")
@@ -1910,7 +1928,8 @@ proc genSetConstr(p: BProc, e: PNode, d: var TLoc) =
     if getSize(e.typ) > 8:
       # big set:
       useStringh(p.module)
-      lineF(p, cpsStmts, "memset($1, 0, sizeof($1));$n", [rdLoc(d)])
+      lineF(p, cpsStmts, "memset($1, 0, sizeof($2));$n",
+          [rdLoc(d), getTypeDesc(p.module, e.typ)])
       for i in countup(0, sonsLen(e) - 1):
         if e.sons[i].kind == nkRange:
           getTemp(p, getSysType(tyInt), idx) # our counter
@@ -2042,6 +2061,7 @@ proc upConv(p: BProc, n: PNode, d: var TLoc) =
       if t.kind notin {tyVar, tyLent} or not p.module.compileToCpp:
         r = "(*$1)" % [r]
       t = skipTypes(t.lastSon, abstractInst)
+    discard getTypeDesc(p.module, t)
     if not p.module.compileToCpp:
       while t.kind == tyObject and t.sons[0] != nil:
         add(r, ".Sup")
@@ -2061,6 +2081,7 @@ proc upConv(p: BProc, n: PNode, d: var TLoc) =
 
 proc downConv(p: BProc, n: PNode, d: var TLoc) =
   if p.module.compileToCpp:
+    discard getTypeDesc(p.module, skipTypes(n[0].typ, abstractPtrs))
     expr(p, n.sons[0], d)     # downcast does C++ for us
   else:
     var dest = skipTypes(n.typ, abstractPtrs)
@@ -2069,6 +2090,7 @@ proc downConv(p: BProc, n: PNode, d: var TLoc) =
     while arg.kind == nkObjDownConv: arg = arg.sons[0]
 
     var src = skipTypes(arg.typ, abstractPtrs)
+    discard getTypeDesc(p.module, src)
     var a: TLoc
     initLocExpr(p, arg, a)
     var r = rdLoc(a)
diff --git a/compiler/ccgstmts.nim b/compiler/ccgstmts.nim
index 6b8ba2b02..f6c4204e8 100644
--- a/compiler/ccgstmts.nim
+++ b/compiler/ccgstmts.nim
@@ -37,6 +37,10 @@ proc isAssignedImmediately(n: PNode): bool {.inline.} =
     return false
   result = true
 
+proc inExceptBlockLen(p: BProc): int = 
+  for x in p.nestedTryStmts:
+    if x.inExcept: result.inc
+
 proc genVarTuple(p: BProc, n: PNode) =
   var tup, field: TLoc
   if n.kind != nkVarTuple: internalError(n.info, "genVarTuple")
@@ -96,7 +100,7 @@ proc startBlock(p: BProc, start: FormatStr = "{$n",
   setLen(p.blocks, result + 1)
   p.blocks[result].id = p.labels
   p.blocks[result].nestedTryStmts = p.nestedTryStmts.len.int16
-  p.blocks[result].nestedExceptStmts = p.inExceptBlock.int16
+  p.blocks[result].nestedExceptStmts = p.inExceptBlockLen.int16
 
 proc assignLabel(b: var TBlock): Rope {.inline.} =
   b.label = "LA" & b.id.rope
@@ -344,26 +348,22 @@ proc blockLeaveActions(p: BProc, howManyTrys, howManyExcepts: int) =
   # Called by return and break stmts.
   # Deals with issues faced when jumping out of try/except/finally stmts,
 
-  var stack: seq[PNode]
-  newSeq(stack, 0)
+  var stack = newSeq[tuple[n: PNode, inExcept: bool]](0)
 
-  var alreadyPoppedCnt = p.inExceptBlock
   for i in countup(1, howManyTrys):
+    let tryStmt = p.nestedTryStmts.pop
     if not p.module.compileToCpp or optNoCppExceptions in gGlobalOptions:
       # Pop safe points generated by try
-      if alreadyPoppedCnt > 0:
-        dec alreadyPoppedCnt
-      else:
+      if not tryStmt.inExcept:
         linefmt(p, cpsStmts, "#popSafePoint();$n")
 
     # Pop this try-stmt of the list of nested trys
     # so we don't infinite recurse on it in the next step.
-    var tryStmt = p.nestedTryStmts.pop
     stack.add(tryStmt)
 
     # Find finally-stmt for this try-stmt
     # and generate a copy of its sons
-    var finallyStmt = lastSon(tryStmt)
+    var finallyStmt = lastSon(tryStmt.n)
     if finallyStmt.kind == nkFinally:
       genStmts(p, finallyStmt.sons[0])
 
@@ -384,7 +384,7 @@ proc genReturnStmt(p: BProc, t: PNode) =
   if (t.sons[0].kind != nkEmpty): genStmts(p, t.sons[0])
   blockLeaveActions(p,
     howManyTrys    = p.nestedTryStmts.len,
-    howManyExcepts = p.inExceptBlock)
+    howManyExcepts = p.inExceptBlockLen)
   if (p.finallySafePoints.len > 0):
     # If we're in a finally block, and we came here by exception
     # consume it before we return.
@@ -567,15 +567,15 @@ proc genBreakStmt(p: BProc, t: PNode) =
   let label = assignLabel(p.blocks[idx])
   blockLeaveActions(p,
     p.nestedTryStmts.len - p.blocks[idx].nestedTryStmts,
-    p.inExceptBlock - p.blocks[idx].nestedExceptStmts)
+    p.inExceptBlockLen - p.blocks[idx].nestedExceptStmts)
   genLineDir(p, t)
   lineF(p, cpsStmts, "goto $1;$n", [label])
 
 proc genRaiseStmt(p: BProc, t: PNode) =
-  if p.inExceptBlock > 0 and p.inExceptBlock == p.nestedTryStmts.len:
+  if p.nestedTryStmts.len > 0 and p.nestedTryStmts[^1].inExcept:
     # if the current try stmt have a finally block,
     # we must execute it before reraising
-    var finallyBlock = p.nestedTryStmts[p.nestedTryStmts.len - 1].lastSon
+    var finallyBlock = p.nestedTryStmts[^1].n[^1]
     if finallyBlock.kind == nkFinally:
       genSimpleBlock(p, finallyBlock.sons[0])
   if t.sons[0].kind != nkEmpty:
@@ -812,14 +812,14 @@ proc genTryCpp(p: BProc, t: PNode, d: var TLoc) =
 
   let end_label = getLabel(p)
   discard cgsym(p.module, "Exception")
-  add(p.nestedTryStmts, t)
+  add(p.nestedTryStmts, (t, false))
   startBlock(p, "try {$n")
   expr(p, t[0], d)
   endBlock(p)
 
   var catchAllPresent = false
 
-  inc p.inExceptBlock
+  p.nestedTryStmts[^1].inExcept = true
   for i in 1..<t.len:
     if t[i].kind != nkExceptBranch: break
 
@@ -839,6 +839,8 @@ proc genTryCpp(p: BProc, t: PNode, d: var TLoc) =
         genExceptBranchBody(t[i][^1])  # exception handler body will duplicated for every type
         endBlock(p)
 
+  discard pop(p.nestedTryStmts)
+
   if not catchAllPresent and t[^1].kind == nkFinally:
     # finally requires catch all presence
     startBlock(p, "catch (...) {$n")
@@ -846,9 +848,6 @@ proc genTryCpp(p: BProc, t: PNode, d: var TLoc) =
     line(p, cpsStmts, ~"throw;$n")
     endBlock(p)
 
-  dec p.inExceptBlock
-  discard pop(p.nestedTryStmts)
-
   if t[^1].kind == nkFinally:
     genSimpleBlock(p, t[^1][0])
 
@@ -902,7 +901,7 @@ proc genTry(p: BProc, t: PNode, d: var TLoc) =
     linefmt(p, cpsStmts, "$1.status = setjmp($1.context);$n", safePoint)
   startBlock(p, "if ($1.status == 0) {$n", [safePoint])
   var length = sonsLen(t)
-  add(p.nestedTryStmts, t)
+  add(p.nestedTryStmts, (t, false))
   expr(p, t.sons[0], d)
   linefmt(p, cpsStmts, "#popSafePoint();$n")
   endBlock(p)
@@ -910,7 +909,7 @@ proc genTry(p: BProc, t: PNode, d: var TLoc) =
   linefmt(p, cpsStmts, "#popSafePoint();$n")
   if optStackTrace in p.options:
     linefmt(p, cpsStmts, "#setFrame((TFrame*)&FR_);$n")
-  inc p.inExceptBlock
+  p.nestedTryStmts[^1].inExcept = true
   var i = 1
   while (i < length) and (t.sons[i].kind == nkExceptBranch):
     # bug #4230: avoid false sharing between branches:
@@ -941,7 +940,6 @@ proc genTry(p: BProc, t: PNode, d: var TLoc) =
       linefmt(p, cpsStmts, "#popCurrentException();$n")
       endBlock(p)
     inc(i)
-  dec p.inExceptBlock
   discard pop(p.nestedTryStmts)
   endBlock(p) # end of else block
   if i < length and t.sons[i].kind == nkFinally:
@@ -965,6 +963,7 @@ proc genAsmOrEmitStmt(p: BProc, t: PNode, isAsmStmt=false): Rope =
       elif sym.kind == skType:
         res.add($getTypeDesc(p.module, sym.typ))
       else:
+        discard getTypeDesc(p.module, skipTypes(sym.typ, abstractPtrs))
         var r = sym.loc.r
         if r == nil:
           # if no name has already been given,
@@ -975,10 +974,10 @@ proc genAsmOrEmitStmt(p: BProc, t: PNode, isAsmStmt=false): Rope =
     of nkTypeOfExpr:
       res.add($getTypeDesc(p.module, t.sons[i].typ))
     else:
+      discard getTypeDesc(p.module, skipTypes(t[i].typ, abstractPtrs))
       var a: TLoc
-      initLocExpr(p, t.sons[i], a)
+      initLocExpr(p, t[i], a)
       res.add($a.rdLoc)
-      #internalError(t.sons[i].info, "genAsmOrEmitStmt()")
 
   if isAsmStmt and hasGnuAsm in CC[cCompiler].props:
     for x in splitLines(res):
diff --git a/compiler/ccgtypes.nim b/compiler/ccgtypes.nim
index bdba34e36..ed44c577d 100644
--- a/compiler/ccgtypes.nim
+++ b/compiler/ccgtypes.nim
@@ -368,6 +368,8 @@ proc getTypeForward(m: BModule, typ: PType; sig: SigHash): Rope =
     if not isImportedType(concrete):
       addf(m.s[cfsForwardTypes], getForwardStructFormat(m),
           [structOrUnion(typ), result])
+    else:
+      pushType(m, concrete)
     doAssert m.forwTypeCache[sig] == result
   else: internalError("getTypeForward(" & $typ.kind & ')')
 
@@ -665,7 +667,6 @@ proc getTypeDescAux(m: BModule, origTyp: PType, check: var IntSet): Rope =
         let name = getTypeForward(m, et, hashType et)
         result = name & star
         m.typeCache[sig] = result
-        pushType(m, et)
     of tySequence:
       # no restriction! We have a forward declaration for structs
       let name = getTypeForward(m, et, hashType et)
@@ -841,6 +842,13 @@ proc getTypeDescAux(m: BModule, origTyp: PType, check: var IntSet): Rope =
       # always call for sideeffects:
       assert t.kind != tyTuple
       discard getRecordDesc(m, t, result, check)
+      # The resulting type will include commas and these won't play well
+      # with the C macros for defining procs such as N_NIMCALL. We must
+      # create a typedef for the type and use it in the proc signature:
+      let typedefName = ~"TY" & $sig
+      addf(m.s[cfsTypes], "typedef $1 $2;$n", [result, typedefName])
+      m.typeCache[sig] = typedefName
+      result = typedefName
     else:
       when false:
         if t.sym != nil and t.sym.name.s == "KeyValuePair":
diff --git a/compiler/cgen.nim b/compiler/cgen.nim
index 8b3da223f..01610010b 100644
--- a/compiler/cgen.nim
+++ b/compiler/cgen.nim
@@ -317,8 +317,10 @@ proc resetLoc(p: BProc, loc: var TLoc) =
       genObjectInit(p, cpsStmts, loc.t, loc, true)
     else:
       useStringh(p.module)
+      # array passed as argument decayed into pointer, bug #7332
+      # so we use getTypeDesc here rather than rdLoc(loc)
       linefmt(p, cpsStmts, "memset((void*)$1, 0, sizeof($2));$n",
-              addrLoc(loc), rdLoc(loc))
+              addrLoc(loc), getTypeDesc(p.module, loc.t))
       # XXX: We can be extra clever here and call memset only
       # on the bytes following the m_type field?
       genObjectInit(p, cpsStmts, loc.t, loc, true)
@@ -335,7 +337,7 @@ proc constructLoc(p: BProc, loc: TLoc, isTemp = false) =
       if not isImportedCppType(typ):
         useStringh(p.module)
         linefmt(p, cpsStmts, "memset((void*)$1, 0, sizeof($2));$n",
-                addrLoc(loc), rdLoc(loc))
+                addrLoc(loc), getTypeDesc(p.module, typ))
     genObjectInit(p, cpsStmts, loc.t, loc, true)
 
 proc initLocalVar(p: BProc, v: PSym, immediateAsgn: bool) =
diff --git a/compiler/cgendata.nim b/compiler/cgendata.nim
index 0f8fa760e..efa346934 100644
--- a/compiler/cgendata.nim
+++ b/compiler/cgendata.nim
@@ -70,11 +70,10 @@ type
     threadVarAccessed*: bool  # true if the proc already accessed some threadvar
     lastLineInfo*: TLineInfo  # to avoid generating excessive 'nimln' statements
     currLineInfo*: TLineInfo  # AST codegen will make this superfluous
-    nestedTryStmts*: seq[PNode]   # in how many nested try statements we are
-                                  # (the vars must be volatile then)
-    inExceptBlock*: int       # are we currently inside an except block?
-                              # leaving such scopes by raise or by return must
-                              # execute any applicable finally blocks
+    nestedTryStmts*: seq[tuple[n: PNode, inExcept: bool]]  
+                              # in how many nested try statements we are
+                              # (the vars must be volatile then)
+                              # bool is true when are in the except part of a try block
     finallySafePoints*: seq[Rope]  # For correctly cleaning up exceptions when
                                    # using return in finally statements
     labels*: Natural          # for generating unique labels in the C proc
diff --git a/compiler/commands.nim b/compiler/commands.nim
index 766b78798..2e9b6f8db 100644
--- a/compiler/commands.nim
+++ b/compiler/commands.nim
@@ -257,6 +257,7 @@ proc testCompileOption*(switch: string, info: TLineInfo): bool =
   of "rangechecks": result = contains(gOptions, optRangeCheck)
   of "boundchecks": result = contains(gOptions, optBoundsCheck)
   of "overflowchecks": result = contains(gOptions, optOverflowCheck)
+  of "movechecks": result = contains(gOptions, optMoveCheck)
   of "linedir": result = contains(gOptions, optLineDir)
   of "assertions", "a": result = contains(gOptions, optAssert)
   of "deadcodeelim": result = contains(gGlobalOptions, optDeadCodeElim)
@@ -493,6 +494,7 @@ proc processSwitch(switch, arg: string, pass: TCmdLinePass, info: TLineInfo;
   of "rangechecks": processOnOffSwitch({optRangeCheck}, arg, pass, info)
   of "boundchecks": processOnOffSwitch({optBoundsCheck}, arg, pass, info)
   of "overflowchecks": processOnOffSwitch({optOverflowCheck}, arg, pass, info)
+  of "movechecks": processOnOffSwitch({optMoveCheck}, arg, pass, info)
   of "linedir": processOnOffSwitch({optLineDir}, arg, pass, info)
   of "assertions", "a": processOnOffSwitch({optAssert}, arg, pass, info)
   of "deadcodeelim": processOnOffSwitchG({optDeadCodeElim}, arg, pass, info)
diff --git a/compiler/destroyer.nim b/compiler/destroyer.nim
index 55da69985..ffa3e37e5 100644
--- a/compiler/destroyer.nim
+++ b/compiler/destroyer.nim
@@ -89,11 +89,34 @@
 ##       tmp.bar))
 ## destroy(tmp.bar)
 ## destroy(tmp.x); destroy(tmp.y)
+##
+
+##[
+From https://github.com/nim-lang/Nim/wiki/Destructors
+
+Rule      Pattern                 Transformed into
+----      -------                 ----------------
+1.1	      var x: T; stmts	        var x: T; try stmts
+                                  finally: `=destroy`(x)
+1.2       var x: sink T; stmts    var x: sink T; stmts; ensureEmpty(x)
+2         x = f()                 `=sink`(x, f())
+3         x = lastReadOf z        `=sink`(x, z)
+4.1       y = sinkParam           `=sink`(y, sinkParam)
+4.2       x = y                   `=`(x, y) # a copy
+5.1       f_sink(g())             f_sink(g())
+5.2       f_sink(y)               f_sink(copy y); # copy unless we can see it's the last read
+5.3       f_sink(move y)          f_sink(y); reset(y) # explicit moves empties 'y'
+5.4       f_noSink(g())           var tmp = bitwiseCopy(g()); f(tmp); `=destroy`(tmp)
 
+Remarks: Rule 1.2 is not yet implemented because ``sink`` is currently
+  not allowed as a local variable.
+
+``move`` builtin needs to be implemented.
+]##
 
 import
   intsets, ast, astalgo, msgs, renderer, magicsys, types, idents, trees,
-  strutils, options, dfa, lowerings, rodread
+  strutils, options, dfa, lowerings, rodread, tables
 
 const
   InterestingSyms = {skVar, skResult, skLet}
@@ -106,6 +129,14 @@ type
     tmpObj: PType
     tmp: PSym
     destroys, topLevelVars: PNode
+    toDropBit: Table[int, PSym]
+
+proc getTemp(c: var Con; typ: PType; info: TLineInfo): PNode =
+  # XXX why are temps fields in an object here?
+  let f = newSym(skField, getIdent(":d" & $c.tmpObj.n.len), c.owner, info)
+  f.typ = typ
+  rawAddField c.tmpObj, f
+  result = rawDirectAccess(c.tmp, f)
 
 proc isHarmlessVar*(s: PSym; c: Con): bool =
   # 's' is harmless if it used only once and its
@@ -212,14 +243,44 @@ proc genDestroy(t: PType; dest: PNode): PNode =
 proc addTopVar(c: var Con; v: PNode) =
   c.topLevelVars.add newTree(nkIdentDefs, v, emptyNode, emptyNode)
 
+proc dropBit(c: var Con; s: PSym): PSym =
+  result = c.toDropBit.getOrDefault(s.id)
+  assert result != nil
+
+proc registerDropBit(c: var Con; s: PSym) =
+  let result = newSym(skTemp, getIdent(s.name.s & "_AliveBit"), c.owner, s.info)
+  result.typ = getSysType(tyBool)
+  let trueVal = newIntTypeNode(nkIntLit, 1, result.typ)
+  c.topLevelVars.add newTree(nkIdentDefs, newSymNode result, emptyNode, trueVal)
+  c.toDropBit[s.id] = result
+  # generate:
+  #  if not sinkParam_AliveBit: `=destroy`(sinkParam)
+  c.destroys.add newTree(nkIfStmt,
+    newTree(nkElifBranch, newSymNode result, genDestroy(s.typ, newSymNode s)))
+
 proc p(n: PNode; c: var Con): PNode
 
 template recurse(n, dest) =
   for i in 0..<n.len:
     dest.add p(n[i], c)
 
+proc isSinkParam(s: PSym): bool {.inline.} =
+  result = s.kind == skParam and s.typ.kind == tySink
+
+const constrExprs = nkCallKinds+{nkObjConstr}
+
+proc destructiveMoveSink(n: PNode; c: var Con): PNode =
+  # generate:  (chckMove(sinkParam_AliveBit); sinkParam_AliveBit = false; sinkParam)
+  result = newNodeIT(nkStmtListExpr, n.info, n.typ)
+  let bit = newSymNode dropBit(c, n.sym)
+  if optMoveCheck in c.owner.options:
+    result.add callCodegenProc("chckMove", bit)
+  result.add newTree(nkAsgn, bit,
+    newIntTypeNode(nkIntLit, 0, getSysType(tyBool)))
+  result.add n
+
 proc moveOrCopy(dest, ri: PNode; c: var Con): PNode =
-  if ri.kind in nkCallKinds+{nkObjConstr}:
+  if ri.kind in constrExprs:
     result = genSink(ri.typ, dest)
     # watch out and no not transform 'ri' twice if it's a call:
     let ri2 = copyNode(ri)
@@ -228,10 +289,51 @@ proc moveOrCopy(dest, ri: PNode; c: var Con): PNode =
   elif ri.kind == nkSym and isHarmlessVar(ri.sym, c):
     result = genSink(ri.typ, dest)
     result.add p(ri, c)
+  elif ri.kind == nkSym and isSinkParam(ri.sym):
+    result = genSink(ri.typ, dest)
+    result.add destructiveMoveSink(ri, c)
   else:
     result = genCopy(ri.typ, dest)
     result.add p(ri, c)
 
+proc passCopyToSink(n: PNode; c: var Con): PNode =
+  result = newNodeIT(nkStmtListExpr, n.info, n.typ)
+  let tmp = getTemp(c, n.typ, n.info)
+  if hasDestructor(n.typ):
+    var m = genCopy(n.typ, tmp)
+    m.add p(n, c)
+    result.add m
+    message(n.info, hintPerformance,
+      "passing '$1' to a sink parameter introduces an implicit copy; " &
+      "use 'move($1)' to prevent it" % $n)
+  else:
+    result.add newTree(nkAsgn, tmp, p(n, c))
+  result.add tmp
+
+proc genReset(n: PNode; c: var Con): PNode =
+  result = newNodeI(nkCall, n.info)
+  result.add(newSymNode(createMagic("reset", mReset)))
+  # The mReset builtin does not take the address:
+  result.add n
+
+proc destructiveMoveVar(n: PNode; c: var Con): PNode =
+  # generate: (let tmp = v; reset(v); tmp)
+  result = newNodeIT(nkStmtListExpr, n.info, n.typ)
+
+  var temp = newSym(skLet, getIdent("blitTmp"), c.owner, n.info)
+  var v = newNodeI(nkLetSection, n.info)
+  let tempAsNode = newSymNode(temp)
+
+  var vpart = newNodeI(nkIdentDefs, tempAsNode.info, 3)
+  vpart.sons[0] = tempAsNode
+  vpart.sons[1] = ast.emptyNode
+  vpart.sons[2] = n
+  add(v, vpart)
+
+  result.add v
+  result.add genReset(n, c)
+  result.add tempAsNode
+
 proc p(n: PNode; c: var Con): PNode =
   case n.kind
   of nkVarSection, nkLetSection:
@@ -266,22 +368,45 @@ proc p(n: PNode; c: var Con): PNode =
         varSection.add itCopy
         result.add varSection
   of nkCallKinds:
+    let parameters = n[0].typ
+    let L = if parameters != nil: parameters.len else: 0
+    for i in 1 ..< n.len:
+      let arg = n[i]
+      if i < L and parameters[i].kind == tySink:
+        if arg.kind in nkCallKinds:
+          # recurse but skip the call expression in order to prevent
+          # destructor injections: Rule 5.1 is different from rule 5.4!
+          let a = copyNode(arg)
+          recurse(arg, a)
+          n.sons[i] = a
+        elif arg.kind in {nkObjConstr, nkCharLit..nkFloat128Lit}:
+          discard "object construction to sink parameter: nothing to do"
+        elif arg.kind == nkSym and isHarmlessVar(arg.sym, c):
+          # if x is a variable and it its last read we eliminate its
+          # destructor invokation, but don't. We need to reset its memory
+          # to disable its destructor which we have not elided:
+          n.sons[i] = destructiveMoveVar(arg, c)
+        elif arg.kind == nkSym and isSinkParam(arg.sym):
+          # mark the sink parameter as used:
+          n.sons[i] = destructiveMoveSink(arg, c)
+        else:
+          # an object that is not temporary but passed to a 'sink' parameter
+          # results in a copy.
+          n.sons[i] = passCopyToSink(arg, c)
+      else:
+        n.sons[i] = p(arg, c)
+
     if n.typ != nil and hasDestructor(n.typ):
       discard "produce temp creation"
       result = newNodeIT(nkStmtListExpr, n.info, n.typ)
-      let f = newSym(skField, getIdent(":d" & $c.tmpObj.n.len), c.owner, n.info)
-      f.typ = n.typ
-      rawAddField c.tmpObj, f
-      var m = genSink(n.typ, rawDirectAccess(c.tmp, f))
-      var call = copyNode(n)
-      recurse(n, call)
-      m.add call
-      result.add m
-      result.add rawDirectAccess(c.tmp, f)
-      c.destroys.add genDestroy(n.typ, rawDirectAccess(c.tmp, f))
+      let tmp = getTemp(c, n.typ, n.info)
+      var sinkExpr = genSink(n.typ, tmp)
+      sinkExpr.add n
+      result.add sinkExpr
+      result.add tmp
+      c.destroys.add genDestroy(n.typ, tmp)
     else:
-      result = copyNode(n)
-      recurse(n, result)
+      result = n
   of nkAsgn, nkFastAsgn:
     if hasDestructor(n[0].typ):
       result = moveOrCopy(n[0], n[1], c)
@@ -311,6 +436,11 @@ proc injectDestructorCalls*(owner: PSym; n: PNode): PNode =
   for i in 0..<c.g.len:
     if c.g[i].kind in {goto, fork}:
       c.jumpTargets.incl(i+c.g[i].dest)
+  if owner.kind in {skProc, skFunc, skMethod, skIterator, skConverter}:
+    let params = owner.typ.n
+    for i in 1 ..< params.len:
+      let param = params[i].sym
+      if param.typ.kind == tySink: registerDropBit(c, param)
   let body = p(n, c)
   if c.tmp.typ.n.len > 0:
     c.addTopVar(newSymNode c.tmp)
diff --git a/compiler/lambdalifting.nim b/compiler/lambdalifting.nim
index fca5ef52e..bc05ec80c 100644
--- a/compiler/lambdalifting.nim
+++ b/compiler/lambdalifting.nim
@@ -275,8 +275,12 @@ proc freshVarForClosureIter*(s, owner: PSym): PNode =
 
 proc markAsClosure(owner: PSym; n: PNode) =
   let s = n.sym
-  if illegalCapture(s) or owner.typ.callConv notin {ccClosure, ccDefault}:
-    localError(n.info, errIllegalCaptureX, s.name.s)
+  if illegalCapture(s):
+    localError(n.info, "illegal capture '$1' of type <$2> which is declared here: $3" %
+      [s.name.s, typeToString(s.typ), $s.info])
+  elif owner.typ.callConv notin {ccClosure, ccDefault}:
+    localError(n.info, "illegal capture '$1' because '$2' has the calling convention: <$3>" %
+      [s.name.s, owner.name.s, CallingConvToStr[owner.typ.callConv]])
   incl(owner.typ.flags, tfCapturesEnv)
   owner.typ.callConv = ccClosure
 
diff --git a/compiler/lookups.nim b/compiler/lookups.nim
index c409acc59..0675c5ca0 100644
--- a/compiler/lookups.nim
+++ b/compiler/lookups.nim
@@ -44,6 +44,7 @@ proc considerQuotedIdent*(n: PNode, origin: PNode = nil): PIdent =
         case x.kind
         of nkIdent: id.add(x.ident.s)
         of nkSym: id.add(x.sym.name.s)
+        of nkLiterals - nkFloatLiterals: id.add(x.renderTree)
         else: handleError(n, origin)
       result = getIdent(id)
   of nkOpenSymChoice, nkClosedSymChoice:
@@ -456,4 +457,4 @@ proc pickSym*(c: PContext, n: PNode; kinds: set[TSymKind];
     a = nextOverloadIter(o, c, n)
 
 proc isInfixAs*(n: PNode): bool =
-  return n.kind == nkInfix and considerQuotedIdent(n[0]).s == "as"
\ No newline at end of file
+  return n.kind == nkInfix and considerQuotedIdent(n[0]).s == "as"
diff --git a/compiler/msgs.nim b/compiler/msgs.nim
index ac4242e67..70504cfc9 100644
--- a/compiler/msgs.nim
+++ b/compiler/msgs.nim
@@ -134,7 +134,7 @@ type
     hintProcessing, hintCodeBegin, hintCodeEnd, hintConf, hintPath,
     hintConditionAlwaysTrue, hintName, hintPattern,
     hintExecuting, hintLinking, hintDependency,
-    hintSource, hintStackTrace, hintGCStats,
+    hintSource, hintPerformance, hintStackTrace, hintGCStats,
     hintUser, hintUserRaw
 
 const
@@ -357,7 +357,9 @@ const
     errXExpectsTwoArguments: "\'$1\' expects two arguments",
     errXExpectsObjectTypes: "\'$1\' expects object types",
     errXcanNeverBeOfThisSubtype: "\'$1\' can never be of this subtype",
-    errTooManyIterations: "interpretation requires too many iterations",
+    errTooManyIterations: "interpretation requires too many iterations; " &
+      "if you are sure this is not a bug in your code edit " &
+      "compiler/vmdef.MaxLoopIterations and rebuild the compiler",
     errCannotInterpretNodeX: "cannot evaluate \'$1\'",
     errFieldXNotFound: "field \'$1\' cannot be found",
     errInvalidConversionFromTypeX: "invalid conversion from type \'$1\'",
@@ -436,6 +438,7 @@ const
     hintLinking: "",
     hintDependency: "$1",
     hintSource: "$1",
+    hintPerformance: "$1",
     hintStackTrace: "$1",
     hintGCStats: "$1",
     hintUser: "$1",
@@ -458,7 +461,7 @@ const
     "XDeclaredButNotUsed", "ConvToBaseNotNeeded", "ConvFromXtoItselfNotNeeded",
     "ExprAlwaysX", "QuitCalled", "Processing", "CodeBegin", "CodeEnd", "Conf",
     "Path", "CondTrue", "Name", "Pattern", "Exec", "Link", "Dependency",
-    "Source", "StackTrace", "GCStats",
+    "Source", "Performance", "StackTrace", "GCStats",
     "User", "UserRaw"]
 
 const
diff --git a/compiler/options.nim b/compiler/options.nim
index 65f5a6245..be13e15d7 100644
--- a/compiler/options.nim
+++ b/compiler/options.nim
@@ -25,7 +25,7 @@ type                          # please make sure we have under 32 options
   TOption* = enum             # **keep binary compatible**
     optNone, optObjCheck, optFieldCheck, optRangeCheck, optBoundsCheck,
     optOverflowCheck, optNilCheck,
-    optNaNCheck, optInfCheck,
+    optNaNCheck, optInfCheck, optMoveCheck,
     optAssert, optLineDir, optWarns, optHints,
     optOptimizeSpeed, optOptimizeSize, optStackTrace, # stack tracing support
     optLineTrace,             # line tracing support (includes stack tracing)
@@ -119,13 +119,14 @@ var
 
 const
   ChecksOptions* = {optObjCheck, optFieldCheck, optRangeCheck, optNilCheck,
-    optOverflowCheck, optBoundsCheck, optAssert, optNaNCheck, optInfCheck}
+    optOverflowCheck, optBoundsCheck, optAssert, optNaNCheck, optInfCheck,
+    optMoveCheck}
 
 var
   gOptions*: TOptions = {optObjCheck, optFieldCheck, optRangeCheck,
                          optBoundsCheck, optOverflowCheck, optAssert, optWarns,
                          optHints, optStackTrace, optLineTrace,
-                         optPatterns, optNilCheck}
+                         optPatterns, optNilCheck, optMoveCheck}
   gGlobalOptions*: TGlobalOptions = {optThreadAnalysis}
   gExitcode*: int8
   gCmd*: TCommands = cmdNone  # the command
diff --git a/compiler/parampatterns.nim b/compiler/parampatterns.nim
index aacd25795..8540f1b32 100644
--- a/compiler/parampatterns.nim
+++ b/compiler/parampatterns.nim
@@ -178,6 +178,36 @@ type
     arDiscriminant,           # is a discriminant
     arStrange                 # it is a strange beast like 'typedesc[var T]'
 
+proc exprRoot*(n: PNode): PSym =
+  var it = n
+  while true:
+    case it.kind
+    of nkSym: return it.sym
+    of nkHiddenDeref, nkDerefExpr:
+      if it[0].typ.skipTypes(abstractInst).kind in {tyPtr, tyRef}:
+        # 'ptr' is unsafe anyway and 'ref' is always on the heap,
+        # so allow these derefs:
+        break
+      else:
+        it = it[0]
+    of nkDotExpr, nkBracketExpr, nkHiddenAddr,
+       nkObjUpConv, nkObjDownConv, nkCheckedFieldExpr:
+      it = it[0]
+    of nkHiddenStdConv, nkHiddenSubConv, nkConv:
+      it = it[1]
+    of nkStmtList, nkStmtListExpr:
+      if it.len > 0 and it.typ != nil: it = it.lastSon
+      else: break
+    of nkCallKinds:
+      if it.typ != nil and it.typ.kind == tyVar and it.len > 1:
+        # See RFC #7373, calls returning 'var T' are assumed to
+        # return a view into the first argument (if there is one):
+        it = it[1]
+      else:
+        break
+    else:
+      break
+
 proc isAssignable*(owner: PSym, n: PNode; isUnsafeAddr=false): TAssignableResult =
   ## 'owner' can be nil!
   result = arNone
@@ -189,7 +219,7 @@ proc isAssignable*(owner: PSym, n: PNode; isUnsafeAddr=false): TAssignableResult
     let kinds = if isUnsafeAddr: {skVar, skResult, skTemp, skParam, skLet}
                 else: {skVar, skResult, skTemp}
     if n.sym.kind in kinds:
-      if owner != nil and owner.id == n.sym.owner.id and
+      if owner != nil and owner == n.sym.owner and
           sfGlobal notin n.sym.flags:
         result = arLocalLValue
       else:
diff --git a/compiler/parser.nim b/compiler/parser.nim
index 1ae7646cd..debb0b34d 100644
--- a/compiler/parser.nim
+++ b/compiler/parser.nim
@@ -820,7 +820,6 @@ proc parseIfExpr(p: var TParser, kind: TNodeKind): PNode =
     if realInd(p):
       p.currInd = p.tok.indent
       wasIndented = true
-      echo result.info, " yes ", p.currInd
     addSon(branch, parseExpr(p))
     result.add branch
     while sameInd(p) or not wasIndented:
@@ -964,6 +963,8 @@ proc parseTuple(p: var TParser, indentAllowed = false): PNode =
             parMessage(p, errIdentifierExpected, p.tok)
             break
           if not sameInd(p): break
+  elif p.tok.tokType == tkParLe:
+    parMessage(p, errGenerated, "the syntax for tuple types is 'tuple[...]', not 'tuple(...)'")
   else:
     result = newNodeP(nkTupleClassTy, p)
 
@@ -985,6 +986,9 @@ proc parseParamList(p: var TParser, retColon = true): PNode =
         a = parseIdentColonEquals(p, {withBothOptional, withPragma})
       of tkParRi:
         break
+      of tkVar:
+        parMessage(p, errGenerated, "the syntax is 'parameter: var T', not 'var parameter: T'")
+        break
       else:
         parMessage(p, errTokenExpected, ")")
         break
@@ -2132,7 +2136,12 @@ proc parseTopLevelStmt(p: var TParser): PNode =
     if p.tok.indent != 0:
       if p.firstTok and p.tok.indent < 0: discard
       elif p.tok.tokType != tkSemiColon:
-        parMessage(p, errInvalidIndentation)
+        # special casing for better error messages:
+        if p.tok.tokType == tkOpr and p.tok.ident.s == "*":
+          parMessage(p, errGenerated,
+            "invalid indentation; an export marker '*' follows the declared identifier")
+        else:
+          parMessage(p, errInvalidIndentation)
     p.firstTok = false
     case p.tok.tokType
     of tkSemiColon:
diff --git a/compiler/pragmas.nim b/compiler/pragmas.nim
index 1b8078628..1295ee18d 100644
--- a/compiler/pragmas.nim
+++ b/compiler/pragmas.nim
@@ -40,7 +40,8 @@ const
     wTags, wLocks, wGcSafe, wExportNims, wUsed}
   exprPragmas* = {wLine, wLocks, wNoRewrite, wGcSafe}
   stmtPragmas* = {wChecks, wObjChecks, wFieldChecks, wRangechecks,
-    wBoundchecks, wOverflowchecks, wNilchecks, wAssertions, wWarnings, wHints,
+    wBoundchecks, wOverflowchecks, wNilchecks, wMovechecks, wAssertions,
+    wWarnings, wHints,
     wLinedir, wStacktrace, wLinetrace, wOptimization, wHint, wWarning, wError,
     wFatal, wDefine, wUndef, wCompile, wLink, wLinksys, wPure, wPush, wPop,
     wBreakpoint, wWatchPoint, wPassl, wPassc, wDeadCodeElim, wDeprecated,
@@ -323,6 +324,7 @@ proc processOption(c: PContext, n: PNode): bool =
     of wFloatchecks: onOff(c, n, {optNaNCheck, optInfCheck})
     of wNanChecks: onOff(c, n, {optNaNCheck})
     of wInfChecks: onOff(c, n, {optInfCheck})
+    of wMovechecks: onOff(c, n, {optMoveCheck})
     of wAssertions: onOff(c, n, {optAssert})
     of wWarnings: onOff(c, n, {optWarns})
     of wHints: onOff(c, n, {optHints})
@@ -693,7 +695,7 @@ proc singlePragma(c: PContext, sym: PSym, n: PNode, i: var int,
     inc c.instCounter
     if c.instCounter > 100:
       globalError(it.info, errRecursiveDependencyX, userPragma.name.s)
-    
+
     pragma(c, sym, userPragma.ast, validPragmas)
     n.sons[i..i] = userPragma.ast.sons # expand user pragma with its content
     i.inc(userPragma.ast.len - 1) # inc by -1 is ok, user pragmas was empty
@@ -906,7 +908,7 @@ proc singlePragma(c: PContext, sym: PSym, n: PNode, i: var int,
       of wCodegenDecl: processCodegenDecl(c, it, sym)
       of wChecks, wObjChecks, wFieldChecks, wRangechecks, wBoundchecks,
          wOverflowchecks, wNilchecks, wAssertions, wWarnings, wHints,
-         wLinedir, wStacktrace, wLinetrace, wOptimization,
+         wLinedir, wStacktrace, wLinetrace, wOptimization, wMovechecks,
          wCallconv,
          wDebugger, wProfiler, wFloatchecks, wNanChecks, wInfChecks,
          wPatterns:
diff --git a/compiler/semcall.nim b/compiler/semcall.nim
index ba38ed215..0fc12f164 100644
--- a/compiler/semcall.nim
+++ b/compiler/semcall.nim
@@ -190,12 +190,12 @@ proc presentFailedCandidates(c: PContext, n: PNode, errors: CandidateErrors):
       if wanted != nil and got != nil:
         effectProblem(wanted, got, candidates)
       if cond: candidates.add "\n"
-    elif err.unmatchedVarParam != 0 and err.unmatchedVarParam < n.len:
-      add(candidates, "for a 'var' type a variable needs to be passed, but '" &
+    if err.unmatchedVarParam != 0 and err.unmatchedVarParam < n.len:
+      candidates.add("  for a 'var' type a variable needs to be passed, but '" &
                       renderNotLValue(n[err.unmatchedVarParam]) &
                       "' is immutable\n")
     for diag in err.diagnostics:
-      add(candidates, diag & "\n")
+      candidates.add(diag & "\n")
 
   result = (prefer, candidates)
 
diff --git a/compiler/semexprs.nim b/compiler/semexprs.nim
index 8e3aeffbe..a523bfc9e 100644
--- a/compiler/semexprs.nim
+++ b/compiler/semexprs.nim
@@ -192,6 +192,10 @@ proc semConv(c: PContext, n: PNode): PNode =
 
   result.addSon copyTree(n.sons[0])
 
+  # special case to make MyObject(x = 3) produce a nicer error message:
+  if n[1].kind == nkExprEqExpr and
+      targetType.skipTypes(abstractPtrs).kind == tyObject:
+    localError(n.info, "object contruction uses ':', not '='")
   var op = semExprWithType(c, n.sons[1])
   if targetType.isMetaType:
     let final = inferWithMetatype(c, targetType, op, true)
@@ -880,6 +884,9 @@ const
 
 proc readTypeParameter(c: PContext, typ: PType,
                        paramName: PIdent, info: TLineInfo): PNode =
+  # Note: This function will return emptyNode when attempting to read
+  # a static type parameter that is not yet resolved (e.g. this may
+  # happen in proc signatures such as `proc(x: T): array[T.sizeParam, U]`
   if typ.kind in {tyUserTypeClass, tyUserTypeClassInst}:
     for statement in typ.n:
       case statement.kind
@@ -910,7 +917,10 @@ proc readTypeParameter(c: PContext, typ: PType,
       if tParam.sym.name.id == paramName.id:
         let rawTyp = ty.sons[s + 1]
         if rawTyp.kind == tyStatic:
-          return rawTyp.n
+          if rawTyp.n != nil:
+            return rawTyp.n
+          else:
+            return emptyNode
         else:
           let foundTyp = makeTypeDesc(c, rawTyp)
           return newSymNode(copySym(tParam.sym).linkTo(foundTyp), info)
@@ -1075,21 +1085,43 @@ proc builtinFieldAccess(c: PContext, n: PNode, flags: TExprFlags): PNode =
   template tryReadingGenericParam(t: PType) =
     case t.kind
     of tyTypeParamsHolders:
-      return readTypeParameter(c, t, i, n.info)
+      result = readTypeParameter(c, t, i, n.info)
+      if result == emptyNode:
+        result = n
+        n.typ = makeTypeFromExpr(c, n.copyTree)
+      return
     of tyUserTypeClasses:
       if t.isResolvedUserTypeClass:
         return readTypeParameter(c, t, i, n.info)
       else:
         n.typ = makeTypeFromExpr(c, copyTree(n))
         return n
-    of tyGenericParam:
+    of tyGenericParam, tyAnything:
       n.typ = makeTypeFromExpr(c, copyTree(n))
       return n
     else:
       discard
 
-  if isTypeExpr(n.sons[0]) or (ty.kind == tyTypeDesc and ty.base.kind != tyNone):
-    if ty.kind == tyTypeDesc: ty = ty.base
+  var argIsType = false
+
+  if ty.kind == tyTypeDesc:
+    if ty.base.kind == tyNone:
+      # This is a still unresolved typedesc parameter.
+      # If this is a regular proc, then all bets are off and we must return
+      # tyFromExpr, but when this happen in a macro this is not a built-in
+      # field access and we leave the compiler to compile a normal call:
+      if getCurrOwner(c).kind != skMacro:
+        n.typ = makeTypeFromExpr(c, n.copyTree)
+        return n
+      else:
+        return nil
+    else:
+      ty = ty.base
+      argIsType = true
+  else:
+    argIsType = isTypeExpr(n.sons[0])
+
+  if argIsType:
     ty = ty.skipTypes(tyDotOpTransparent)
     case ty.kind
     of tyEnum:
@@ -1297,13 +1329,23 @@ proc propertyWriteAccess(c: PContext, n, nOrig, a: PNode): PNode =
     #analyseIfAddressTakenInCall(c, result)
 
 proc takeImplicitAddr(c: PContext, n: PNode; isLent: bool): PNode =
+  # See RFC #7373, calls returning 'var T' are assumed to
+  # return a view into the first argument (if there is one):
+  let root = exprRoot(n)
+  if root != nil and root.owner == c.p.owner:
+    if root.kind in {skLet, skVar, skTemp} and sfGlobal notin root.flags:
+      localError(n.info, "'$1' escapes its stack frame; context: '$2'" % [
+        root.name.s, renderTree(n, {renderNoComments})])
+    elif root.kind == skParam and root.position != 0:
+      localError(n.info, "'$1' is not the first parameter; context: '$2'" % [
+        root.name.s, renderTree(n, {renderNoComments})])
   case n.kind
   of nkHiddenAddr, nkAddr: return n
   of nkHiddenDeref, nkDerefExpr: return n.sons[0]
   of nkBracketExpr:
     if len(n) == 1: return n.sons[0]
   else: discard
-  var valid = isAssignable(c, n)
+  let valid = isAssignable(c, n)
   if valid != arLValue:
     if valid == arLocalLValue:
       localError(n.info, errXStackEscape, renderTree(n, {renderNoComments}))
@@ -2172,7 +2214,7 @@ proc semExpr(c: PContext, n: PNode, flags: TExprFlags = {}): PNode =
     # because of the changed symbol binding, this does not mean that we
     # don't have to check the symbol for semantics here again!
     result = semSym(c, n, n.sym, flags)
-  of nkEmpty, nkNone, nkCommentStmt:
+  of nkEmpty, nkNone, nkCommentStmt, nkType:
     discard
   of nkNilLit:
     if result.typ == nil: result.typ = getSysType(tyNil)
diff --git a/compiler/seminst.nim b/compiler/seminst.nim
index acea9330b..32b385308 100644
--- a/compiler/seminst.nim
+++ b/compiler/seminst.nim
@@ -174,6 +174,8 @@ proc sideEffectsCheck(c: PContext, s: PSym) =
 
 proc instGenericContainer(c: PContext, info: TLineInfo, header: PType,
                           allowMetaTypes = false): PType =
+  internalAssert header.kind == tyGenericInvocation
+
   var
     typeMap: LayeredIdTable
     cl: TReplTypeVars
@@ -185,7 +187,35 @@ proc instGenericContainer(c: PContext, info: TLineInfo, header: PType,
   cl.info = info
   cl.c = c
   cl.allowMetaTypes = allowMetaTypes
+
+  # We must add all generic params in scope, because the generic body
+  # may include tyFromExpr nodes depending on these generic params.
+  # XXX: This looks quite similar to the code in matchUserTypeClass,
+  # perhaps the code can be extracted in a shared function.
+  openScope(c)
+  let genericTyp = header.base
+  for i in 0 .. (genericTyp.len - 2):
+    let genParam = genericTyp[i]
+    var param: PSym
+
+    template paramSym(kind): untyped =
+        newSym(kind, genParam.sym.name, genericTyp.sym, genParam.sym.info)
+
+    if genParam.kind == tyStatic:
+      param = paramSym skConst
+      param.ast = header[i+1].n
+      param.typ = header[i+1]
+    else:
+      param = paramSym skType
+      param.typ = makeTypeDesc(c, header[i+1])
+
+    # this scope was not created by the user,
+    # unused params shoudn't be reported.
+    param.flags.incl sfUsed
+    addDecl(c, param)
+
   result = replaceTypeVarsT(cl, header)
+  closeScope(c)
 
 proc instantiateProcType(c: PContext, pt: TIdTable,
                          prc: PSym, info: TLineInfo) =
@@ -316,7 +346,9 @@ proc generateInstance(c: PContext, fn: PSym, pt: TIdTable,
     if c.inGenericContext == 0:
       instantiateBody(c, n, fn.typ.n, result, fn)
     sideEffectsCheck(c, result)
-    paramsTypeCheck(c, result.typ)
+    if result.magic != mSlice:
+      # 'toOpenArray' is special and it is allowed to return 'openArray':
+      paramsTypeCheck(c, result.typ)
   else:
     result = oldPrc
   popProcCon(c)
diff --git a/compiler/semobjconstr.nim b/compiler/semobjconstr.nim
index 63a4eb99a..e2296a0d2 100644
--- a/compiler/semobjconstr.nim
+++ b/compiler/semobjconstr.nim
@@ -76,7 +76,7 @@ proc semConstrField(c: PContext, flags: TExprFlags,
     return initValue
 
 proc caseBranchMatchesExpr(branch, matched: PNode): bool =
-  for i in 0 .. (branch.len - 2):
+  for i in 0 .. branch.len-2:
     if exprStructuralEquivalent(branch[i], matched):
       return true
 
diff --git a/compiler/semtypes.nim b/compiler/semtypes.nim
index d097a373f..b43a96a87 100644
--- a/compiler/semtypes.nim
+++ b/compiler/semtypes.nim
@@ -720,7 +720,8 @@ proc semObjectNode(c: PContext, n: PNode, prev: PType): PType =
           addInheritedFields(c, check, pos, concreteBase)
       else:
         if concreteBase.kind != tyError:
-          localError(n.sons[1].info, errInheritanceOnlyWithNonFinalObjects)
+          localError(n.sons[1].info, "inheritance only works with non-final objects; " &
+             "to enable inheritance write '" & typeToString(realBase) & " of RootObj'")
         base = nil
         realBase = nil
   if n.kind != nkObjectTy: internalError(n.info, "semObjectNode")
@@ -1396,7 +1397,10 @@ proc semTypeNode(c: PContext, n: PNode, prev: PType): PType =
         fixupTypeOf(c, prev, typExpr)
         result = typExpr.typ
       else:
-        result = semTypeExpr(c, n, prev)
+        if c.inGenericContext > 0 and n.kind == nkCall:
+          result = makeTypeFromExpr(c, n.copyTree)
+        else:
+          result = semTypeExpr(c, n, prev)
   of nkWhenStmt:
     var whenResult = semWhen(c, n, false)
     if whenResult.kind == nkStmtList: whenResult.kind = nkStmtListType
diff --git a/compiler/semtypinst.nim b/compiler/semtypinst.nim
index d9b368b0e..09434c925 100644
--- a/compiler/semtypinst.nim
+++ b/compiler/semtypinst.nim
@@ -460,6 +460,10 @@ proc replaceTypeVarsTAux(cl: var TReplTypeVars, t: PType): PType =
 
   of tyFromExpr:
     if cl.allowMetaTypes: return
+    # This assert is triggered when a tyFromExpr was created in a cyclic
+    # way. You should break the cycle at the point of creation by introducing
+    # a call such as: `n.typ = makeTypeFromExpr(c, n.copyTree)`
+    # Otherwise, the cycle will be fatal for the prepareNode call below
     assert t.n.typ != t
     var n = prepareNode(cl, t.n)
     if n.kind != nkEmpty:
diff --git a/compiler/sighashes.nim b/compiler/sighashes.nim
index 5d6b5978d..0fea3bbe3 100644
--- a/compiler/sighashes.nim
+++ b/compiler/sighashes.nim
@@ -155,7 +155,7 @@ proc hashType(c: var MD5Context, t: PType; flags: set[ConsiderFlag]) =
     else:
       c.hashSym(t.sym)
     return
-  of tyAlias, tyGenericInst, tyUserTypeClasses:
+  of tyAlias, tySink, tyGenericInst, tyUserTypeClasses:
     c.hashType t.lastSon, flags
     return
   else:
diff --git a/compiler/sigmatch.nim b/compiler/sigmatch.nim
index e4509ff91..96d815df7 100644
--- a/compiler/sigmatch.nim
+++ b/compiler/sigmatch.nim
@@ -1145,7 +1145,8 @@ proc typeRelImpl(c: var TCandidate, f, aOrig: PType,
         else:
           fRange = prev
       let ff = f.sons[1].skipTypes({tyTypeDesc})
-      let aa = a.sons[1].skipTypes({tyTypeDesc})
+      # This typeDesc rule is wrong, see bug #7331
+      let aa = a.sons[1] #.skipTypes({tyTypeDesc})
 
       if f.sons[0].kind != tyGenericParam and aa.kind == tyEmpty:
         result = isGeneric
@@ -1883,7 +1884,7 @@ proc paramTypesMatchAux(m: var TCandidate, f, a: PType,
       return arg
     elif f.kind == tyTypeDesc:
       return arg
-    elif f.kind == tyStatic:
+    elif f.kind == tyStatic and arg.typ.n != nil:
       return arg.typ.n
     else:
       return argSemantized # argOrig
diff --git a/compiler/types.nim b/compiler/types.nim
index 7ae02486e..ff3572517 100644
--- a/compiler/types.nim
+++ b/compiler/types.nim
@@ -1136,6 +1136,8 @@ proc typeAllowedAux(marker: var IntSet, typ: PType, kind: TSymKind,
   of tyTypeClasses:
     if tfGenericTypeParam in t.flags or taConcept in flags: #or taField notin flags:
       discard
+    elif t.isResolvedUserTypeClass:
+      result = typeAllowedAux(marker, t.lastSon, kind, flags)
     elif kind notin {skParam, skResult}:
       result = t
   of tyGenericBody, tyGenericParam, tyGenericInvocation,
diff --git a/compiler/vmdef.nim b/compiler/vmdef.nim
index 5395d4bad..dd4bc5060 100644
--- a/compiler/vmdef.nim
+++ b/compiler/vmdef.nim
@@ -16,7 +16,7 @@ const
   byteExcess* = 128 # we use excess-K for immediates
   wordExcess* = 32768
 
-  MaxLoopIterations* = 1500_000 # max iterations of all loops
+  MaxLoopIterations* = 1_000_000_000 # max iterations of all loops
 
 
 type
diff --git a/compiler/wordrecg.nim b/compiler/wordrecg.nim
index e458cad03..76d91d4e7 100644
--- a/compiler/wordrecg.nim
+++ b/compiler/wordrecg.nim
@@ -52,7 +52,7 @@ type
     wNimcall, wStdcall, wCdecl, wSafecall, wSyscall, wInline, wNoInline,
     wFastcall, wClosure, wNoconv, wOn, wOff, wChecks, wRangechecks,
     wBoundchecks, wOverflowchecks, wNilchecks,
-    wFloatchecks, wNanChecks, wInfChecks,
+    wFloatchecks, wNanChecks, wInfChecks, wMoveChecks,
     wAssertions, wPatterns, wWarnings,
     wHints, wOptimization, wRaises, wWrites, wReads, wSize, wEffects, wTags,
     wDeadCodeElim, wSafecode, wPackage, wNoForward, wReorder, wNoRewrite,
@@ -139,7 +139,7 @@ const
     "cdecl", "safecall", "syscall", "inline", "noinline", "fastcall", "closure",
     "noconv", "on", "off", "checks", "rangechecks", "boundchecks",
     "overflowchecks", "nilchecks",
-    "floatchecks", "nanchecks", "infchecks",
+    "floatchecks", "nanchecks", "infchecks", "movechecks",
 
     "assertions", "patterns", "warnings", "hints",
     "optimization", "raises", "writes", "reads", "size", "effects", "tags",
diff --git a/config/nimdoc.cfg b/config/nimdoc.cfg
index 8e47264ac..11d9987d8 100644
--- a/config/nimdoc.cfg
+++ b/config/nimdoc.cfg
@@ -229,7 +229,7 @@ body {
   line-height: 20px;
   color: #444;
   letter-spacing: 0.15px;
-  background-color: rgba(252, 248, 244, 0.45); }
+  background-color: #FDFBFA; }
 
 /* Skeleton grid */
 .container {
diff --git a/doc/lib.rst b/doc/lib.rst
index 2e963451d..b46d957a8 100644
--- a/doc/lib.rst
+++ b/doc/lib.rst
@@ -216,12 +216,6 @@ Math libraries
   Floating-point environment. Handling of floating-point rounding and
   exceptions (overflow, zero-devide, etc.).
 
-* `basic2d <basic2d.html>`_
-  Basic 2d support with vectors, points, matrices and some basic utilities.
-
-* `basic3d <basic3d.html>`_
-  Basic 3d support with vectors, points, matrices and some basic utilities.
-
 * `mersenne <mersenne.html>`_
   Mersenne twister random number generator.
 
@@ -568,29 +562,4 @@ Nimble is a package manager for the Nim programming language.
 For instructions on how to install Nimble packages see
 `its README <https://github.com/nim-lang/nimble#readme>`_.
 
-Official packages
------------------
-
-These packages are officially supported and will therefore be continually
-maintained to ensure that they work with the latest versions of the Nim
-compiler.
-
-.. raw:: html
-
-  <div id="officialPkgList"><b>If you are reading this you are missing
-  nimblepkglist.js or have javascript disabled in your browser.</b></div>
-
-Unofficial packages
--------------------
-
-These packages have been developed by independent Nim developers and as
-such may not always be up to date with the latest developments in the
-Nim programming language.
-
-.. raw:: html
-
-  <div id="unofficialPkgList"><b>If you are reading this you are missing
-  nimblepkglist.js or have javascript disabled in your browser.</b></div>
-
-  <script type="text/javascript" src="nimblepkglist.js"></script>
-  <script type="text/javascript" src="https://irclogs.nim-lang.org/packages?callback=gotPackageList" async></script>
+To see a list of Nimble's packages, check out `https://nimble.directory/ <https://nimble.directory/>`_ or the `packages repos <https://github.com/nim-lang/packages>`_ on GitHub.
diff --git a/doc/manual/lexing.txt b/doc/manual/lexing.txt
index 915e87971..0328ffd55 100644
--- a/doc/manual/lexing.txt
+++ b/doc/manual/lexing.txt
@@ -344,9 +344,11 @@ prefix), binary (prefix ``0b``), octal (prefix ``0o`` or ``0c``) and hexadecimal
 
 There exists a literal for each numerical type that is
 defined. The suffix starting with an apostrophe ('\'') is called a
-`type suffix`:idx:. Literals without a type suffix are of the type ``int``,
+`type suffix`:idx:. Literals without a type suffix are of an integer type,
 unless the literal contains a dot or ``E|e`` in which case it is of
-type ``float``. For notational convenience the apostrophe of a type suffix
+type ``float``. This integer type is ``int`` if the literal is in the range
+``low(i32)..high(i32)``, otherwise it is ``int64``.
+For notational convenience the apostrophe of a type suffix
 is optional if it is not ambiguous (only hexadecimal floating point literals
 with a type suffix can be ambiguous).
 
diff --git a/doc/manual/stmts.txt b/doc/manual/stmts.txt
index 721b5cff8..14d272cee 100644
--- a/doc/manual/stmts.txt
+++ b/doc/manual/stmts.txt
@@ -145,7 +145,7 @@ the variable has been initialized and does not rely on syntactic properties:
       x = a()
     else:
       x = a()
-    use x
+    # use x
 
 
 let statement
@@ -296,7 +296,7 @@ empty ``discard`` statement should be used.
 For non ordinal types it is not possible to list every possible value and so
 these always require an ``else`` part.
 
-As case statements perform compile-time exhaustiveness checks, the value in 
+As case statements perform compile-time exhaustiveness checks, the value in
 every ``of`` branch must be known at compile time. This fact is also exploited
 to generate more performant code.
 
diff --git a/doc/nimc.rst b/doc/nimc.rst
index e949df69c..151510df2 100644
--- a/doc/nimc.rst
+++ b/doc/nimc.rst
@@ -115,7 +115,7 @@ The ``nim`` executable processes configuration files in the following
 directories (in this order; later files overwrite previous settings):
 
 1) ``$nim/config/nim.cfg``, ``/etc/nim.cfg`` (UNIX) or ``%NIMROD%/config/nim.cfg`` (Windows). This file can be skipped with the ``--skipCfg`` command line option.
-2) ``/home/$user/.config/nim.cfg`` (UNIX) or  ``%APPDATA%/nim.cfg`` (Windows). This file can be skipped with the ``--skipUserCfg`` command line option.
+2) ``$HOME/.config/nim.cfg`` (POSIX) or  ``%APPDATA%/nim.cfg`` (Windows). This file can be skipped with the ``--skipUserCfg`` command line option.
 3) ``$parentDir/nim.cfg`` where ``$parentDir`` stands for any parent  directory of the project file's path. These files can be skipped with the ``--skipParentCfg`` command line option.
 4) ``$projectDir/nim.cfg`` where ``$projectDir`` stands for the project  file's path. This file can be skipped with the ``--skipProjCfg`` command line option.
 5) A project can also have a project specific configuration file named ``$project.nim.cfg`` that resides in the same directory as ``$project.nim``. This file can be skipped with the ``--skipProjCfg`` command line option.
diff --git a/lib/core/macros.nim b/lib/core/macros.nim
index ed9c304fe..d09f5f933 100644
--- a/lib/core/macros.nim
+++ b/lib/core/macros.nim
@@ -678,7 +678,7 @@ proc astGenRepr*(n: NimNode): string {.compileTime, benign.} =
   ## See also `repr`, `treeRepr`, and `lispRepr`.
 
   const
-    NodeKinds = {nnkEmpty, nnkNilLit, nnkIdent, nnkSym, nnkNone}
+    NodeKinds = {nnkEmpty, nnkNilLit, nnkIdent, nnkSym, nnkNone, nnkCommentStmt}
     LitKinds = {nnkCharLit..nnkInt64Lit, nnkFloatLit..nnkFloat64Lit, nnkStrLit..nnkTripleStrLit}
 
   proc escape(s: string, prefix = "\"", suffix = "\""): string {.noSideEffect.} =
@@ -723,7 +723,7 @@ proc astGenRepr*(n: NimNode): string {.compileTime, benign.} =
     of nnkCharLit: res.add("'" & $chr(n.intVal) & "'")
     of nnkIntLit..nnkInt64Lit: res.add($n.intVal)
     of nnkFloatLit..nnkFloat64Lit: res.add($n.floatVal)
-    of nnkStrLit..nnkTripleStrLit: res.add($n.strVal.escape())
+    of nnkStrLit..nnkTripleStrLit, nnkCommentStmt: res.add($n.strVal.escape())
     of nnkIdent: res.add(($n.ident).escape())
     of nnkSym: res.add(($n.symbol).escape())
     of nnkNone: assert false
diff --git a/lib/js/dom.nim b/lib/js/dom.nim
index 55692d47d..cd7609729 100644
--- a/lib/js/dom.nim
+++ b/lib/js/dom.nim
@@ -45,6 +45,7 @@ type
     location*: Location
     closed*: bool
     defaultStatus*: cstring
+    devicePixelRatio*: float
     innerHeight*, innerWidth*: int
     locationbar*: ref TLocationBar
     menubar*: ref TMenuBar
@@ -53,11 +54,14 @@ type
     pageXOffset*, pageYOffset*: int
     personalbar*: ref TPersonalBar
     scrollbars*: ref TScrollBars
+    scrollX*: float
+    scrollY*: float
     statusbar*: ref TStatusBar
     status*: cstring
     toolbar*: ref TToolBar
     frames*: seq[TFrame]
     screen*: Screen
+    performance*: Performance
 
   Frame* = ref FrameObj
   FrameObj {.importc.} = object of WindowObj
@@ -253,6 +257,8 @@ type
     minHeight*: cstring
     minWidth*: cstring
     overflow*: cstring
+    overflowX*: cstring
+    overflowY*: cstring
     padding*: cstring
     paddingBottom*: cstring
     paddingLeft*: cstring
@@ -400,6 +406,40 @@ type
     once*: bool
     passive*: bool
 
+  BoundingRect* {.importc.} = ref object
+    top*, bottom*, left*, right*, x*, y*, width*, height*: float
+
+  PerformanceMemory* {.importc.} = ref object 
+    jsHeapSizeLimit*: float
+    totalJSHeapSize*: float
+    usedJSHeapSize*: float
+
+  PerformanceTiming* {.importc.} = ref object 
+    connectStart*: float
+    domComplete*: float
+    domContentLoadedEventEnd*: float
+    domContentLoadedEventStart*: float
+    domInteractive*: float
+    domLoading*: float
+    domainLookupEnd*: float
+    domainLookupStart*: float
+    fetchStart*: float
+    loadEventEnd*: float
+    loadEventStart*: float
+    navigationStart*: float
+    redirectEnd*: float
+    redirectStart*: float
+    requestStart*: float
+    responseEnd*: float
+    responseStart*: float
+    secureConnectionStart*: float
+    unloadEventEnd*: float
+    unloadEventStart*: float
+
+  Performance* {.importc.} = ref object
+    memory*: PerformanceMemory
+    timing*: PerformanceTiming
+
 {.push importcpp.}
 
 # EventTarget "methods"
@@ -451,6 +491,7 @@ proc cloneNode*(n: Node, copyContent: bool): Node
 proc deleteData*(n: Node, start, len: int)
 proc getAttribute*(n: Node, attr: cstring): cstring
 proc getAttributeNode*(n: Node, attr: cstring): Node
+proc getBoundingClientRect*(e: Node): BoundingRect
 proc hasChildNodes*(n: Node): bool
 proc insertBefore*(n, newNode, before: Node)
 proc insertData*(n: Node, position: int, data: cstring)
@@ -530,6 +571,9 @@ proc preventDefault*(ev: Event)
 proc identifiedTouch*(list: TouchList): Touch
 proc item*(list: TouchList, i: int): Touch
 
+# Performance "methods"
+proc now*(p: Performance): float
+
 {.pop.}
 
 var
diff --git a/lib/pure/algorithm.nim b/lib/pure/algorithm.nim
index 23a0cdb02..2f7b44b31 100644
--- a/lib/pure/algorithm.nim
+++ b/lib/pure/algorithm.nim
@@ -84,7 +84,7 @@ proc smartBinarySearch*[T](a: openArray[T], key: T): int =
 const
   onlySafeCode = true
 
-proc lowerBound*[T](a: openArray[T], key: T, cmp: proc(x,y: T): int {.closure.}): int =
+proc lowerBound*[T, K](a: openArray[T], key: K, cmp: proc(x: T, k: K): int {.closure.}): int =
   ## same as binarySearch except that if key is not in `a` then this
   ## returns the location where `key` would be if it were. In other
   ## words if you have a sorted sequence and you call
diff --git a/lib/pure/asyncfile.nim b/lib/pure/asyncfile.nim
index 97bec2815..1df7c3fc0 100644
--- a/lib/pure/asyncfile.nim
+++ b/lib/pure/asyncfile.nim
@@ -78,7 +78,10 @@ proc getFileSize*(f: AsyncFile): int64 =
       raiseOSError(osLastError())
     result = (high shl 32) or low
   else:
+    let curPos = lseek(f.fd.cint, 0, SEEK_CUR)
     result = lseek(f.fd.cint, 0, SEEK_END)
+    f.offset = lseek(f.fd.cint, curPos, SEEK_SET)
+    assert(f.offset == curPos)
 
 proc newAsyncFile*(fd: AsyncFd): AsyncFile =
   ## Creates `AsyncFile` with a previously opened file descriptor `fd`.
@@ -281,6 +284,7 @@ proc read*(f: AsyncFile, size: int): Future[string] =
           result = false # We still want this callback to be called.
       elif res == 0:
         # EOF
+        f.offset = lseek(fd.cint, 0, SEEK_CUR)
         retFuture.complete("")
       else:
         readBuffer.setLen(res)
diff --git a/lib/pure/collections/tables.nim b/lib/pure/collections/tables.nim
index c97846f92..7b508b294 100644
--- a/lib/pure/collections/tables.nim
+++ b/lib/pure/collections/tables.nim
@@ -158,6 +158,12 @@ template getOrDefaultImpl(t, key): untyped =
   var index = rawGet(t, key, hc)
   if index >= 0: result = t.data[index].val
 
+template getOrDefaultImpl(t, key, default: untyped): untyped =
+  mixin rawGet
+  var hc: Hash
+  var index = rawGet(t, key, hc)
+  result = if index >= 0: t.data[index].val else: default
+
 proc `[]`*[A, B](t: Table[A, B], key: A): B {.deprecatedGet.} =
   ## retrieves the value at ``t[key]``. If `key` is not in `t`, the
   ## ``KeyError`` exception is raised. One can check with ``hasKey`` whether
@@ -175,10 +181,18 @@ proc mget*[A, B](t: var Table[A, B], key: A): var B {.deprecated.} =
   ## instead.
   get(t, key)
 
-proc getOrDefault*[A, B](t: Table[A, B], key: A): B = getOrDefaultImpl(t, key)
+proc getOrDefault*[A, B](t: Table[A, B], key: A): B =
+  ## retrieves the value at ``t[key]`` iff `key` is in `t`. Otherwise, the
+  ## default initialization value for type `B` is returned (e.g. 0 for any
+  ## integer type).
+  getOrDefaultImpl(t, key)
 
-template withValue*[A, B](t: var Table[A, B], key: A,
-                          value, body: untyped) =
+proc getOrDefault*[A, B](t: Table[A, B], key: A, default: B): B =
+  ## retrieves the value at ``t[key]`` iff `key` is in `t`. Otherwise, `default`
+  ## is returned.
+  getOrDefaultImpl(t, key, default)
+
+template withValue*[A, B](t: var Table[A, B], key: A, value, body: untyped) =
   ## retrieves the value at ``t[key]``.
   ## `value` can be modified in the scope of the ``withValue`` call.
   ##
@@ -325,8 +339,7 @@ proc initTable*[A, B](initialSize=64): Table[A, B] =
   result.counter = 0
   newSeq(result.data, initialSize)
 
-proc toTable*[A, B](pairs: openArray[(A,
-                    B)]): Table[A, B] =
+proc toTable*[A, B](pairs: openArray[(A, B)]): Table[A, B] =
   ## creates a new hash table that contains the given `pairs`.
   result = initTable[A, B](rightSize(pairs.len))
   for key, val in items(pairs): result[key] = val
@@ -410,7 +423,16 @@ proc mget*[A, B](t: TableRef[A, B], key: A): var B {.deprecated.} =
   ## Use ```[]``` instead.
   t[][key]
 
-proc getOrDefault*[A, B](t: TableRef[A, B], key: A): B = getOrDefault(t[], key)
+proc getOrDefault*[A, B](t: TableRef[A, B], key: A): B =
+  ## retrieves the value at ``t[key]`` iff `key` is in `t`. Otherwise, the
+  ## default initialization value for type `B` is returned (e.g. 0 for any
+  ## integer type).
+  getOrDefault(t[], key)
+
+proc getOrDefault*[A, B](t: TableRef[A, B], key: A, default: B): B =
+  ## retrieves the value at ``t[key]`` iff `key` is in `t`. Otherwise, `default`
+  ## is returned.
+  getOrDefault(t[], key, default)
 
 proc mgetOrPut*[A, B](t: TableRef[A, B], key: A, val: B): var B =
   ## retrieves value at ``t[key]`` or puts ``val`` if not present, either way
@@ -562,8 +584,15 @@ proc mget*[A, B](t: var OrderedTable[A, B], key: A): var B {.deprecated.} =
   get(t, key)
 
 proc getOrDefault*[A, B](t: OrderedTable[A, B], key: A): B =
+  ## retrieves the value at ``t[key]`` iff `key` is in `t`. Otherwise, the
+  ## default initialization value for type `B` is returned (e.g. 0 for any
+  ## integer type).
   getOrDefaultImpl(t, key)
 
+proc getOrDefault*[A, B](t: OrderedTable[A, B], key: A, default: B): B =
+  ## retrieves the value at ``t[key]`` iff `key` is in `t`. Otherwise, `default`
+  ## is returned.
+  getOrDefaultImpl(t, key, default)
 
 proc hasKey*[A, B](t: OrderedTable[A, B], key: A): bool =
   ## returns true iff `key` is in the table `t`.
@@ -630,8 +659,7 @@ proc initOrderedTable*[A, B](initialSize=64): OrderedTable[A, B] =
   result.last = -1
   newSeq(result.data, initialSize)
 
-proc toOrderedTable*[A, B](pairs: openArray[(A,
-                           B)]): OrderedTable[A, B] =
+proc toOrderedTable*[A, B](pairs: openArray[(A, B)]): OrderedTable[A, B] =
   ## creates a new ordered hash table that contains the given `pairs`.
   result = initOrderedTable[A, B](rightSize(pairs.len))
   for key, val in items(pairs): result[key] = val
@@ -657,8 +685,7 @@ proc `==`*[A, B](s, t: OrderedTable[A, B]): bool =
     hs = nxts
   return true
 
-proc sort*[A, B](t: var OrderedTable[A, B],
-                 cmp: proc (x,y: (A, B)): int) =
+proc sort*[A, B](t: var OrderedTable[A, B], cmp: proc (x,y: (A, B)): int) =
   ## sorts `t` according to `cmp`. This modifies the internal list
   ## that kept the insertion order, so insertion order is lost after this
   ## call but key lookup and insertions remain possible after `sort` (in
@@ -748,8 +775,16 @@ proc mget*[A, B](t: OrderedTableRef[A, B], key: A): var B {.deprecated.} =
   result = t[][key]
 
 proc getOrDefault*[A, B](t: OrderedTableRef[A, B], key: A): B =
+  ## retrieves the value at ``t[key]`` iff `key` is in `t`. Otherwise, the
+  ## default initialization value for type `B` is returned (e.g. 0 for any
+  ## integer type).
   getOrDefault(t[], key)
 
+proc getOrDefault*[A, B](t: OrderedTableRef[A, B], key: A, default: B): B =
+  ## retrieves the value at ``t[key]`` iff `key` is in `t`. Otherwise, `default`
+  ## is returned.
+  getOrDefault(t[], key, default)
+
 proc mgetOrPut*[A, B](t: OrderedTableRef[A, B], key: A, val: B): var B =
   ## retrieves value at ``t[key]`` or puts ``val`` if not present, either way
   ## returning a value which can be modified.
@@ -802,8 +837,7 @@ proc `==`*[A, B](s, t: OrderedTableRef[A, B]): bool =
   elif isNil(t): result = false
   else: result = s[] == t[]
 
-proc sort*[A, B](t: OrderedTableRef[A, B],
-                 cmp: proc (x,y: (A, B)): int) =
+proc sort*[A, B](t: OrderedTableRef[A, B], cmp: proc (x,y: (A, B)): int) =
   ## sorts `t` according to `cmp`. This modifies the internal list
   ## that kept the insertion order, so insertion order is lost after this
   ## call but key lookup and insertions remain possible after `sort` (in
@@ -916,9 +950,17 @@ proc mget*[A](t: var CountTable[A], key: A): var int {.deprecated.} =
   ctget(t, key)
 
 proc getOrDefault*[A](t: CountTable[A], key: A): int =
+  ## retrieves the value at ``t[key]`` iff `key` is in `t`. Otherwise, 0 (the
+  ## default initialization value of `int`), is returned.
   var index = rawGet(t, key)
   if index >= 0: result = t.data[index].val
 
+proc getOrDefault*[A](t: CountTable[A], key: A, default: int): int =
+  ## retrieves the value at ``t[key]`` iff `key` is in `t`. Otherwise, the
+  ## integer value of `default` is returned.
+  var index = rawGet(t, key)
+  result = if index >= 0: t.data[index].val else: default
+
 proc hasKey*[A](t: CountTable[A], key: A): bool =
   ## returns true iff `key` is in the table `t`.
   result = rawGet(t, key) >= 0
@@ -1073,8 +1115,15 @@ proc mget*[A](t: CountTableRef[A], key: A): var int {.deprecated.} =
   result = t[][key]
 
 proc getOrDefault*[A](t: CountTableRef[A], key: A): int =
+  ## retrieves the value at ``t[key]`` iff `key` is in `t`. Otherwise, 0 (the
+  ## default initialization value of `int`), is returned.
   result = t[].getOrDefault(key)
 
+proc getOrDefault*[A](t: CountTableRef[A], key: A, default: int): int =
+  ## retrieves the value at ``t[key]`` iff `key` is in `t`. Otherwise, the
+  ## integer value of `default` is returned.
+  result = t[].getOrDefault(key, default)
+
 proc hasKey*[A](t: CountTableRef[A], key: A): bool =
   ## returns true iff `key` is in the table `t`.
   result = t[].hasKey(key)
@@ -1267,7 +1316,7 @@ when isMainModule:
     #lib/pure/collections/tables.nim(117, 21) template/generic instantiation from here
     #lib/pure/collections/tableimpl.nim(32, 27) Error: undeclared field: 'hcode
     doAssert 0 == t.getOrDefault(testKey)
-    t.inc(testKey,3)
+    t.inc(testKey, 3)
     doAssert 3 == t.getOrDefault(testKey)
 
   block:
@@ -1334,3 +1383,21 @@ when isMainModule:
   block: # CountTable.smallest
     let t = toCountTable([0, 0, 5, 5, 5])
     doAssert t.smallest == (0, 2)
+
+  block:
+    var tp: Table[string, string] = initTable[string, string]()
+    doAssert "test1" == tp.getOrDefault("test1", "test1")
+    tp["test2"] = "test2"
+    doAssert "test2" == tp.getOrDefault("test2", "test1")
+    var tr: TableRef[string, string] = newTable[string, string]()
+    doAssert "test1" == tr.getOrDefault("test1", "test1")
+    tr["test2"] = "test2"
+    doAssert "test2" == tr.getOrDefault("test2", "test1")
+    var op: OrderedTable[string, string] = initOrderedTable[string, string]()
+    doAssert "test1" == op.getOrDefault("test1", "test1")
+    op["test2"] = "test2"
+    doAssert "test2" == op.getOrDefault("test2", "test1")
+    var orf: OrderedTableRef[string, string] = newOrderedTable[string, string]()
+    doAssert "test1" == orf.getOrDefault("test1", "test1")
+    orf["test2"] = "test2"
+    doAssert "test2" == orf.getOrDefault("test2", "test1")
diff --git a/lib/pure/dynlib.nim b/lib/pure/dynlib.nim
index fda41dadb..ec6cbb232 100644
--- a/lib/pure/dynlib.nim
+++ b/lib/pure/dynlib.nim
@@ -10,6 +10,49 @@
 ## This module implements the ability to access symbols from shared
 ## libraries. On POSIX this uses the ``dlsym`` mechanism, on
 ## Windows ``LoadLibrary``.
+##
+## Examples
+## --------
+##
+## Loading a simple C function
+## ^^^^^^^^^^^^^^^^^^^^^^^^^^^
+##
+## The following example demonstrates loading a function called 'greet' 
+## from a library that is determined at runtime based upon a language choice.
+## If the library fails to load or the function 'greet' is not found, 
+## it quits with a failure error code.
+##
+## .. code-block::nim
+##
+##   import dynlib
+##
+##   type
+##     greetFunction = proc(): cstring {.gcsafe, stdcall.}
+##
+##   let lang = stdin.readLine()
+##
+##   let lib = case lang
+##   of "french":
+##     loadLib("french.dll")
+##   else:
+##     loadLib("english.dll")
+##
+##   if lib == nil:
+##     echo "Error loading library"
+##     quit(QuitFailure)
+##
+##   let greet = cast[greetFunction](lib.symAddr("greet"))
+##
+##   if greet == nil:
+##     echo "Error loading 'greet' function from library"
+##     quit(QuitFailure)
+##
+##   let greeting = greet()
+##
+##   echo greeting
+##
+##   unloadLib(lib)
+##
 
 import strutils
 
diff --git a/lib/pure/json.nim b/lib/pure/json.nim
index bbde4db5f..912cd6837 100644
--- a/lib/pure/json.nim
+++ b/lib/pure/json.nim
@@ -734,7 +734,7 @@ proc getFields*(n: JsonNode,
   else: return n.fields
 
 proc getElems*(n: JsonNode, default: seq[JsonNode] = @[]): seq[JsonNode] =
-  ## Retrieves the int value of a `JArray JsonNode`.
+  ## Retrieves the array of a `JArray JsonNode`.
   ##
   ## Returns ``default`` if ``n`` is not a ``JArray``, or if ``n`` is nil.
   if n.isNil or n.kind != JArray: return default
@@ -964,6 +964,16 @@ proc `{}`*(node: JsonNode, keys: varargs[string]): JsonNode =
       return nil
     result = result.fields.getOrDefault(key)
 
+proc `{}`*(node: JsonNode, index: varargs[int]): JsonNode =
+  ## Traverses the node and gets the given value. If any of the
+  ## indexes do not exist, returns ``nil``. Also returns ``nil`` if one of the
+  ## intermediate data structures is not an array.
+  result = node
+  for i in index:
+    if isNil(result) or result.kind != JArray or i >= node.len:
+      return nil
+    result = result.elems[i]
+
 proc getOrDefault*(node: JsonNode, key: string): JsonNode =
   ## Gets a field from a `node`. If `node` is nil or not an object or
   ## value at `key` does not exist, returns nil
diff --git a/lib/pure/net.nim b/lib/pure/net.nim
index 336068df0..ccf02a1fc 100644
--- a/lib/pure/net.nim
+++ b/lib/pure/net.nim
@@ -1701,6 +1701,9 @@ proc connect*(socket: Socket, address: string, port = Port(0),
   if selectWrite(s, timeout) != 1:
     raise newException(TimeoutError, "Call to 'connect' timed out.")
   else:
+    let res = getSockOptInt(socket.fd, SOL_SOCKET, SO_ERROR)
+    if res != 0:
+      raiseOSError(OSErrorCode(res))
     when defineSsl and not defined(nimdoc):
       if socket.isSSL:
         socket.fd.setBlocking(true)
diff --git a/lib/pure/times.nim b/lib/pure/times.nim
index 6c1e1fe87..75b5bac43 100644
--- a/lib/pure/times.nim
+++ b/lib/pure/times.nim
@@ -274,6 +274,18 @@ proc toTime*(dt: DateTime): Time {.tags: [], raises: [], benign.} =
   # so we need to compensate for that here.
   result.inc dt.utcOffset
 
+proc `<`*(a, b: DateTime): bool =
+  ## Returns true iff ``a < b``, that is iff a happened before b.
+  return a.toTime < b.toTime
+
+proc `<=` * (a, b: DateTime): bool =
+  ## Returns true iff ``a <= b``.
+  return a.toTime <= b.toTime
+
+proc `==`*(a, b: DateTime): bool =
+  ## Returns true if ``a == b``, that is if both dates represent the same point in datetime.
+  return a.toTime == b.toTime
+
 proc initDateTime(zt: ZonedTime, zone: Timezone): DateTime =
   let adjTime = zt.adjTime.int64
   let epochday = (if adjTime >= 0: adjTime else: adjTime - (secondsInDay - 1)) div secondsInDay
diff --git a/lib/pure/unittest.nim b/lib/pure/unittest.nim
index fbce087ff..0034d0c60 100644
--- a/lib/pure/unittest.nim
+++ b/lib/pure/unittest.nim
@@ -150,6 +150,7 @@ var
   checkpoints {.threadvar.}: seq[string]
   formatters {.threadvar.}: seq[OutputFormatter]
   testsFilters {.threadvar.}: HashSet[string]
+  disabledParamFiltering {.threadvar.}: bool
 
 when declared(stdout):
   abortOnError = existsEnv("NIMTEST_ABORT_ON_ERROR")
@@ -379,7 +380,7 @@ proc ensureInitialized() =
   if formatters == nil:
     formatters = @[OutputFormatter(defaultConsoleFormatter())]
 
-  if not testsFilters.isValid:
+  if not disabledParamFiltering and not testsFilters.isValid:
     testsFilters.init()
     when declared(paramCount):
       # Read tests to run from the command line.
@@ -701,3 +702,7 @@ macro expect*(exceptions: varargs[typed], body: untyped): untyped =
     errorTypes.add(exp[i])
 
   result = getAst(expectBody(errorTypes, exp.lineinfo, body))
+
+proc disableParamFiltering* =
+  ## disables filtering tests with the command line params
+  disabledParamFiltering = true
diff --git a/lib/pure/xmlparser.nim b/lib/pure/xmlparser.nim
index 22bd259b7..9159b4bfc 100644
--- a/lib/pure/xmlparser.nim
+++ b/lib/pure/xmlparser.nim
@@ -12,9 +12,9 @@
 import streams, parsexml, strtabs, xmltree
 
 type
-  XmlError* = object of ValueError ## exception that is raised
-                                   ## for invalid XML
-    errors*: seq[string]           ## all detected parsing errors
+  XmlError* = object of ValueError ## Exception that is raised
+                                   ## for invalid XML.
+    errors*: seq[string]           ## All detected parsing errors.
 
 {.deprecated: [EInvalidXml: XmlError].}
 
@@ -102,8 +102,8 @@ proc parse(x: var XmlParser, errors: var seq[string]): XmlNode =
 
 proc parseXml*(s: Stream, filename: string,
                errors: var seq[string]): XmlNode =
-  ## parses the XML from stream `s` and returns a ``PXmlNode``. Every
-  ## occurred parsing error is added to the `errors` sequence.
+  ## Parses the XML from stream ``s`` and returns a ``XmlNode``. Every
+  ## occurred parsing error is added to the ``errors`` sequence.
   var x: XmlParser
   open(x, s, filename, {reportComments})
   while true:
@@ -121,15 +121,20 @@ proc parseXml*(s: Stream, filename: string,
   close(x)
 
 proc parseXml*(s: Stream): XmlNode =
-  ## parses the XTML from stream `s` and returns a ``PXmlNode``. All parsing
-  ## errors are turned into an ``EInvalidXML`` exception.
+  ## Parses the XML from stream ``s`` and returns a ``XmlNode``. All parsing
+  ## errors are turned into an ``XmlError`` exception.
   var errors: seq[string] = @[]
-  result = parseXml(s, "unknown_html_doc", errors)
+  result = parseXml(s, "unknown_xml_doc", errors)
   if errors.len > 0: raiseInvalidXml(errors)
 
+proc parseXml*(str: string): XmlNode =
+  ## Parses the XML from string ``str`` and returns a ``XmlNode``. All parsing
+  ## errors are turned into an ``XmlError`` exception.
+  parseXml(newStringStream(str))
+
 proc loadXml*(path: string, errors: var seq[string]): XmlNode =
   ## Loads and parses XML from file specified by ``path``, and returns
-  ## a ``PXmlNode``. Every occurred parsing error is added to the `errors`
+  ## a ``XmlNode``. Every occurred parsing error is added to the ``errors``
   ## sequence.
   var s = newFileStream(path, fmRead)
   if s == nil: raise newException(IOError, "Unable to read file: " & path)
@@ -137,7 +142,7 @@ proc loadXml*(path: string, errors: var seq[string]): XmlNode =
 
 proc loadXml*(path: string): XmlNode =
   ## Loads and parses XML from file specified by ``path``, and returns
-  ## a ``PXmlNode``.  All parsing errors are turned into an ``EInvalidXML``
+  ## a ``XmlNode``. All parsing errors are turned into an ``XmlError``
   ## exception.
   var errors: seq[string] = @[]
   result = loadXml(path, errors)
diff --git a/lib/system.nim b/lib/system.nim
index b71a3c73c..7eda30276 100644
--- a/lib/system.nim
+++ b/lib/system.nim
@@ -617,6 +617,11 @@ type
     ##
     ## This is only raised if the ``segfaults.nim`` module was imported!
 
+when defined(nimNewRuntime):
+  type
+    MoveError* = object of SystemError ## \
+      ## Raised on attempts to re-sink an already consumed ``sink`` parameter.
+
 {.deprecated: [TObject: RootObj, PObject: RootRef, TEffect: RootEffect,
   FTime: TimeEffect, FIO: IOEffect, FReadIO: ReadIOEffect,
   FWriteIO: WriteIOEffect, FExecIO: ExecIOEffect,
@@ -1774,7 +1779,7 @@ when not defined(nimscript):
     proc createU*(T: typedesc, size = 1.Positive): ptr T {.inline, benign.} =
       ## allocates a new memory block with at least ``T.sizeof * size``
       ## bytes. The block has to be freed with ``resize(block, 0)`` or
-      ## ``free(block)``. The block is not initialized, so reading
+      ## ``dealloc(block)``. The block is not initialized, so reading
       ## from it before writing to it is undefined behaviour!
       ## The allocated memory belongs to its allocating thread!
       ## Use `createSharedU` to allocate from a shared heap.
@@ -1789,7 +1794,7 @@ when not defined(nimscript):
     proc create*(T: typedesc, size = 1.Positive): ptr T {.inline, benign.} =
       ## allocates a new memory block with at least ``T.sizeof * size``
       ## bytes. The block has to be freed with ``resize(block, 0)`` or
-      ## ``free(block)``. The block is initialized with all bytes
+      ## ``dealloc(block)``. The block is initialized with all bytes
       ## containing zero, so it is somewhat safer than ``createU``.
       ## The allocated memory belongs to its allocating thread!
       ## Use `createShared` to allocate from a shared heap.
@@ -1807,7 +1812,7 @@ when not defined(nimscript):
       ## grows or shrinks a given memory block. If p is **nil** then a new
       ## memory block is returned. In either way the block has at least
       ## ``T.sizeof * newSize`` bytes. If ``newSize == 0`` and p is not
-      ## **nil** ``resize`` calls ``free(p)``. In other cases the block
+      ## **nil** ``resize`` calls ``dealloc(p)``. In other cases the block
       ## has to be freed with ``free``. The allocated memory belongs to
       ## its allocating thread!
       ## Use `resizeShared` to reallocate from a shared heap.
@@ -4131,3 +4136,13 @@ when defined(cpp) and appType != "lib" and not defined(js) and
     stderr.write trace & "Error: unhandled exception: " & ex.msg &
                  " [" & $ex.name & "]\n"
     quit 1
+
+when not defined(js):
+  proc toOpenArray*[T](x: seq[T]; first, last: int): openarray[T] {.
+    magic: "Slice".}
+  proc toOpenArray*[T](x: openarray[T]; first, last: int): openarray[T] {.
+    magic: "Slice".}
+  proc toOpenArray*[I, T](x: array[I, T]; first, last: I): openarray[T] {.
+    magic: "Slice".}
+  proc toOpenArray*(x: string; first, last: int): openarray[char] {.
+    magic: "Slice".}
diff --git a/lib/system/alloc.nim b/lib/system/alloc.nim
index 4291013a2..6aef4f411 100644
--- a/lib/system/alloc.nim
+++ b/lib/system/alloc.nim
@@ -29,7 +29,9 @@ const
   FliOffset = 6
   RealFli = MaxFli - FliOffset
 
-  HugeChunkSize = int high(int32) - 1 # 2 GB, depends on TLSF's impl
+  # size of chunks in last matrix bin
+  MaxBigChunkSize = 1 shl MaxFli - 1 shl (MaxFli-MaxLog2Sli-1)
+  HugeChunkSize = MaxBigChunkSize + 1
 
 type
   PTrunk = ptr Trunk
@@ -154,10 +156,11 @@ proc mappingSearch(r, fl, sl: var int) {.inline.} =
   # PageSize alignment:
   let t = roundup((1 shl (msbit(uint32 r) - MaxLog2Sli)), PageSize) - 1
   r = r + t
+  r = r and not t
+  r = min(r, MaxBigChunkSize)
   fl = msbit(uint32 r)
   sl = (r shr (fl - MaxLog2Sli)) - MaxSli
   dec fl, FliOffset
-  r = r and not t
   sysAssert((r and PageMask) == 0, "mappingSearch: still not aligned")
 
 # See http://www.gii.upv.es/tlsf/files/papers/tlsf_desc.pdf for details of
@@ -518,55 +521,61 @@ proc updatePrevSize(a: var MemRegion, c: PBigChunk,
   if isAccessible(a, ri):
     ri.prevSize = prevSize or (ri.prevSize and 1)
 
+proc splitChunk2(a: var MemRegion, c: PBigChunk, size: int): PBigChunk =
+  result = cast[PBigChunk](cast[ByteAddress](c) +% size)
+  result.size = c.size - size
+  track("result.origSize", addr result.origSize, sizeof(int))
+  # XXX check if these two nil assignments are dead code given
+  # addChunkToMatrix's implementation:
+  result.next = nil
+  result.prev = nil
+  # size and not used:
+  result.prevSize = size
+  sysAssert((size and 1) == 0, "splitChunk 2")
+  sysAssert((size and PageMask) == 0,
+      "splitChunk: size is not a multiple of the PageSize")
+  updatePrevSize(a, c, result.size)
+  c.size = size
+  incl(a, a.chunkStarts, pageIndex(result))
+
+proc splitChunk(a: var MemRegion, c: PBigChunk, size: int) =
+  let rest = splitChunk2(a, c, size)
+  addChunkToMatrix(a, rest)
+
 proc freeBigChunk(a: var MemRegion, c: PBigChunk) =
   var c = c
   sysAssert(c.size >= PageSize, "freeBigChunk")
   inc(a.freeMem, c.size)
-  when coalescRight:
-    var ri = cast[PChunk](cast[ByteAddress](c) +% c.size)
-    sysAssert((cast[ByteAddress](ri) and PageMask) == 0, "freeBigChunk 2")
-    if isAccessible(a, ri) and chunkUnused(ri):
-      sysAssert(not isSmallChunk(ri), "freeBigChunk 3")
-      if not isSmallChunk(ri):
-        removeChunkFromMatrix(a, cast[PBigChunk](ri))
-        inc(c.size, ri.size)
-        excl(a.chunkStarts, pageIndex(ri))
+  c.prevSize = c.prevSize and not 1  # set 'used' to false
   when coalescLeft:
-    let prevSize = c.prevSize and not 1
+    let prevSize = c.prevSize
     if prevSize != 0:
       var le = cast[PChunk](cast[ByteAddress](c) -% prevSize)
       sysAssert((cast[ByteAddress](le) and PageMask) == 0, "freeBigChunk 4")
       if isAccessible(a, le) and chunkUnused(le):
         sysAssert(not isSmallChunk(le), "freeBigChunk 5")
-        if not isSmallChunk(le):
+        if not isSmallChunk(le) and le.size < MaxBigChunkSize:
           removeChunkFromMatrix(a, cast[PBigChunk](le))
           inc(le.size, c.size)
           excl(a.chunkStarts, pageIndex(c))
           c = cast[PBigChunk](le)
-
-  incl(a, a.chunkStarts, pageIndex(c))
-  updatePrevSize(a, c, c.size)
+          if c.size > MaxBigChunkSize:
+            let rest = splitChunk2(a, c, MaxBigChunkSize)
+            addChunkToMatrix(a, c)
+            c = rest
+  when coalescRight:
+    var ri = cast[PChunk](cast[ByteAddress](c) +% c.size)
+    sysAssert((cast[ByteAddress](ri) and PageMask) == 0, "freeBigChunk 2")
+    if isAccessible(a, ri) and chunkUnused(ri):
+      sysAssert(not isSmallChunk(ri), "freeBigChunk 3")
+      if not isSmallChunk(ri) and c.size < MaxBigChunkSize:
+        removeChunkFromMatrix(a, cast[PBigChunk](ri))
+        inc(c.size, ri.size)
+        excl(a.chunkStarts, pageIndex(ri))
+        if c.size > MaxBigChunkSize:
+          let rest = splitChunk2(a, c, MaxBigChunkSize)
+          addChunkToMatrix(a, rest)
   addChunkToMatrix(a, c)
-  # set 'used' to false:
-  c.prevSize = c.prevSize and not 1
-
-proc splitChunk(a: var MemRegion, c: PBigChunk, size: int) =
-  var rest = cast[PBigChunk](cast[ByteAddress](c) +% size)
-  rest.size = c.size - size
-  track("rest.origSize", addr rest.origSize, sizeof(int))
-  # XXX check if these two nil assignments are dead code given
-  # addChunkToMatrix's implementation:
-  rest.next = nil
-  rest.prev = nil
-  # size and not used:
-  rest.prevSize = size
-  sysAssert((size and 1) == 0, "splitChunk 2")
-  sysAssert((size and PageMask) == 0,
-      "splitChunk: size is not a multiple of the PageSize")
-  updatePrevSize(a, c, rest.size)
-  c.size = size
-  incl(a, a.chunkStarts, pageIndex(rest))
-  addChunkToMatrix(a, rest)
 
 proc getBigChunk(a: var MemRegion, size: int): PBigChunk =
   sysAssert(size > 0, "getBigChunk 2")
diff --git a/lib/system/chcks.nim b/lib/system/chcks.nim
index 69b680dbd..d3651f659 100644
--- a/lib/system/chcks.nim
+++ b/lib/system/chcks.nim
@@ -52,6 +52,11 @@ proc chckNil(p: pointer) =
   if p == nil:
     sysFatal(NilAccessError, "attempt to write to a nil address")
 
+when defined(nimNewRuntime):
+  proc chckMove(b: bool) {.compilerproc.} =
+    if not b:
+      sysFatal(MoveError, "attempt to access an object that was moved")
+
 proc chckNilDisp(p: pointer) {.compilerproc.} =
   if p == nil:
     sysFatal(NilAccessError, "cannot dispatch; dispatcher is nil")
diff --git a/lib/wrappers/mysql.nim b/lib/wrappers/mysql.nim
index e53d5308a..4464eae50 100644
--- a/lib/wrappers/mysql.nim
+++ b/lib/wrappers/mysql.nim
@@ -13,10 +13,10 @@
 when defined(Unix):
   when defined(macosx):
     const
-      lib = "(libmysqlclient|libmariadbclient).(|20|19|18|17|16|15).dylib"
+      lib = "(libmysqlclient|libmariadbclient)(|.20|.19|.18|.17|.16|.15).dylib"
   else:
     const
-      lib = "(libmysqlclient|libmariadbclient).so.(|20|19|18|17|16|15)"
+      lib = "(libmysqlclient|libmariadbclient).so(|.20|.19|.18|.17|.16|.15)"
 when defined(Windows):
   const
     lib = "(libmysql.dll|libmariadb.dll)"
diff --git a/lib/wrappers/openssl.nim b/lib/wrappers/openssl.nim
index eefc09cb9..357343bff 100644
--- a/lib/wrappers/openssl.nim
+++ b/lib/wrappers/openssl.nim
@@ -38,7 +38,7 @@ when useWinVersion:
 
   from winlean import SocketHandle
 else:
-  const versions = "(.1.1|.38|.39|.41|.43|.10|.1.0.2|.1.0.1|.1.0.0|.0.9.9|.0.9.8|)"
+  const versions = "(.1.1|.38|.39|.41|.43|.44|.10|.1.0.2|.1.0.1|.1.0.0|.0.9.9|.0.9.8|)"
 
   when defined(macosx):
     const
diff --git a/nimsuggest/nimsuggest.nim b/nimsuggest/nimsuggest.nim
index 0328b817a..abfb21c13 100644
--- a/nimsuggest/nimsuggest.nim
+++ b/nimsuggest/nimsuggest.nim
@@ -608,9 +608,9 @@ proc handleCmdLine(cache: IdentCache; config: ConfigRef) =
     options.command = "nimsuggest"
     let scriptFile = gProjectFull.changeFileExt("nims")
     if fileExists(scriptFile):
-      runNimScript(cache, scriptFile, freshDefines=false, config)
-      # 'nim foo.nims' means to just run the NimScript file and do nothing more:
-      if scriptFile == gProjectFull: return
+      # 'nimsuggest foo.nims' means to just auto-complete the NimScript file:
+      if scriptFile != gProjectFull:
+        runNimScript(cache, scriptFile, freshDefines=false, config)
     elif fileExists(gProjectPath / "config.nims"):
       # directory wide NimScript file
       runNimScript(cache, gProjectPath / "config.nims", freshDefines=false, config)
diff --git a/readme.md b/readme.md
index ebcf5f802..44c92d06b 100644
--- a/readme.md
+++ b/readme.md
@@ -52,6 +52,10 @@ Nim from source using ``gcc``, ``git`` and the ``koch`` build tool (in the place
 of ``sh build.sh`` you should substitute ``build.bat`` on x86 Windows or
 ``build64.bat`` on x86_64 Windows):
 
+**Note: The following commands are for the development version of the compiler.**
+For most users, installing the latest stable version is enough. Check out
+the installation instructions on the website to do so: https://nim-lang.org/install.html.
+
 ```
 git clone https://github.com/nim-lang/Nim.git
 cd Nim
@@ -61,6 +65,7 @@ sh build.sh
 cd ../
 bin/nim c koch
 ./koch boot -d:release
+./koch tools # Compile Nimble and other tools.
 ```
 
 Finally, once you have finished the build steps (on Windows, Mac or Linux) you
@@ -80,11 +85,9 @@ For more information on the ``koch`` build tool please see the documentation
 within the [doc/koch.rst](doc/koch.rst) file.
 
 ## Nimble
-``nimble`` is Nim's package manager and it can be acquired from the
-[``nim-lang/nimble``][nimble-repo] repository. Assuming that you added Nim's
-``bin`` directory to your PATH, you may install Nimble from source by running
-``koch nimble`` within the root of the cloned repository.
 
+``nimble`` is Nim's package manager. To learn more about it, see the
+[``nim-lang/nimble``][nimble-repo] repository.
 
 ## Contributors
 
diff --git a/tests/async/hello.txt b/tests/async/hello.txt
new file mode 100644
index 000000000..854d6c20a
--- /dev/null
+++ b/tests/async/hello.txt
@@ -0,0 +1 @@
+hello humans!
\ No newline at end of file
diff --git a/tests/async/tasyncfile.nim b/tests/async/tasyncfile.nim
index aa7f03ab1..c7b71a2f7 100644
--- a/tests/async/tasyncfile.nim
+++ b/tests/async/tasyncfile.nim
@@ -1,4 +1,8 @@
 discard """
+  output: '''13
+hello humans!
+13
+'''
   file: "tasyncfile.nim"
   exitcode: 0
 """
@@ -48,5 +52,12 @@ proc main() {.async.} =
     doAssert data == "t3"
     file.close()
 
+  # Issue #7347
+  block:
+    let appDir = getAppDir()
+    var file = openAsync(appDir & DirSep & "hello.txt")
+    echo file.getFileSize()
+    echo await file.readAll()
+    echo file.getFilePos()
 
 waitFor main()
diff --git a/tests/ccgbugs/mymodule.nim b/tests/ccgbugs/mymodule.nim
new file mode 100644
index 000000000..8c78cdf9b
--- /dev/null
+++ b/tests/ccgbugs/mymodule.nim
@@ -0,0 +1,14 @@
+type
+  MyRefObject* = ref object
+    s: string
+  
+  BaseObj* = ref object of RootObj
+  ChildObj* = ref object of BaseObj
+
+proc newMyRefObject*(s: string): MyRefObject =
+  new(result)
+  result.s = s
+  
+proc `$`*(o: MyRefObject): string =
+  o.s
+  
\ No newline at end of file
diff --git a/tests/ccgbugs/tforward_decl_only.nim b/tests/ccgbugs/tforward_decl_only.nim
new file mode 100644
index 000000000..2a867bc3b
--- /dev/null
+++ b/tests/ccgbugs/tforward_decl_only.nim
@@ -0,0 +1,34 @@
+discard """
+ccodecheck: "\\i !@('struct tyObject_MyRefObject'[0-z]+' {')"
+output: "hello"
+"""
+
+# issue #7339 
+# Test that MyRefObject is only forward declared as it used only by reference
+
+import mymodule
+type AnotherType = object
+  f: MyRefObject 
+
+let x = AnotherType(f: newMyRefObject("hello"))
+echo $x.f
+
+
+# bug #7363
+
+type 
+  Foo = object
+    a: cint
+  Foo2 = object
+    b: cint
+
+proc f(foo: ptr Foo, foo2: ptr Foo2): cint =
+  if foo  != nil:  {.emit: "`result` = `foo`->a;".}
+  if foo2 != nil: {.emit: [result, " = ", foo2[], ".b;"].}
+
+discard f(nil, nil)
+
+
+# bug #7392
+var x1: BaseObj
+var x2 = ChildObj(x1)
diff --git a/tests/ccgbugs/tresult_of_array.nim b/tests/ccgbugs/tresult_of_array.nim
new file mode 100644
index 000000000..fb5abf18a
--- /dev/null
+++ b/tests/ccgbugs/tresult_of_array.nim
@@ -0,0 +1,29 @@
+discard """
+  output: '''false
+true
+false
+[false, false, false]
+'''
+"""
+
+# bug #7332
+# resetLoc generate incorrect memset code
+# because of array passed as argument decaying into a pointer
+
+import tables
+const tableOfArray = {
+    "one": [true, false, false],
+    "two": [false, true, false],
+    "three": [false, false, true]
+}.toTable()
+for i in 0..2:
+    echo tableOfArray["two"][i]
+
+var seqOfArray = @[
+    [true, false, false],
+    [false, true, false],
+    [false, false, true]
+]
+proc crashingProc*[B](t: seq[B], index: Natural): B =
+    discard
+echo seqOfArray.crashingProc(0)
diff --git a/tests/concepts/tseqofconcept.nim b/tests/concepts/tseqofconcept.nim
new file mode 100644
index 000000000..5e44117ea
--- /dev/null
+++ b/tests/concepts/tseqofconcept.nim
@@ -0,0 +1,19 @@
+discard """
+output: "1\n2\n3"
+"""
+
+type
+  MyConcept = concept x
+    someProc(x)
+
+  SomeSeq = seq[MyConcept]
+
+proc someProc(x:int) = echo x
+
+proc work (s: SomeSeq) =
+  for item in s:
+    someProc item
+
+var s = @[1, 2, 3]
+work s
+
diff --git a/tests/cpp/tcovariancerules.nim b/tests/cpp/tcovariancerules.nim
index 9365a3a18..f81d67a50 100644
--- a/tests/cpp/tcovariancerules.nim
+++ b/tests/cpp/tcovariancerules.nim
@@ -300,7 +300,7 @@ reject wantsVarPointer2(pcat)
 
 # covariance may be allowed for certain extern types
 
-{.emit: """
+{.emit: """/*TYPESECTION*/
 template <class T> struct FN { typedef void (*type)(T); };
 template <class T> struct ARR { typedef T DataType[2]; DataType data; };
 """.}
diff --git a/tests/cpp/tvector_iterator.nim b/tests/cpp/tvector_iterator.nim
index 9df3754ba..4d686955f 100644
--- a/tests/cpp/tvector_iterator.nim
+++ b/tests/cpp/tvector_iterator.nim
@@ -2,7 +2,7 @@ discard """
   targets: "cpp"
 """
 
-{.emit: """
+{.emit: """/*TYPESECTION*/
 
 template <class T>
 struct Vector {
diff --git a/tests/errmsgs/twrong_at_operator.nim b/tests/errmsgs/twrong_at_operator.nim
new file mode 100644
index 000000000..b6b3d101f
--- /dev/null
+++ b/tests/errmsgs/twrong_at_operator.nim
@@ -0,0 +1,15 @@
+discard """
+errormsg: "type mismatch: got <array[0..0, type int]>"
+line: 15
+nimout: '''
+twrong_at_operator.nim(15, 30) Error: type mismatch: got <array[0..0, type int]>
+but expected one of:
+proc `@`[T](a: openArray[T]): seq[T]
+proc `@`[IDX, T](a: array[IDX, T]): seq[T]
+
+expression: @[int]
+'''
+"""
+
+# bug #7331
+var seqOfStrings: seq[int] = @[int]
diff --git a/tests/exception/tfinally.nim b/tests/exception/tfinally.nim
index e5315a318..7a218b444 100644
--- a/tests/exception/tfinally.nim
+++ b/tests/exception/tfinally.nim
@@ -7,6 +7,11 @@ msg1
 msg2
 finally2
 finally1
+-----------
+except1
+finally1
+except2
+finally2
 '''
 """
 # Test return in try statement:
@@ -39,4 +44,19 @@ proc nested_finally =
   finally:
     echo "finally1"
 
-nested_finally()
\ No newline at end of file
+nested_finally()
+
+echo "-----------"
+#bug 7414
+try:
+  try:
+    raise newException(Exception, "Hello")
+  except:
+    echo "except1"
+    raise
+  finally:
+    echo "finally1"
+except:
+  echo "except2"
+finally:
+  echo "finally2"
\ No newline at end of file
diff --git a/tests/fragmentation/tfragment_gc.nim b/tests/fragmentation/tfragment_gc.nim
index c930ec931..d387bbea2 100644
--- a/tests/fragmentation/tfragment_gc.nim
+++ b/tests/fragmentation/tfragment_gc.nim
@@ -1,6 +1,7 @@
 discard """
   output: '''occupied ok: true
 total ok: true'''
+  disabled: "windows"
 """
 
 import strutils, data
diff --git a/tests/macros/tdumpastgen.nim b/tests/macros/tdumpastgen.nim
index faed77225..0a1836886 100644
--- a/tests/macros/tdumpastgen.nim
+++ b/tests/macros/tdumpastgen.nim
@@ -2,16 +2,33 @@ discard """
 msg: '''nnkStmtList.newTree(
   nnkVarSection.newTree(
     nnkIdentDefs.newTree(
-      newIdentNode(!"x"),
+      newIdentNode("x"),
       newEmptyNode(),
       nnkCall.newTree(
         nnkDotExpr.newTree(
-          newIdentNode(!"foo"),
-          newIdentNode(!"create")
+          newIdentNode("baz"),
+          newIdentNode("create")
         ),
         newLit(56)
       )
     )
+  ),
+  nnkProcDef.newTree(
+    newIdentNode("foo"),
+    newEmptyNode(),
+    newEmptyNode(),
+    nnkFormalParams.newTree(
+      newEmptyNode()
+    ),
+    newEmptyNode(),
+    newEmptyNode(),
+    nnkStmtList.newTree(
+      newCommentStmtNode("This is a docstring"),
+      nnkCommand.newTree(
+        newIdentNode("echo"),
+        newLit("bar")
+      )
+    )
   )
 )'''
 """
@@ -21,5 +38,8 @@ msg: '''nnkStmtList.newTree(
 import macros
 
 dumpAstGen:
-  var x = foo.create(56)
+  var x = baz.create(56)
 
+  proc foo() =
+    ## This is a docstring
+    echo "bar"
diff --git a/tests/metatype/tstaticparammacro.nim b/tests/metatype/tstaticparammacro.nim
index bd3295874..02021185f 100644
--- a/tests/metatype/tstaticparammacro.nim
+++ b/tests/metatype/tstaticparammacro.nim
@@ -14,7 +14,6 @@ AST b
 20Test
 20
 '''
-  disabled: true
 """
 
 import macros
@@ -26,7 +25,7 @@ type
 
 const data: Tconfig = (@["aa", "bb"], @[11, 22])
 
-macro mymacro(data: static[TConfig]) =
+macro mymacro(data: static[TConfig]): untyped =
   echo "letters"
   for s in items(data.letters):
     echo s
@@ -44,10 +43,10 @@ const
   a : Ta = @[(11, 22), (33, 44)]
   b : Tb = (@[55,66], @[77, 88])
 
-macro mA(data: static[Ta]) =
+macro mA(data: static[Ta]): untyped =
   echo "AST a \n", repr(data)
 
-macro mB(data: static[Tb]) =
+macro mB(data: static[Tb]): untyped =
   echo "AST b \n", repr(data)
   echo data.e[0]
 
@@ -57,13 +56,15 @@ mB(b)
 type
   Foo[N: static[int], Z: static[string]] = object
 
-macro staticIntMacro(f: static[int]) = echo f
+macro staticIntMacro(f: static[int]): untyped =
+  echo f
+
 staticIntMacro 10
 
 var
   x: Foo[20, "Test"]
 
-macro genericMacro[N; Z: static[string]](f: Foo[N, Z], ll = 3, zz = 12) =
+macro genericMacro[N; Z: static[string]](f: Foo[N, Z], ll = 3, zz = 12): untyped =
   echo N, Z
 
 genericMacro x
diff --git a/tests/metatype/ttypeselectors.nim b/tests/metatype/ttypeselectors.nim
index c29fd15ce..1209fe78f 100644
--- a/tests/metatype/ttypeselectors.nim
+++ b/tests/metatype/ttypeselectors.nim
@@ -1,4 +1,9 @@
-import macros
+discard """
+output: "8\n8\n4"
+"""
+
+import
+  macros, typetraits
 
 template selectType(x: int): typeDesc =
   when x < 10:
@@ -11,6 +16,9 @@ template simpleTypeTempl: typeDesc =
 
 macro typeFromMacro: typedesc = string
 
+# The tests below check that the result variable of the
+# selected type matches the literal types in the code:
+
 proc t1*(x: int): simpleTypeTempl() =
   result = "test"
 
@@ -37,3 +45,57 @@ proc t6*(x: type(t3(0))): type(t1(0)) =
 proc t7*(x: int): type($x) =
   result = "test"
 
+# This is a more compicated example involving a type
+# selection through a macro:
+# https://github.com/nim-lang/Nim/issues/7230
+
+macro getBase*(bits: static[int]): untyped =
+  if bits >= 128:
+    result = newTree(nnkBracketExpr, ident("MpUintBase"), ident("uint64"))
+  else:
+    result = newTree(nnkBracketExpr, ident("MpUintBase"), ident("uint32"))
+
+type
+  BaseUint* = SomeUnsignedInt or MpUintBase
+
+  MpUintBase*[T] = object
+      lo*, hi*: T
+
+  ## This gets type mismatch
+  MpUint*[bits: static[int]] = getBase(bits)
+
+var m1: MpUint[128]
+var m2: MpUint[64]
+var m3: getBase(32)
+
+static:
+  # assert m1.type.name == "MpUintBase[uint64]"
+  assert m1.lo.type.name == "uint64"
+  assert m2.lo.type.name == "uint32"
+  assert m3.type.name == "MpUintBase[system.uint32]"
+
+# https://github.com/nim-lang/Nim/issues/7379
+
+import macros, typetraits
+
+macro works(): untyped =
+  result = getType(int64)
+
+macro fails(bits: static[int]): untyped =
+  if bits > 64:
+    result = getType(int64)
+  else:
+    result = getType(int32)
+
+type
+  Foo*[bits: static[int]] = works()
+  Bar*[bits: static[int]] = fails(bits)
+
+var a: Foo[16]
+var b: Bar[256]
+var c: Bar[32]
+
+echo sizeof(a)
+echo sizeof(b)
+echo sizeof(c)
+
diff --git a/tests/metatype/typeclassinference.nim b/tests/metatype/typeclassinference.nim
index 8b99eb501..c845e04f7 100644
--- a/tests/metatype/typeclassinference.nim
+++ b/tests/metatype/typeclassinference.nim
@@ -1,7 +1,6 @@
 discard """
   errormsg: "type mismatch: got <string> but expected 'ptr'"
   line: 20
-  disabled: true
 """
 
 import typetraits
@@ -12,7 +11,7 @@ type
 var x = Vec([1, 2, 3])
 
 static:
-  assert x.type.name == "Vec[static[int](3), int]"
+  assert x.type.name == "Vec[3, system.int]"
 
 var str1: string = "hello, world!"
 var ptr1: ptr = addr(str1)
diff --git a/tests/misc/tidentconcatenations.nim b/tests/misc/tidentconcatenations.nim
new file mode 100644
index 000000000..302c51d87
--- /dev/null
+++ b/tests/misc/tidentconcatenations.nim
@@ -0,0 +1,32 @@
+type
+  Hash*[bits: static[int]] = object
+    data*: array[bits div 8, uint8]
+
+{.emit: """
+
+void sha_256(void* input, int input_len, void* output, int output_len) {}
+void sha_512(void* input, int input_len, void* output, int output_len) {}
+
+void keccak_256(void* input, int input_len, void* output, int output_len) {}
+void keccak_512(void* input, int input_len, void* output, int output_len) {}
+
+""".}
+
+template defineKeccak(bits: untyped) =
+  proc `extKeccak bits`(output: pointer, outSize: csize, input: pointer, inputSize: csize) {.nodecl, importc: "keccak_" & astToStr(bits).}
+
+template defineSha(bits: static[int]) =
+  proc `extSha bits`(output: pointer, outSize: csize, input: pointer, inputSize: csize) {.nodecl, importc: "sha_" & astToStr(bits).}
+
+template defineHashProcs(bits) =
+  defineSha(bits)
+  defineKeccak(bits)
+
+defineHashProcs(256)
+defineHashProcs(512)
+
+extSha256(nil, 0, nil, 0)
+extSha512(nil, 0, nil, 0)
+extKeccak256(nil, 0, nil, 0)
+extKeccak512(nil, 0, nil, 0)
+
diff --git a/tests/statictypes/tcryptodigest.nim b/tests/statictypes/tcryptodigest.nim
new file mode 100644
index 000000000..c78a4188a
--- /dev/null
+++ b/tests/statictypes/tcryptodigest.nim
@@ -0,0 +1,44 @@
+discard """
+  output: "Digest[128]\nDigest[256]"
+"""
+
+import typetraits
+
+type
+  Digest[bits: static[int]] = object
+    data: array[bits div 8, byte]
+
+  ContextKind = enum
+    A, B, C
+
+  HashingContext[bits: static[int], kind: static[ContextKind]] = object
+    ctx: array[bits div 8, byte]
+
+  Hash128 = HashingContext[128, A]
+  Hash256 = HashingContext[256, B]
+
+  HMAC[HashType] = object
+    h: HashType
+
+proc init(c: var HashingContext) = discard
+proc update(c: var HashingContext, data: ptr byte, dataLen: uint) = discard
+proc finish(c: var HashingContext): Digest[c.bits] = discard
+
+proc digest(T: typedesc, data: ptr byte, dataLen: uint): Digest[T.bits] =
+  mixin init, update, finish
+
+  var ctx: T
+  ctx.init()
+  ctx.update(data, dataLen)
+  result = ctx.finish()
+
+var h = Hash128.digest(nil, 0)
+echo h.type.name
+
+proc finish(hmac: var HMAC): Digest[HMAC.HashType.bits] =
+  discard
+
+var hm: HMAC[Hash256]
+var d = hm.finish
+echo d.type.name
+
diff --git a/tests/statictypes/tstaticimportcpp.nim b/tests/statictypes/tstaticimportcpp.nim
index e13cc36b4..0cbbc1df6 100644
--- a/tests/statictypes/tstaticimportcpp.nim
+++ b/tests/statictypes/tstaticimportcpp.nim
@@ -1,9 +1,9 @@
 discard """
 targets: "cpp"
-output: "[0, 0, 10, 0]\n5\n1.2\n15\ntest"
+output: "[0, 0, 10, 0]\n5\n1.2\n15\ntest\n[0, 0, 20, 0]"
 """
 
-{.emit: """
+{.emit: """/*TYPESECTION*/
 
 template <int N, class T>
 struct GenericIntType {
@@ -51,3 +51,9 @@ echo c.field
 echo d.field
 echo e.field
 
+proc plus(a, b: GenInt4): GenInt4 =
+  for i in 0 ..< result.data.len:
+    result.data[i] = a.data[i] + b.data[i]
+
+echo plus(a, a).data
+
diff --git a/tests/stdlib/tjsonmacro.nim b/tests/stdlib/tjsonmacro.nim
index a69b03426..e8740c591 100644
--- a/tests/stdlib/tjsonmacro.nim
+++ b/tests/stdlib/tjsonmacro.nim
@@ -315,6 +315,21 @@ when isMainModule:
     doAssert noYearDeser.year.isNone
     doAssert noYearDeser.engine.name == "V8"
 
+    # Issue #7433
+    type
+      Obj2 = object
+        n1: int
+        n2: Option[string]
+        n3: bool
+
+    var j = %*[ { "n1": 4, "n2": "ABC", "n3": true },
+                { "n1": 1, "n3": false },
+                { "n1": 1, "n2": "XYZ", "n3": false } ]
+
+    let jDeser = j.to(seq[Obj2])
+    doAssert jDeser[0].n2.get() == "ABC"
+    doAssert jDeser[1].n2.isNone()
+
   # Table[T, Y] support.
   block:
     type
diff --git a/tests/stdlib/ttimes.nim b/tests/stdlib/ttimes.nim
index ae056a79f..8efc50086 100644
--- a/tests/stdlib/ttimes.nim
+++ b/tests/stdlib/ttimes.nim
@@ -367,4 +367,12 @@ suite "ttimes":
     check $(dt - 1.months) == "2017-02-15T00:00:00+00:00"
     dt = initDateTime(31, mMar, 2017, 00, 00, 00, utc())
     # This happens due to monthday overflow. It's consistent with Phobos.
-    check $(dt - 1.months) == "2017-03-03T00:00:00+00:00"
\ No newline at end of file
+    check $(dt - 1.months) == "2017-03-03T00:00:00+00:00"
+
+  test "compare datetimes":
+    var dt1 = now()
+    var dt2 = dt1
+    check dt1 == dt2
+    check dt1 <= dt2
+    dt2 = dt2 + 1.seconds
+    check dt1 < dt2
diff --git a/tests/system/alloc.nim b/tests/system/talloc.nim
index 7abefec2a..18396041d 100644
--- a/tests/system/alloc.nim
+++ b/tests/system/talloc.nim
@@ -8,7 +8,7 @@ x.dealloc()
 
 x = createU(int, 3)
 assert x != nil
-x.free()
+x.dealloc()
 
 x = create(int, 4)
 assert cast[ptr array[4, int]](x)[0] == 0
@@ -18,7 +18,7 @@ assert cast[ptr array[4, int]](x)[3] == 0
 
 x = x.resize(4)
 assert x != nil
-x.free()
+x.dealloc()
 
 x = cast[ptr int](allocShared(100))
 assert x != nil
@@ -26,7 +26,7 @@ deallocShared(x)
 
 x = createSharedU(int, 3)
 assert x != nil
-x.freeShared()
+x.deallocShared()
 
 x = createShared(int, 3)
 assert x != nil
@@ -37,7 +37,7 @@ assert cast[ptr array[3, int]](x)[2] == 0
 assert x != nil
 x = cast[ptr int](x.resizeShared(2))
 assert x != nil
-x.freeShared()
+x.deallocShared()
 
 x = create(int, 10)
 assert x != nil
@@ -49,4 +49,9 @@ x = createShared(int, 1)
 assert x != nil
 x = x.resizeShared(1)
 assert x != nil
-x.freeShared()
+x.deallocShared()
+
+x = cast[ptr int](alloc0(125 shl 23))
+dealloc(x)
+x = cast[ptr int](alloc0(126 shl 23))
+dealloc(x)
diff --git a/tests/system/talloc2.nim b/tests/system/talloc2.nim
new file mode 100644
index 000000000..c8cab78a1
--- /dev/null
+++ b/tests/system/talloc2.nim
@@ -0,0 +1,37 @@
+const
+  nmax = 2*1024*1024*1024
+
+proc test(n: int) =
+  var a = alloc0(9999)
+  var t = cast[ptr UncheckedArray[int8]](alloc(n))
+  var b = alloc0(9999)
+  t[0] = 1
+  t[1] = 2
+  t[n-2] = 3
+  t[n-1] = 4
+  dealloc(a)
+  dealloc(t)
+  dealloc(b)
+
+# allocator adds 48 bytes to BigChunk
+# BigChunk allocator edges at 2^n * (1 - s) for s = [1..32]/64
+proc test2(n: int) =
+  let d = n div 256  # cover edges and more
+  for i in countdown(128,1):
+    for j in [-4096, -64, -49, -48, -47, -32, 0, 4096]:
+      let b = n + j - i*d
+      if b>0 and b<=nmax:
+        test(b)
+        #echo b, ": ", getTotalMem(), " ", getOccupiedMem(), " ", getFreeMem()
+
+proc test3 =
+  var n = 1
+  while n <= nmax:
+    test2(n)
+    n *= 2
+  n = nmax
+  while n >= 1:
+    test2(n)
+    n = n div 2
+
+test3()
diff --git a/tests/system/io.nim b/tests/system/tio.nim
index 3d4df806b..3d4df806b 100644
--- a/tests/system/io.nim
+++ b/tests/system/tio.nim
diff --git a/tests/system/params.nim b/tests/system/tparams.nim
index 1358212f2..1358212f2 100644
--- a/tests/system/params.nim
+++ b/tests/system/tparams.nim
diff --git a/tests/system/tsystem_misc.nim b/tests/system/tsystem_misc.nim
index ce36895a1..85228e9e7 100644
--- a/tests/system/tsystem_misc.nim
+++ b/tests/system/tsystem_misc.nim
@@ -1,5 +1,17 @@
 discard """
-  output:""
+  output:'''1
+1
+2
+3
+11
+12
+13
+14
+15
+2
+3
+4
+'''
 """
 
 # check high/low implementations
@@ -20,3 +32,18 @@ doAssert high(float64) > low(float64)
 # bug #6710
 var s = @[1]
 s.delete(0)
+
+
+proc foo(a: openArray[int]) =
+  for x in a: echo x
+
+foo(toOpenArray([1, 2, 3], 0, 0))
+
+foo(toOpenArray([1, 2, 3], 0, 2))
+
+var arr: array[8..12, int] = [11, 12, 13, 14, 15]
+
+foo(toOpenArray(arr, 8, 12))
+
+var seqq = @[1, 2, 3, 4, 5]
+foo(toOpenArray(seqq, 1, 3))
diff --git a/tests/varres/tvarres1.nim b/tests/varres/tvarres1.nim
index 849805768..5a5247142 100644
--- a/tests/varres/tvarres1.nim
+++ b/tests/varres/tvarres1.nim
@@ -1,7 +1,7 @@
 discard """
   file: "tvarres1.nim"
   line: 12
-  errormsg: "address of 'bla' may not escape its stack frame"
+  errormsg: "'bla' escapes its stack frame; context: 'bla'"
 """
 
 var
diff --git a/tests/varres/tvarres_via_forwarding.nim b/tests/varres/tvarres_via_forwarding.nim
new file mode 100644
index 000000000..8fd3dfcfd
--- /dev/null
+++ b/tests/varres/tvarres_via_forwarding.nim
@@ -0,0 +1,12 @@
+discard """
+  line: 10
+  errormsg: "'y' escapes its stack frame; context: 'forward(y)'"
+"""
+
+proc forward(x: var int): var int = result = x
+
+proc foo(): var int =
+  var y = 9
+  result = forward(y)
+
+echo foo()
diff --git a/tests/varres/twrong_parameter.nim b/tests/varres/twrong_parameter.nim
new file mode 100644
index 000000000..8a363dd19
--- /dev/null
+++ b/tests/varres/twrong_parameter.nim
@@ -0,0 +1,16 @@
+discard """
+  line: 10
+  errormsg: "'x' is not the first parameter; context: 'x.field[0]'"
+"""
+
+type
+  MyObject = object
+    field: array[2, int]
+
+proc forward(abc: int; x: var MyObject): var int = result = x.field[0]
+
+proc foo(): var int =
+  var y: MyObject
+  result = forward(45, y)
+
+echo foo()
diff --git a/todo.txt b/todo.txt
deleted file mode 100644
index 32bc32630..000000000
--- a/todo.txt
+++ /dev/null
@@ -1,71 +0,0 @@
-version 1.0 battle plan
-=======================
-
-- let 'doAssert' analyse the expressions and produce more helpful output
-- fix "high priority" bugs
-- try to fix as many compiler crashes as reasonable
-
-
-Not critical for 1.0
-====================
-
-- introduce ``nkStmtListExpr`` for template/macro invokations to produce
-  better stack traces
-- make 'break' not leave named blocks
-- make FlowVar compatible to Futures
-- make 'not nil' the default (produce warnings instead of errors for
-  a smooth migration path)
-- case objects needs to be safe and need to support pattern matching
-
-- find a solution for the  x.f[T](y)  gotcha
-- implement ``.delegate`` for .experimental
-- annotation support for getType()
-- make '--implicitStatic:on' the default; then we can also clean up the
-  'static[T]' mess in the compiler!
-- ``not`` or ``~`` for the effects system
-- figure out why C++ bootstrapping is so much slower
-- make 'nil' work for 'add':
-  - resizeString
-  - incrSeq
-  - addChar
-- pragmas need 'bindSym' support
-- pragmas need re-work: 'push' is dangerous, 'hasPragma' does not work
-  reliably with user-defined pragmas
-- we need a magic thisModule symbol
-- optimize 'genericReset'; 'newException' leads to code bloat
-
-- prevent 'alloc(TypeWithGCedMemory)'?
-- map ``string`` and ``seq`` to ``std::string`` and ``std::vector``
-- macro support for '='; bind '=' to a memory region
-- macros as type pragmas
-
-
-Bugs
-====
-
-- VM: Pegs do not work at compile-time
-- blocks can "export" an identifier but the CCG generates {} for them ...
-
-
-GC
-==
-
-- resizing of strings/sequences could take into account the memory that
-  is allocated
-
-
-Concurrency
-===========
-
-- implement 'foo[1..4] = spawn(f[4..7])'
-
-Low priority:
-- support for exception propagation? (hard to implement)
-- the copying of the 'ref Promise' into the thead local storage only
-  happens to work due to the write barrier's implementation
-
-
-CGEN
-====
-- codegen should use "NIM_CAST" macro and respect aliasing rules for GCC
-- ``restrict`` pragma + backend support
diff --git a/web/website.ini b/web/website.ini
index 44f01c784..83a014821 100644
--- a/web/website.ini
+++ b/web/website.ini
@@ -58,7 +58,7 @@ srcdoc2: "pure/memfiles;pure/subexes;pure/collections/critbits"
 srcdoc2: "deprecated/pure/asyncio;deprecated/pure/actors;core/locks;core/rlocks;pure/oids;pure/endians;pure/uri"
 srcdoc2: "pure/nimprof;pure/unittest;packages/docutils/highlite"
 srcdoc2: "packages/docutils/rst;packages/docutils/rstast"
-srcdoc2: "packages/docutils/rstgen;pure/logging;pure/options;pure/asyncdispatch;pure/asyncnet"
+srcdoc2: "packages/docutils/rstgen;pure/logging;pure/options;pure/asyncdispatch;pure/asyncnet;pure/asyncstreams;pure/asyncfutures"
 srcdoc2: "pure/nativesockets;pure/asynchttpserver;pure/net;pure/selectors;pure/future"
 srcdoc2: "deprecated/pure/ftpclient;pure/collections/chains"
 srcdoc2: "pure/asyncfile;pure/asyncftpclient;pure/lenientops"