summary refs log tree commit diff stats
diff options
context:
space:
mode:
-rw-r--r--compiler/ast.nim5
-rw-r--r--compiler/ccgexprs.nim7
-rw-r--r--compiler/cgen.nim2
-rw-r--r--compiler/condsyms.nim1
-rw-r--r--compiler/msgs.nim1
-rw-r--r--compiler/semcall.nim5
-rw-r--r--compiler/semdata.nim3
-rw-r--r--compiler/semexprs.nim62
-rw-r--r--compiler/semfold.nim9
-rw-r--r--compiler/semgnrc.nim23
-rw-r--r--compiler/seminst.nim2
-rw-r--r--compiler/semmagic.nim34
-rw-r--r--compiler/semstmts.nim2
-rw-r--r--compiler/semtempl.nim51
-rw-r--r--compiler/semtypes.nim35
-rw-r--r--compiler/sigmatch.nim4
-rw-r--r--doc/manual/generics.txt11
-rw-r--r--doc/manual/pragmas.txt15
-rw-r--r--doc/manual/types.txt24
-rw-r--r--lib/system.nim24
-rw-r--r--tests/ccgbugs/tnocodegen_for_compiletime.nim9
-rw-r--r--tests/generics/mbind_bracket.nim17
-rw-r--r--tests/generics/tbind_bracket.nim20
-rw-r--r--tests/generics/tthread_generic.nim2
-rw-r--r--tests/metatype/ttypedesc1.nim2
-rw-r--r--tests/types/tauto_excessive.nim20
-rw-r--r--todo.txt1
-rw-r--r--web/news.txt55
28 files changed, 356 insertions, 90 deletions
diff --git a/compiler/ast.nim b/compiler/ast.nim
index 860bf67e8..be11e80be 100644
--- a/compiler/ast.nim
+++ b/compiler/ast.nim
@@ -477,6 +477,8 @@ type
                       # wildcard type.
     tfHasAsgn         # type has overloaded assignment operator
     tfBorrowDot       # distinct type borrows '.'
+    tfTriggersCompileTime # uses the NimNode type which make the proc
+                          # implicitly '.compiletime'
 
   TTypeFlags* = set[TTypeFlag]
 
@@ -1380,6 +1382,9 @@ proc propagateToOwner*(owner, elem: PType) =
       o2.flags.incl tfHasAsgn
       owner.flags.incl tfHasAsgn
 
+  if tfTriggersCompileTime in elem.flags:
+    owner.flags.incl tfTriggersCompileTime
+
   if owner.kind notin {tyProc, tyGenericInst, tyGenericBody,
                        tyGenericInvocation, tyPtr}:
     let elemB = elem.skipTypes({tyGenericInst})
diff --git a/compiler/ccgexprs.nim b/compiler/ccgexprs.nim
index 54063229f..32fc76470 100644
--- a/compiler/ccgexprs.nim
+++ b/compiler/ccgexprs.nim
@@ -1741,6 +1741,8 @@ proc genMagicExpr(p: BProc, e: PNode, d: var TLoc, op: TMagic) =
   of mEcho: genEcho(p, e[1].skipConv)
   of mArrToSeq: genArrToSeq(p, e, d)
   of mNLen..mNError, mSlurp..mQuoteAst:
+    echo "from here ", p.prc.name.s, " ", p.prc.info
+    writestacktrace()
     localError(e.info, errXMustBeCompileTime, e.sons[0].sym.name.s)
   of mSpawn:
     let n = lowerings.wrapProcForSpawn(p.module.module, e, e.typ, nil, nil)
@@ -1973,6 +1975,9 @@ proc expr(p: BProc, n: PNode, d: var TLoc) =
         genProc(p.module, sym)
       putLocIntoDest(p, d, sym.loc)
     of skProc, skConverter, skIterators:
+      if sfCompileTime in sym.flags:
+        localError(n.info, "request to generate code for .compileTime proc: " &
+           sym.name.s)
       genProc(p.module, sym)
       if sym.loc.r == nil or sym.loc.t == nil:
         internalError(n.info, "expr: proc not init " & sym.name.s)
@@ -2126,7 +2131,7 @@ proc expr(p: BProc, n: PNode, d: var TLoc) =
       # due to a bug/limitation in the lambda lifting, unused inner procs
       # are not transformed correctly. We work around this issue (#411) here
       # by ensuring it's no inner proc (owner is a module):
-      if prc.skipGenericOwner.kind == skModule:
+      if prc.skipGenericOwner.kind == skModule and sfCompileTime notin prc.flags:
         if (optDeadCodeElim notin gGlobalOptions and
             sfDeadCodeElim notin getModule(prc).flags) or
             ({sfExportc, sfCompilerProc} * prc.flags == {sfExportc}) or
diff --git a/compiler/cgen.nim b/compiler/cgen.nim
index 3f88e63ee..f63134b66 100644
--- a/compiler/cgen.nim
+++ b/compiler/cgen.nim
@@ -1110,7 +1110,7 @@ proc rawNewModule(module: PSym, filename: string): BModule =
 
 proc nullify[T](arr: var T) =
   for i in low(arr)..high(arr):
-    arr[i] = nil
+    arr[i] = Rope(nil)
 
 proc resetModule*(m: BModule) =
   # between two compilations in CAAS mode, we can throw
diff --git a/compiler/condsyms.nim b/compiler/condsyms.nim
index 31bd85a06..60e8f2826 100644
--- a/compiler/condsyms.nim
+++ b/compiler/condsyms.nim
@@ -92,3 +92,4 @@ proc initDefines*() =
   defineSymbol("nimvarargstyped")
   defineSymbol("nimtypedescfixed")
   defineSymbol("nimKnowsNimvm")
+  defineSymbol("nimArrIdx")
diff --git a/compiler/msgs.nim b/compiler/msgs.nim
index 8b3b11f4a..c5bc44664 100644
--- a/compiler/msgs.nim
+++ b/compiler/msgs.nim
@@ -514,6 +514,7 @@ const
     {low(TNoteKind)..high(TNoteKind)} - {warnShadowIdent, warnUninit,
                                          warnProveField, warnProveIndex,
                                          warnGcUnsafe,
+                                         hintPath, hintConf,
                                          hintDependency,
                                          hintExecuting,
                                          hintCodeBegin, hintCodeEnd,
diff --git a/compiler/semcall.nim b/compiler/semcall.nim
index 2f181b5f3..f9fadeec7 100644
--- a/compiler/semcall.nim
+++ b/compiler/semcall.nim
@@ -308,7 +308,10 @@ proc semResolvedCall(c: PContext, n: PNode, x: TCandidate): PNode =
   let gp = finalCallee.ast.sons[genericParamsPos]
   if gp.kind != nkEmpty:
     if x.calleeSym.kind notin {skMacro, skTemplate}:
-      finalCallee = generateInstance(c, x.calleeSym, x.bindings, n.info)
+      if x.calleeSym.magic in {mArrGet, mArrPut}:
+        finalCallee = x.calleeSym
+      else:
+        finalCallee = generateInstance(c, x.calleeSym, x.bindings, n.info)
     else:
       # For macros and templates, the resolved generic params
       # are added as normal params.
diff --git a/compiler/semdata.nim b/compiler/semdata.nim
index 345a8c0d1..e6456293c 100644
--- a/compiler/semdata.nim
+++ b/compiler/semdata.nim
@@ -45,7 +45,8 @@ type
   TExprFlag* = enum
     efLValue, efWantIterator, efInTypeof,
     efWantStmt, efAllowStmt, efDetermineType,
-    efAllowDestructor, efWantValue, efOperand, efNoSemCheck
+    efAllowDestructor, efWantValue, efOperand, efNoSemCheck,
+    efNoProcvarCheck
   TExprFlags* = set[TExprFlag]
 
   TTypeAttachedOp* = enum
diff --git a/compiler/semexprs.nim b/compiler/semexprs.nim
index 3ff04a4fc..0e1d52fd4 100644
--- a/compiler/semexprs.nim
+++ b/compiler/semexprs.nim
@@ -52,7 +52,7 @@ proc semExprWithType(c: PContext, n: PNode, flags: TExprFlags = {}): PNode =
     result.typ = errorType(c)
   else:
     # XXX tyGenericInst here?
-    semProcvarCheck(c, result)
+    if efNoProcvarCheck notin flags: semProcvarCheck(c, result)
     if result.typ.kind == tyVar: result = newDeref(result)
     semDestructorCheck(c, result, flags)
 
@@ -452,18 +452,18 @@ proc changeType(n: PNode, newType: PType, check: bool) =
     let tup = newType.skipTypes({tyGenericInst})
     if tup.kind != tyTuple:
       if tup.kind == tyObject: return
-      internalError(n.info, "changeType: no tuple type for constructor")
+      globalError(n.info, "no tuple type for constructor")
     elif sonsLen(n) > 0 and n.sons[0].kind == nkExprColonExpr:
       # named tuple?
       for i in countup(0, sonsLen(n) - 1):
         var m = n.sons[i].sons[0]
         if m.kind != nkSym:
-          internalError(m.info, "changeType(): invalid tuple constr")
+          globalError(m.info, "invalid tuple constructor")
           return
         if tup.n != nil:
           var f = getSymFromList(tup.n, m.sym.name)
           if f == nil:
-            internalError(m.info, "changeType(): invalid identifier")
+            globalError(m.info, "unknown identifier: " & m.sym.name.s)
             return
           changeType(n.sons[i].sons[1], f.typ, check)
         else:
@@ -1156,7 +1156,7 @@ proc semSubscript(c: PContext, n: PNode, flags: TExprFlags): PNode =
     result.add(x[0])
     return
   checkMinSonsLen(n, 2)
-  n.sons[0] = semExprWithType(c, n.sons[0])
+  n.sons[0] = semExprWithType(c, n.sons[0], {efNoProcvarCheck})
   let arr = skipTypes(n.sons[0].typ, {tyGenericInst, tyVar, tyPtr, tyRef})
   case arr.kind
   of tyArray, tyOpenArray, tyVarargs, tyArrayConstr, tySequence, tyString,
@@ -1196,7 +1196,17 @@ proc semSubscript(c: PContext, n: PNode, flags: TExprFlags): PNode =
       localError(n.info, errIndexTypesDoNotMatch)
     result = n
   else:
-    c.p.bracketExpr = n.sons[0]
+    let s = if n.sons[0].kind == nkSym: n.sons[0].sym
+            elif n[0].kind in nkSymChoices: n.sons[0][0].sym
+            else: nil
+    if s != nil and s.kind in {skProc, skMethod, skConverter}+skIterators:
+      # type parameters: partial generic specialization
+      n.sons[0] = semSymGenericInstantiation(c, n.sons[0], s)
+      result = explicitGenericInstantiation(c, n, s)
+    elif s != nil and s.kind == skType:
+      result = symNodeFromType(c, semTypeNode(c, n, nil), n.info)
+    else:
+      c.p.bracketExpr = n.sons[0]
 
 proc semArrayAccess(c: PContext, n: PNode, flags: TExprFlags): PNode =
   let oldBracketExpr = c.p.bracketExpr
@@ -1250,7 +1260,7 @@ proc asgnToResultVar(c: PContext, n, le, ri: PNode) {.inline.} =
 template resultTypeIsInferrable(typ: PType): expr =
   typ.isMetaType and typ.kind != tyTypeDesc
 
-proc semAsgn(c: PContext, n: PNode): PNode =
+proc semAsgn(c: PContext, n: PNode; mode=asgnNormal): PNode =
   checkSonsLen(n, 2)
   var a = n.sons[0]
   case a.kind
@@ -1273,12 +1283,15 @@ proc semAsgn(c: PContext, n: PNode): PNode =
     # --> `[]=`(a, i, x)
     let oldBracketExpr = c.p.bracketExpr
     a = semSubscript(c, a, {efLValue})
-    if a == nil:
+    if a == nil and mode != noOverloadedSubscript:
       result = buildOverloadedSubscripts(n.sons[0], getIdent"[]=")
       add(result, n[1])
       result = semExprNoType(c, result)
       c.p.bracketExpr = oldBracketExpr
       return result
+    elif a == nil:
+      localError(n.info, "could not resolve: " & $n[0])
+      return n
     c.p.bracketExpr = oldBracketExpr
   of nkCurlyExpr:
     # a{i} = x -->  `{}=`(a, i, x)
@@ -1323,7 +1336,8 @@ proc semAsgn(c: PContext, n: PNode): PNode =
           typeMismatch(n, lhs.typ, rhs.typ)
 
     n.sons[1] = fitNode(c, le, rhs)
-    if tfHasAsgn in lhs.typ.flags and not lhsIsResult:
+    if tfHasAsgn in lhs.typ.flags and not lhsIsResult and
+        mode != noOverloadedAsgn:
       return overloadedAsgn(c, lhs, n.sons[1])
 
     fixAbstractType(c, n)
@@ -1715,6 +1729,9 @@ proc semMagic(c: PContext, n: PNode, s: PSym, flags: TExprFlags): PNode =
   of mTypeOf:
     checkSonsLen(n, 2)
     result = semTypeOf(c, n.sons[1])
+  #of mArrGet: result = semArrGet(c, n, flags)
+  #of mArrPut: result = semArrPut(c, n, flags)
+  #of mAsgn: result = semAsgnOpr(c, n)
   of mDefined: result = semDefined(c, setMs(n, s), false)
   of mDefinedInScope: result = semDefined(c, setMs(n, s), true)
   of mCompiles: result = semCompiles(c, setMs(n, s), flags)
@@ -2066,6 +2083,19 @@ proc semExport(c: PContext, n: PNode): PNode =
     c.module.ast.add x
   result = n
 
+proc shouldBeBracketExpr(n: PNode): bool =
+  assert n.kind in nkCallKinds
+  let a = n.sons[0]
+  if a.kind in nkCallKinds:
+    let b = a[0]
+    if b.kind in nkSymChoices:
+      for i in 0..<b.len:
+        if b[i].sym.magic == mArrGet:
+          let be = newNodeI(nkBracketExpr, n.info)
+          for i in 1..<a.len: be.add(a[i])
+          n.sons[0] = be
+          return true
+
 proc setGenericParams(c: PContext, n: PNode) =
   for i in 1 .. <n.len:
     n[i].typ = semTypeNode(c, n[i], nil)
@@ -2173,7 +2203,8 @@ proc semExpr(c: PContext, n: PNode, flags: TExprFlags = {}): PNode =
       else:
         #liMessage(n.info, warnUser, renderTree(n));
         result = semIndirectOp(c, n, flags)
-    elif n[0].kind == nkBracketExpr and isSymChoice(n[0][0]):
+    elif (n[0].kind == nkBracketExpr or shouldBeBracketExpr(n)) and
+        isSymChoice(n[0][0]):
       # indirectOp can deal with explicit instantiations; the fixes
       # the 'newSeq[T](x)' bug
       setGenericParams(c, n.sons[0])
@@ -2194,16 +2225,7 @@ proc semExpr(c: PContext, n: PNode, flags: TExprFlags = {}): PNode =
         result = semExpr(c, result, flags)
   of nkBracketExpr:
     checkMinSonsLen(n, 1)
-    var s = qualifiedLookUp(c, n.sons[0], {checkUndeclared})
-    if (s != nil and s.kind in {skProc, skMethod, skConverter}+skIterators) or
-        n[0].kind in nkSymChoices:
-      # type parameters: partial generic specialization
-      n.sons[0] = semSymGenericInstantiation(c, n.sons[0], s)
-      result = explicitGenericInstantiation(c, n, s)
-    elif s != nil and s.kind in {skType}:
-      result = symNodeFromType(c, semTypeNode(c, n, nil), n.info)
-    else:
-      result = semArrayAccess(c, n, flags)
+    result = semArrayAccess(c, n, flags)
   of nkCurlyExpr:
     result = semExpr(c, buildOverloadedSubscripts(n, getIdent"{}"), flags)
   of nkPragmaExpr:
diff --git a/compiler/semfold.nim b/compiler/semfold.nim
index 70276a6d4..5fe4e3299 100644
--- a/compiler/semfold.nim
+++ b/compiler/semfold.nim
@@ -430,17 +430,10 @@ proc evalOp(m: TMagic, n, a, b, c: PNode): PNode =
   of mCompileOptionArg:
     result = newIntNodeT(ord(
       testCompileOptionArg(getStr(a), getStr(b), n.info)), n)
-  of mNewString, mNewStringOfCap,
-     mExit, mInc, ast.mDec, mEcho, mSwap, mAppendStrCh,
-     mAppendStrStr, mAppendSeqElem, mSetLengthStr, mSetLengthSeq,
-     mParseExprToAst, mParseStmtToAst, mExpandToAst, mTypeTrait, mDotDot,
-     mNLen..mNError, mEqRef, mSlurp, mStaticExec, mNGenSym, mSpawn,
-     mParallel, mPlugin, mGetTypeInfo, mTypeOf:
-    discard
   of mEqProc:
     result = newIntNodeT(ord(
         exprStructuralEquivalent(a, b, strictSymEquality=true)), n)
-  else: internalError(a.info, "evalOp(" & $m & ')')
+  else: discard
 
 proc getConstIfExpr(c: PSym, n: PNode): PNode =
   result = nil
diff --git a/compiler/semgnrc.nim b/compiler/semgnrc.nim
index e3b598919..ed0244b0c 100644
--- a/compiler/semgnrc.nim
+++ b/compiler/semgnrc.nim
@@ -251,6 +251,29 @@ proc semGenericStmt(c: PContext, n: PNode,
     let flags = if mixinContext: flags+{withinMixin} else: flags
     for i in countup(first, sonsLen(result) - 1):
       result.sons[i] = semGenericStmt(c, result.sons[i], flags, ctx)
+  of nkBracketExpr, nkCurlyExpr:
+    result = newNodeI(nkCall, n.info)
+    result.add newIdentNode(getIdent(if n.kind == nkBracketExpr:"[]" else:"{}"),
+                            n.info)
+    for i in 0 ..< n.len: result.add(n[i])
+    result = semGenericStmt(c, result, flags, ctx)
+  of nkAsgn, nkFastAsgn:
+    checkSonsLen(n, 2)
+    let a = n.sons[0]
+    let b = n.sons[1]
+
+    let k = a.kind
+    case k
+    of nkBracketExpr, nkCurlyExpr:
+      result = newNodeI(nkCall, n.info)
+      result.add newIdentNode(getIdent(if k == nkBracketExpr:"[]=" else:"{}="),
+                              n.info)
+      for i in 0 ..< a.len: result.add(a[i])
+      result.add(b)
+      result = semGenericStmt(c, result, flags, ctx)
+    else:
+      for i in countup(0, sonsLen(n) - 1):
+        result.sons[i] = semGenericStmt(c, n.sons[i], flags, ctx)
   of nkIfStmt:
     for i in countup(0, sonsLen(n)-1):
       n.sons[i] = semGenericStmtScope(c, n.sons[i], flags, ctx)
diff --git a/compiler/seminst.nim b/compiler/seminst.nim
index 42a39d0df..64e3e8cb8 100644
--- a/compiler/seminst.nim
+++ b/compiler/seminst.nim
@@ -246,6 +246,8 @@ proc generateInstance(c: PContext, fn: PSym, pt: TIdTable,
     inc i
   pushProcCon(c, result)
   instantiateProcType(c, pt, result, info)
+  if tfTriggersCompileTime in result.typ.flags:
+    incl(result.flags, sfCompileTime)
   n.sons[genericParamsPos] = ast.emptyNode
   var oldPrc = genericCacheGet(fn, entry[])
   if oldPrc == nil:
diff --git a/compiler/semmagic.nim b/compiler/semmagic.nim
index 5d16470b0..65185f762 100644
--- a/compiler/semmagic.nim
+++ b/compiler/semmagic.nim
@@ -26,6 +26,37 @@ proc semTypeOf(c: PContext; n: PNode): PNode =
   result.add typExpr
   result.typ = makeTypeDesc(c, typExpr.typ.skipTypes({tyTypeDesc, tyIter}))
 
+type
+  SemAsgnMode = enum asgnNormal, noOverloadedSubscript, noOverloadedAsgn
+
+proc semAsgn(c: PContext, n: PNode; mode=asgnNormal): PNode
+proc semSubscript(c: PContext, n: PNode, flags: TExprFlags): PNode
+
+proc semArrGet(c: PContext; n: PNode; flags: TExprFlags): PNode =
+  result = newNodeI(nkBracketExpr, n.info)
+  for i in 1..<n.len: result.add(n[i])
+  let oldBracketExpr = c.p.bracketExpr
+  result = semSubscript(c, result, flags)
+  c.p.bracketExpr = oldBracketExpr
+  if result.isNil:
+    localError(n.info, "could not resolve: " & $n)
+    result = n
+
+proc semArrPut(c: PContext; n: PNode; flags: TExprFlags): PNode =
+  # rewrite `[]=`(a, i, x)  back to ``a[i] = x``.
+  let b = newNodeI(nkBracketExpr, n.info)
+  for i in 1..n.len-2: b.add(n[i])
+  result = newNodeI(nkAsgn, n.info, 2)
+  result.sons[0] = b
+  result.sons[1] = n.lastSon
+  result = semAsgn(c, result, noOverloadedSubscript)
+
+proc semAsgnOpr(c: PContext; n: PNode): PNode =
+  result = newNodeI(nkAsgn, n.info, 2)
+  result.sons[0] = n[1]
+  result.sons[1] = n[2]
+  result = semAsgn(c, result, noOverloadedAsgn)
+
 proc semIsPartOf(c: PContext, n: PNode, flags: TExprFlags): PNode =
   var r = isPartOf(n[1], n[2])
   result = newIntNodeT(ord(r), n)
@@ -125,6 +156,9 @@ proc magicsAfterOverloadResolution(c: PContext, n: PNode,
   of mTypeOf:
     checkSonsLen(n, 2)
     result = semTypeOf(c, n.sons[1])
+  of mArrGet: result = semArrGet(c, n, flags)
+  of mArrPut: result = semArrPut(c, n, flags)
+  of mAsgn: result = semAsgnOpr(c, n)
   of mIsPartOf: result = semIsPartOf(c, n, flags)
   of mTypeTrait: result = semTypeTraits(c, n)
   of mAstToStr:
diff --git a/compiler/semstmts.nim b/compiler/semstmts.nim
index 4399c0ab0..f67ee2822 100644
--- a/compiler/semstmts.nim
+++ b/compiler/semstmts.nim
@@ -1033,6 +1033,7 @@ proc semOverride(c: PContext, s: PSym, n: PNode) =
                  "signature for 'deepCopy' must be proc[T: ptr|ref](x: T): T")
     incl(s.flags, sfUsed)
   of "=":
+    if s.magic == mAsgn: return
     incl(s.flags, sfUsed)
     let t = s.typ
     if t.len == 3 and t.sons[0] == nil and t.sons[1].kind == tyVar:
@@ -1131,6 +1132,7 @@ proc semProcAux(c: PContext, n: PNode, kind: TSymKind,
         # semParamList(c, n.sons[ParamsPos], nil, s)
   else:
     s.typ = newProcType(c, n.info)
+  if tfTriggersCompileTime in s.typ.flags: incl(s.flags, sfCompileTime)
   if n.sons[patternPos].kind != nkEmpty:
     n.sons[patternPos] = semPattern(c, n.sons[patternPos])
   if s.kind in skIterators:
diff --git a/compiler/semtempl.nim b/compiler/semtempl.nim
index 371abe1e3..fc1af7246 100644
--- a/compiler/semtempl.nim
+++ b/compiler/semtempl.nim
@@ -281,6 +281,35 @@ proc semTemplBodySons(c: var TemplCtx, n: PNode): PNode =
   for i in 0.. < n.len:
     result.sons[i] = semTemplBody(c, n.sons[i])
 
+proc wrapInBind(c: var TemplCtx; n: PNode; opr: string): PNode =
+  let ident = getIdent(opr)
+  if ident.id in c.toInject: return n
+
+  let s = searchInScopes(c.c, ident)
+  if s != nil:
+    var callee: PNode
+    if contains(c.toBind, s.id):
+      callee = symChoice(c.c, n, s, scClosed)
+    elif contains(c.toMixin, s.name.id):
+      callee = symChoice(c.c, n, s, scForceOpen)
+    elif s.owner == c.owner and sfGenSym in s.flags:
+      # template tmp[T](x: var seq[T]) =
+      # var yz: T
+      incl(s.flags, sfUsed)
+      callee = newSymNode(s, n.info)
+      styleCheckUse(n.info, s)
+    else:
+      callee = semTemplSymbol(c.c, n, s)
+
+    let call = newNodeI(nkCall, n.info)
+    call.add(callee)
+    for i in 0 .. n.len-1: call.add(n[i])
+    result = newNodeI(nkBind, n.info, 2)
+    result.sons[0] = n
+    result.sons[1] = call
+  else:
+    result = n
+
 proc semTemplBody(c: var TemplCtx, n: PNode): PNode =
   result = n
   semIdeForTemplateOrGenericCheck(n, c.cursorInBody)
@@ -423,6 +452,28 @@ proc semTemplBody(c: var TemplCtx, n: PNode): PNode =
     result.sons[1] = semTemplBody(c, n.sons[1])
   of nkPragma:
     result = onlyReplaceParams(c, n)
+  of nkBracketExpr, nkCurlyExpr:
+    result = newNodeI(nkCall, n.info)
+    result.add newIdentNode(getIdent(if n.kind == nkBracketExpr:"[]" else:"{}"),
+                            n.info)
+    for i in 0 ..< n.len: result.add(n[i])
+    result = semTemplBodySons(c, result)
+  of nkAsgn, nkFastAsgn:
+    checkSonsLen(n, 2)
+    let a = n.sons[0]
+    let b = n.sons[1]
+
+    let k = a.kind
+    case k
+    of nkBracketExpr, nkCurlyExpr:
+      result = newNodeI(nkCall, n.info)
+      result.add newIdentNode(getIdent(if k == nkBracketExpr:"[]=" else:"{}="),
+                              n.info)
+      for i in 0 ..< a.len: result.add(a[i])
+      result.add(b)
+    else:
+      result = n
+    result = semTemplBodySons(c, result)
   else:
     # dotExpr is ambiguous: note that we explicitly allow 'x.TemplateParam',
     # so we use the generic code for nkDotExpr too
diff --git a/compiler/semtypes.nim b/compiler/semtypes.nim
index 2ee17fcaf..1cfbc368b 100644
--- a/compiler/semtypes.nim
+++ b/compiler/semtypes.nim
@@ -718,12 +718,12 @@ proc liftParamType(c: PContext, procKind: TSymKind, genericParams: PNode,
   if paramType == nil: return # (e.g. proc return type)
 
   proc addImplicitGenericImpl(typeClass: PType, typId: PIdent): PType =
-    let finalTypId = if typId != nil: typId
-                     else: getIdent(paramName & ":type")
     if genericParams == nil:
       # This happens with anonymous proc types appearing in signatures
       # XXX: we need to lift these earlier
       return
+    let finalTypId = if typId != nil: typId
+                     else: getIdent(paramName & ":type")
     # is this a bindOnce type class already present in the param list?
     for i in countup(0, genericParams.len - 1):
       if genericParams.sons[i].sym.name.id == finalTypId.id:
@@ -757,7 +757,7 @@ proc liftParamType(c: PContext, procKind: TSymKind, genericParams: PNode,
 
   case paramType.kind:
   of tyAnything:
-    result = addImplicitGeneric(newTypeS(tyGenericParam, c))
+    result = addImplicitGenericImpl(newTypeS(tyGenericParam, c), nil)
 
   of tyStatic:
     # proc(a: expr{string}, b: expr{nkLambda})
@@ -868,6 +868,7 @@ proc liftParamType(c: PContext, procKind: TSymKind, genericParams: PNode,
   of tyExpr:
     if procKind notin {skMacro, skTemplate}:
       result = addImplicitGeneric(newTypeS(tyAnything, c))
+      #result = addImplicitGenericImpl(newTypeS(tyGenericParam, c), nil)
 
   of tyGenericParam:
     markUsed(info, paramType.sym)
@@ -977,7 +978,11 @@ proc semProcTypeNode(c: PContext, n, genericParams: PNode,
     # compiler only checks for 'nil':
     if skipTypes(r, {tyGenericInst}).kind != tyEmpty:
       # 'auto' as a return type does not imply a generic:
-      if r.kind != tyExpr:
+      if r.kind == tyAnything:
+        # 'p(): auto' and 'p(): expr' are equivalent, but the rest of the
+        # compiler is hardly aware of 'auto':
+        r = newTypeS(tyExpr, c)
+      elif r.kind != tyExpr:
         if r.sym == nil or sfAnon notin r.sym.flags:
           let lifted = liftParamType(c, kind, genericParams, r, "result",
                                      n.sons[0].info)
@@ -1149,7 +1154,17 @@ proc semTypeNode(c: PContext, n: PNode, prev: PType): PType =
     else:
       result = semAnonTuple(c, n, prev)
   of nkCallKinds:
-    if isRange(n):
+    let x = n[0]
+    let ident = case x.kind
+                of nkIdent: x.ident
+                of nkSym: x.sym.name
+                of nkClosedSymChoice, nkOpenSymChoice: x[0].sym.name
+                else: nil
+    if ident != nil and ident.s == "[]":
+      let b = newNodeI(nkBracketExpr, n.info)
+      for i in 1..<n.len: b.add(n[i])
+      result = semTypeNode(c, b, prev)
+    elif ident != nil and ident.id == ord(wDotDot):
       result = semRangeAux(c, n, prev)
     elif n[0].kind notin nkIdentKinds:
       result = semTypeExpr(c, n)
@@ -1336,8 +1351,11 @@ proc processMagicType(c: PContext, m: PSym) =
   of mIntSetBaseType: setMagicType(m, tyRange, intSize)
   of mNil: setMagicType(m, tyNil, ptrSize)
   of mExpr:
-    setMagicType(m, tyExpr, 0)
-    if m.name.s == "expr": m.typ.flags.incl tfOldSchoolExprStmt
+    if m.name.s == "auto":
+      setMagicType(m, tyAnything, 0)
+    else:
+      setMagicType(m, tyExpr, 0)
+      if m.name.s == "expr": m.typ.flags.incl tfOldSchoolExprStmt
   of mStmt:
     setMagicType(m, tyStmt, 0)
     if m.name.s == "stmt": m.typ.flags.incl tfOldSchoolExprStmt
@@ -1365,7 +1383,8 @@ proc processMagicType(c: PContext, m: PSym) =
   of mOrdinal:
     setMagicType(m, tyOrdinal, 0)
     rawAddSon(m.typ, newTypeS(tyNone, c))
-  of mPNimrodNode: discard
+  of mPNimrodNode:
+    incl m.typ.flags, tfTriggersCompileTime
   of mShared:
     setMagicType(m, tyObject, 0)
     m.typ.n = newNodeI(nkRecList, m.info)
diff --git a/compiler/sigmatch.nim b/compiler/sigmatch.nim
index 61f1a7444..f6f029936 100644
--- a/compiler/sigmatch.nim
+++ b/compiler/sigmatch.nim
@@ -1691,6 +1691,10 @@ proc partialMatch*(c: PContext, n, nOrig: PNode, m: var TCandidate) =
   matchesAux(c, n, nOrig, m, marker)
 
 proc matches*(c: PContext, n, nOrig: PNode, m: var TCandidate) =
+  if m.calleeSym != nil and m.calleeSym.magic in {mArrGet, mArrPut}:
+    m.state = csMatch
+    m.call = n
+    return
   var marker = initIntSet()
   matchesAux(c, n, nOrig, m, marker)
   if m.state == csNoMatch: return
diff --git a/doc/manual/generics.txt b/doc/manual/generics.txt
index 8f7dcd580..c6206d030 100644
--- a/doc/manual/generics.txt
+++ b/doc/manual/generics.txt
@@ -116,7 +116,7 @@ type class           matches
 ``array``            any array type
 ``set``              any set type
 ``seq``              any seq type
-``auto``             any type
+``any``              any type
 ==================   ===================================================
 
 Furthermore, every generic type automatically creates a type class of the same
@@ -163,15 +163,6 @@ module to illustrate this:
 Alternatively, the ``distinct`` type modifier can be applied to the type class
 to allow each param matching the type class to bind to a different type.
 
-If a proc param doesn't have a type specified, Nim will use the
-``distinct auto`` type class (also known as ``any``). Note this behavior is
-deprecated for procs; templates, however, support them:
-
-.. code-block:: nim
-  # allow any combination of param types
-  proc concat(a, b): string = $a & $b # deprecated
-  proc concat(a, b: any): string = $a & $b # preferred
-
 Procs written with the implicitly generic style will often need to refer to the
 type parameters of the matched generic type. They can be easily accessed using
 the dot syntax:
diff --git a/doc/manual/pragmas.txt b/doc/manual/pragmas.txt
index 8166994a9..68a88f865 100644
--- a/doc/manual/pragmas.txt
+++ b/doc/manual/pragmas.txt
@@ -72,7 +72,20 @@ compileTime pragma
 ------------------
 The ``compileTime`` pragma is used to mark a proc or variable to be used at
 compile time only. No code will be generated for it. Compile time procs are
-useful as helpers for macros.
+useful as helpers for macros. Since version 0.12.0 of the language, a proc
+that uses ``system.NimNode`` within its parameter types is implictly declared
+``compileTime``:
+
+.. code-block:: nim
+  proc astHelper(n: NimNode): NimNode =
+    result = n
+
+Is the same as:
+
+.. code-block:: nim
+  proc astHelper(n: NimNode): NimNode {.compileTime.} =
+    result = n
+
 
 noReturn pragma
 ---------------
diff --git a/doc/manual/types.txt b/doc/manual/types.txt
index 44a20d093..c9ac6f062 100644
--- a/doc/manual/types.txt
+++ b/doc/manual/types.txt
@@ -1228,3 +1228,27 @@ However, a ``void`` type cannot be inferred in generic code:
 
 The ``void`` type is only valid for parameters and return types; other symbols
 cannot have the type ``void``.
+
+
+Auto type
+---------
+
+The ``auto`` type can only be used for return types and parameters. For return
+types it causes the compiler to infer the type from the routine body:
+
+.. code-block:: nim
+  proc returnsInt(): auto = 1984
+
+For parameters it currently creates implicitly generic routines:
+
+.. code-block:: nim
+  proc foo(a, b: auto) = discard
+
+Is the same as:
+
+.. code-block:: nim
+  proc foo[T1, T2](a: T1, b: T2) = discard
+
+However later versions of the language might change this to mean "infer the
+parameters' types from the body". Then the above ``foo`` would be rejected as
+the parameters' types can not be infered from an empty ``discard`` statement.
diff --git a/lib/system.nim b/lib/system.nim
index 1890ce5be..27c23e0bc 100644
--- a/lib/system.nim
+++ b/lib/system.nim
@@ -78,7 +78,7 @@ type
   stmt* {.magic: Stmt.} ## meta type to denote a statement (for templates)
   typedesc* {.magic: TypeDesc.} ## meta type to denote a type description
   void* {.magic: "VoidType".}   ## meta type to denote the absence of any type
-  auto* = expr ## meta type for automatic type determination
+  auto* {.magic: Expr.} ## meta type for automatic type determination
   any* = distinct auto ## meta type for any supported type
   untyped* {.magic: Expr.} ## meta type to denote an expression that
                            ## is not resolved (for templates)
@@ -104,7 +104,7 @@ type
   SomeNumber* = SomeInteger|SomeReal
     ## type class matching all number types
 
-proc defined*(x: expr): bool {.magic: "Defined", noSideEffect.}
+proc defined*(x: expr): bool {.magic: "Defined", noSideEffect, compileTime.}
   ## Special compile-time procedure that checks whether `x` is
   ## defined.
   ## `x` is an external symbol introduced through the compiler's
@@ -125,7 +125,7 @@ when defined(nimalias):
     TNumber: SomeNumber,
     TOrdinal: SomeOrdinal].}
 
-proc declared*(x: expr): bool {.magic: "Defined", noSideEffect.}
+proc declared*(x: expr): bool {.magic: "Defined", noSideEffect, compileTime.}
   ## Special compile-time procedure that checks whether `x` is
   ## declared. `x` has to be an identifier or a qualified identifier.
   ## This can be used to check whether a library provides a certain
@@ -140,11 +140,11 @@ when defined(useNimRtl):
   {.deadCodeElim: on.}
 
 proc definedInScope*(x: expr): bool {.
-  magic: "DefinedInScope", noSideEffect, deprecated.}
+  magic: "DefinedInScope", noSideEffect, deprecated, compileTime.}
   ## **Deprecated since version 0.9.6**: Use ``declaredInScope`` instead.
 
 proc declaredInScope*(x: expr): bool {.
-  magic: "DefinedInScope", noSideEffect.}
+  magic: "DefinedInScope", noSideEffect, compileTime.}
   ## Special compile-time procedure that checks whether `x` is
   ## declared in the current scope. `x` has to be an identifier.
 
@@ -160,7 +160,7 @@ proc unsafeAddr*[T](x: var T): ptr T {.magic: "Addr", noSideEffect.} =
   ## Cannot be overloaded.
   discard
 
-proc `type`*(x: expr): typeDesc {.magic: "TypeOf", noSideEffect.} =
+proc `type`*(x: expr): typeDesc {.magic: "TypeOf", noSideEffect, compileTime.} =
   ## Builtin 'type' operator for accessing the type of an expression.
   ## Cannot be overloaded.
   discard
@@ -239,6 +239,14 @@ type
   seq*{.magic: "Seq".}[T]  ## Generic type to construct sequences.
   set*{.magic: "Set".}[T]  ## Generic type to construct bit sets.
 
+when defined(nimArrIdx):
+  # :array|openarray|string|seq|cstring|tuple
+  proc `[]`*[I: Ordinal;T](a: T; i: I): T {.
+    noSideEffect, magic: "ArrGet".}
+  proc `[]=`*[I: Ordinal;T,S](a: var T; i: I;
+    x: S) {.noSideEffect, magic: "ArrPut".}
+  proc `=`*[T](dest: var T; src: T) {.noSideEffect, magic: "Asgn".}
+
 type
   Slice*[T] = object ## builtin slice type
     a*, b*: T        ## the bounds
@@ -3384,7 +3392,7 @@ when hasAlloc:
       x[j+i] = item[j]
       inc(j)
 
-proc compiles*(x: expr): bool {.magic: "Compiles", noSideEffect.} =
+proc compiles*(x: expr): bool {.magic: "Compiles", noSideEffect, compileTime.} =
   ## Special compile-time procedure that checks whether `x` can be compiled
   ## without any semantic error.
   ## This can be used to check whether a type supports some operation:
@@ -3448,7 +3456,7 @@ when hasAlloc and not defined(nimscript) and not defined(JS):
 
   include "system/deepcopy"
 
-proc procCall*(x: expr) {.magic: "ProcCall".} =
+proc procCall*(x: expr) {.magic: "ProcCall", compileTime.} =
   ## special magic to prohibit dynamic binding for `method`:idx: calls.
   ## This is similar to `super`:idx: in ordinary OO languages.
   ##
diff --git a/tests/ccgbugs/tnocodegen_for_compiletime.nim b/tests/ccgbugs/tnocodegen_for_compiletime.nim
new file mode 100644
index 000000000..a88ba4b32
--- /dev/null
+++ b/tests/ccgbugs/tnocodegen_for_compiletime.nim
@@ -0,0 +1,9 @@
+# bug #1679
+import macros, tables, hashes
+proc hash(v: NimNode): Hash = 4  # performance is for suckers
+macro test(body: stmt): stmt {.immediate.} =
+  var a = initCountTable[NimNode]()
+  a.inc(body)
+
+test:
+  1 + 1
diff --git a/tests/generics/mbind_bracket.nim b/tests/generics/mbind_bracket.nim
new file mode 100644
index 000000000..4bf18b471
--- /dev/null
+++ b/tests/generics/mbind_bracket.nim
@@ -0,0 +1,17 @@
+
+import tables
+
+type
+  UUIDObject* = ref object
+    uuid: string
+
+  Registry*[T] = ref object
+    objects: Table[string, T]
+
+proc newRegistry*[T](): Registry[T] =
+  result = Registry[T]()
+  result.objects = initTable[string, T](128)
+
+proc register*[T](self: Registry[T], obj: T) =
+  self.objects[obj.uuid] = obj
+
diff --git a/tests/generics/tbind_bracket.nim b/tests/generics/tbind_bracket.nim
new file mode 100644
index 000000000..d0c5e2c6b
--- /dev/null
+++ b/tests/generics/tbind_bracket.nim
@@ -0,0 +1,20 @@
+discard """
+  output: "317"
+"""
+
+# bug #2599
+
+import mbind_bracket
+
+# also test that `[]` can be passed now as a first class construct:
+
+template takeBracket(x, a, i: untyped) =
+  echo x(a, i)
+
+var a: array[10, int]
+a[8] = 317
+
+takeBracket(`[]`, a, 8)
+
+let reg = newRegistry[UUIDObject]()
+reg.register(UUIDObject())
diff --git a/tests/generics/tthread_generic.nim b/tests/generics/tthread_generic.nim
index d34b24628..e8946caf6 100644
--- a/tests/generics/tthread_generic.nim
+++ b/tests/generics/tthread_generic.nim
@@ -3,7 +3,7 @@ discard """
 """
 
 type
-  TThreadFuncArgs[T] = object of TObject
+  TThreadFuncArgs[T] = object of RootObj
     a: proc(): T {.thread.}
     b: proc(val: T) {.thread.}
 
diff --git a/tests/metatype/ttypedesc1.nim b/tests/metatype/ttypedesc1.nim
index 19072d966..d78c62a94 100644
--- a/tests/metatype/ttypedesc1.nim
+++ b/tests/metatype/ttypedesc1.nim
@@ -7,7 +7,7 @@ type
 
 proc getTypeName(t: typedesc): string = t.name
 
-proc foo(T: typedesc[float], a: expr): string =
+proc foo(T: typedesc[float], a: auto): string =
   result = "float " & $(a.len > 5)
 
 proc foo(T: typedesc[TFoo], a: int): string =
diff --git a/tests/types/tauto_excessive.nim b/tests/types/tauto_excessive.nim
new file mode 100644
index 000000000..2626b0cf4
--- /dev/null
+++ b/tests/types/tauto_excessive.nim
@@ -0,0 +1,20 @@
+discard """
+  output: '''10
+10.0
+1.0hiho'''
+"""
+
+# bug #3224
+proc f(x: auto): auto =
+  result = $(x+10)
+
+proc f(x, y: auto): auto =
+  result = $(x+y)
+
+
+echo f(0)     # prints 10
+echo f(0.0)  # prints 10.0
+
+proc `+`(a, b: string): string = a & b
+
+echo f(0.7, 0.3), f("hi", "ho")
diff --git a/todo.txt b/todo.txt
index 91c6f1625..306b7008e 100644
--- a/todo.txt
+++ b/todo.txt
@@ -24,7 +24,6 @@ version 1.0
 - The bitwise 'not' operator will be renamed to 'bnot' to
   prevent 'not 4 == 5' from compiling. -> requires 'mixin' annotation for procs!
 - split docgen into separate tool
-- special rule for ``[]=``, items, pairs
 - BUG: echo with template `$`*(info: TLineInfo): expr = toFileLineCol(info)
 - make 'nil' work for 'add':
   - resizeString
diff --git a/web/news.txt b/web/news.txt
index 1a312f67b..aaa27cfee 100644
--- a/web/news.txt
+++ b/web/news.txt
@@ -3,7 +3,7 @@ News
 ====
 
 ..
-  2015-05-05 Version 0.11.4 released
+  2015-09-14 Version 0.11.4 released
   ==================================
 
   Changes affecting backwards compatibility
@@ -58,7 +58,7 @@ News
     of all the DLLs the standard library needs. This means that the following
     DLLs are now split into 32 and 64 versions:
 
-    * ``prce.dll``: Split into ``prce32.dll`` and ``prce64.dll``.
+    * ``pcre.dll``: Split into ``pcre32.dll`` and ``pcre64.dll``.
     * ``pdcurses.dll``: Split into ``pdcurses32.dll`` and ``pdcurses64.dll``.
     * ``sqlite3.dll``: Split into ``sqlite3_32.dll`` and ``sqlite3_64.dll``.
     * ``ssleay32.dll``: Split into ``ssleay32.dll`` and ``ssleay64.dll``.
@@ -75,6 +75,13 @@ News
     with Unix's ``#!``.
   - An implicit return type for an iterator is now deprecated. Use ``auto`` if
     you want more type inference.
+  - The type ``auto`` is now a "multi-bind" metatype, so the following compiles:
+
+    .. code-block:: nim
+      proc f(x, y: auto): auto =
+        result = $x & y
+
+      echo f(0, "abc")
 
 
   Library Additions
@@ -95,6 +102,9 @@ News
 
   - The compiler now supports a new configuration system based on
     `NimScript <docs/nims.html>`_.
+  - The compiler finally considers symbol binding rules in templates and
+    generics for overloaded ``[]``, ``[]=``, ``{}``, ``{}=`` operators
+    (issue `#2599 <https://github.com/nim-lang/Nim/issues/2599>`_).
 
 
   Language Additions
@@ -112,22 +122,21 @@ News
     this ``let (x, y) == f()`` still needs to be used.
   - ``when nimvm`` can now be used for compiletime versions of some code
     sections. Click `here <docs/manual.html#when-nimvm-statement>`_ for details.
+  - Usage of the type ``NimNode`` in a proc now implicitly annotates the proc
+    with ``.compileTime``. This means generics work much better for ``NimNode``.
 
 
   Bugfixes
   --------
-  - Fixed "Compiler internal error on iterator it(T: typedesc[Base]) called with
- it(Child), where Child = object of Base"
+  - Fixed "Compiler internal error on iterator it(T: typedesc[Base]) called with it(Child), where Child = object of Base"
     (`#2662 <https://github.com/Araq/Nim/issues/2662>`_)
   - Fixed "repr() misses base object field in 2nd level derived object"
     (`#2749 <https://github.com/Araq/Nim/issues/2749>`_)
   - Fixed "nimsuggest doesn't work more than once on the non-main file"
     (`#2694 <https://github.com/Araq/Nim/issues/2694>`_)
-  - Fixed "JS Codegen. Passing arguments by var in certain cases leads to invali
-d JS."
+  - Fixed "JS Codegen. Passing arguments by var in certain cases leads to invalid JS."
     (`#2798 <https://github.com/Araq/Nim/issues/2798>`_)
-  - Fixed ""check" proc in unittest.nim prevents the propagation of changes to v
-ar parameters."
+  - Fixed ""check" proc in unittest.nim prevents the propagation of changes to var parameters."
     (`#964 <https://github.com/Araq/Nim/issues/964>`_)
   - Fixed "Excessive letters in integer literals are not an error"
     (`#2523 <https://github.com/Araq/Nim/issues/2523>`_)
@@ -141,8 +150,7 @@ ar parameters."
     (`#2687 <https://github.com/Araq/Nim/issues/2687>`_)
   - Fixed "Compile error using object in const array"
     (`#2774 <https://github.com/Araq/Nim/issues/2774>`_)
-  - Fixed "httpclient async requests with method httpPOST isn't sending Content-
-Length header"
+  - Fixed "httpclient async requests with method httpPOST isn't sending Content-Length header"
     (`#2884 <https://github.com/Araq/Nim/issues/2884>`_)
   - Fixed "Streams module not working with JS backend"
     (`#2148 <https://github.com/Araq/Nim/issues/2148>`_)
@@ -173,8 +181,7 @@ Length header"
     (`#2974 <https://github.com/Araq/Nim/issues/2974>`_)
   - Fixed "repr is broken"
     (`#2992 <https://github.com/Araq/Nim/issues/2992>`_)
-  - Fixed "Ipv6 devel - add IPv6 support for asyncsockets, make AF_INET6 a defau
-lt"
+  - Fixed "Ipv6 devel - add IPv6 support for asyncsockets, make AF_INET6 a default"
     (`#2976 <https://github.com/Araq/Nim/issues/2976>`_)
   - Fixed "Compilation broken on windows"
     (`#2996 <https://github.com/Araq/Nim/issues/2996>`_)
@@ -184,8 +191,7 @@ lt"
     (`#2672 <https://github.com/Araq/Nim/issues/2672>`_)
   - Fixed "Uncatched exception in async procedure on raise statement"
     (`#3014 <https://github.com/Araq/Nim/issues/3014>`_)
-  - Fixed "nim doc2 fails in Mac OS X due to system.nim (possibly related to #18
-98)"
+  - Fixed "nim doc2 fails in Mac OS X due to system.nim (possibly related to #1898)"
     (`#3005 <https://github.com/Araq/Nim/issues/3005>`_)
   - Fixed "IndexError when rebuilding Nim on iteration 2"
     (`#3018 <https://github.com/Araq/Nim/issues/3018>`_)
@@ -233,8 +239,7 @@ lt"
     (`#3054 <https://github.com/Araq/Nim/issues/3054>`_)
   - Fixed "Wrong sharing of static_t instantations"
     (`#3112 <https://github.com/Araq/Nim/issues/3112>`_)
-  - Fixed "Automatically generated proc conflicts with user-defined proc when .e
-xportc.'ed"
+  - Fixed "Automatically generated proc conflicts with user-defined proc when .exportc.'ed"
     (`#3134 <https://github.com/Araq/Nim/issues/3134>`_)
   - Fixed "getTypeInfo call crashes nim"
     (`#3099 <https://github.com/Araq/Nim/issues/3099>`_)
@@ -254,15 +259,13 @@ xportc.'ed"
     (`#3149 <https://github.com/Araq/Nim/issues/3149>`_)
   - Fixed "Inference of `static[T]` in sequences"
     (`#3144 <https://github.com/Araq/Nim/issues/3144>`_)
-  - Fixed "Argument named "closure" to proc inside template interfere with closu
-re pragma"
+  - Fixed "Argument named "closure" to proc inside template interfere with closure pragma"
     (`#3171 <https://github.com/Araq/Nim/issues/3171>`_)
   - Fixed "Internal error with aliasing inside template"
     (`#3158 <https://github.com/Araq/Nim/issues/3158>`_)
   - Fixed "Cardinality of sets prints unexpected value"
     (`#3135 <https://github.com/Araq/Nim/issues/3135>`_)
-  - Fixed "Nim crashes on const assignment from function returning var ref objec
-t"
+  - Fixed "Nim crashes on const assignment from function returning var ref object"
     (`#3103 <https://github.com/Araq/Nim/issues/3103>`_)
   - Fixed "`repr` cstring"
     (`#3080 <https://github.com/Araq/Nim/issues/3080>`_)
@@ -270,8 +273,7 @@ t"
     (`#3052 <https://github.com/Araq/Nim/issues/3052>`_)
   - Fixed "Compiler assertion when evaluating template with static[T]"
     (`#1858 <https://github.com/Araq/Nim/issues/1858>`_)
-  - Fixed "Erroneous overflow in iterators when compiler built with overflowChec
-ks enabled"
+  - Fixed "Erroneous overflow in iterators when compiler built with overflowChecks enabled"
     (`#3140 <https://github.com/Araq/Nim/issues/3140>`_)
   - Fixed "Unicode dashes as "lisp'ish" alternative to hump and snake notation"
     (`#2811 <https://github.com/Araq/Nim/issues/2811>`_)
@@ -283,8 +285,7 @@ ks enabled"
     (`#3193 <https://github.com/Araq/Nim/issues/3193>`_)
   - Fixed "VM crash when accessing array's element"
     (`#3192 <https://github.com/Araq/Nim/issues/3192>`_)
-  - Fixed "Unexpected proc invoked when different modules add procs to a type fr
-om a 3rd module"
+  - Fixed "Unexpected proc invoked when different modules add procs to a type from a 3rd module"
     (`#2664 <https://github.com/Araq/Nim/issues/2664>`_)
   - Fixed "Nim crashes on conditional declaration inside a template"
     (`#2670 <https://github.com/Araq/Nim/issues/2670>`_)
@@ -292,8 +293,7 @@ om a 3rd module"
     (`#2752 <https://github.com/Araq/Nim/issues/2752>`_)
   - Fixed "VM: Cannot assign int value to ref variable"
     (`#1329 <https://github.com/Araq/Nim/issues/1329>`_)
-  - Fixed "Incorrect code generated for tagged unions with enums not starting at
- zero"
+  - Fixed "Incorrect code generated for tagged unions with enums not starting at zero"
     (`#3096 <https://github.com/Araq/Nim/issues/3096>`_)
   - Fixed "Compile time procs using forward declarations are silently ignored"
     (`#3066 <https://github.com/Araq/Nim/issues/3066>`_)
@@ -301,8 +301,7 @@ om a 3rd module"
     (`#1965 <https://github.com/Araq/Nim/issues/1965>`_)
   - Fixed "os.getCreationTime is incorrect/impossible on Posix systems"
     (`#1058 <https://github.com/Araq/Nim/issues/1058>`_)
-  - Fixed "Improve error message for osproc.startProcess when command does not e
-xist"
+  - Fixed "Improve error message for osproc.startProcess when command does not exist"
     (`#2183 <https://github.com/Araq/Nim/issues/2183>`_)
   - Fixed "gctest segfaults with --gc:markandsweep on x86_64"
     (`#2305 <https://github.com/Araq/Nim/issues/2305>`_)