summary refs log tree commit diff stats
diff options
context:
space:
mode:
-rw-r--r--compiler/astalgo.nim13
-rw-r--r--compiler/ccgutils.nim1
-rw-r--r--compiler/cgen.nim2
-rw-r--r--compiler/docgen.nim54
-rw-r--r--compiler/lookups.nim28
-rw-r--r--compiler/semexprs.nim13
-rw-r--r--compiler/semstmts.nim2
-rw-r--r--compiler/semtypes.nim4
-rw-r--r--compiler/transf.nim3
-rw-r--r--lib/core/macros.nim35
-rw-r--r--lib/packages/docutils/rst.nim29
-rw-r--r--lib/pure/strscans.nim4
-rw-r--r--tests/ccgbugs/tcodegenbug1.nim35
-rw-r--r--tests/openarray/t8259.nim7
-rw-r--r--tests/pragmas/tcustom_pragma.nim2
-rw-r--r--tests/stdlib/t8925.nim16
16 files changed, 190 insertions, 58 deletions
diff --git a/compiler/astalgo.nim b/compiler/astalgo.nim
index 34963ee83..b716882dc 100644
--- a/compiler/astalgo.nim
+++ b/compiler/astalgo.nim
@@ -549,7 +549,8 @@ proc strTableAdd*(t: var TStrTable, n: PSym) =
   strTableRawInsert(t.data, n)
   inc(t.counter)
 
-proc strTableIncl*(t: var TStrTable, n: PSym; onConflictKeepOld=false): bool {.discardable.} =
+proc strTableInclReportConflict*(t: var TStrTable, n: PSym;
+                                 onConflictKeepOld = false): PSym =
   # returns true if n is already in the string table:
   # It is essential that `n` is written nevertheless!
   # This way the newest redefinition is picked by the semantic analyses!
@@ -564,13 +565,13 @@ proc strTableIncl*(t: var TStrTable, n: PSym; onConflictKeepOld=false): bool {.d
     # So it is possible the very same sym is added multiple
     # times to the symbol table which we allow here with the 'it == n' check.
     if it.name.id == n.name.id:
-      if it == n: return false
+      if it == n: return nil
       replaceSlot = h
     h = nextTry(h, high(t.data))
   if replaceSlot >= 0:
     if not onConflictKeepOld:
       t.data[replaceSlot] = n # overwrite it with newer definition!
-    return true             # found it
+    return t.data[replaceSlot] # found it
   elif mustRehash(len(t.data), t.counter):
     strTableEnlarge(t)
     strTableRawInsert(t.data, n)
@@ -578,7 +579,11 @@ proc strTableIncl*(t: var TStrTable, n: PSym; onConflictKeepOld=false): bool {.d
     assert(t.data[h] == nil)
     t.data[h] = n
   inc(t.counter)
-  result = false
+  result = nil
+
+proc strTableIncl*(t: var TStrTable, n: PSym;
+                   onConflictKeepOld = false): bool {.discardable.} =
+  result = strTableInclReportConflict(t, n, onConflictKeepOld) != nil
 
 proc strTableGet*(t: TStrTable, name: PIdent): PSym =
   var h: Hash = name.h and high(t.data)
diff --git a/compiler/ccgutils.nim b/compiler/ccgutils.nim
index 75cd3d35d..6d2f33f2d 100644
--- a/compiler/ccgutils.nim
+++ b/compiler/ccgutils.nim
@@ -92,6 +92,7 @@ proc mangle*(name: string): string =
     of '+': special "plus"
     of '-': special "minus"
     of '/': special "slash"
+    of '\\': special "backslash"
     of '=': special "eq"
     of '<': special "lt"
     of '>': special "gt"
diff --git a/compiler/cgen.nim b/compiler/cgen.nim
index 2db92bc21..3040f98da 100644
--- a/compiler/cgen.nim
+++ b/compiler/cgen.nim
@@ -707,7 +707,7 @@ proc containsResult(n: PNode): bool =
     for i in 0..<n.safeLen:
       if containsResult(n[i]): return true
 
-const harmless = {nkConstSection, nkTypeSection, nkEmpty, nkCommentStmt} +
+const harmless = {nkConstSection, nkTypeSection, nkEmpty, nkCommentStmt, nkTemplateDef, nkMacroDef} +
                   declarativeDefs
 
 proc easyResultAsgn(n: PNode): PNode =
diff --git a/compiler/docgen.nim b/compiler/docgen.nim
index ca3b1ac2d..e7920ad06 100644
--- a/compiler/docgen.nim
+++ b/compiler/docgen.nim
@@ -19,6 +19,9 @@ import
   typesrenderer, astalgo, modulepaths, lineinfos, sequtils, intsets,
   pathutils
 
+const
+  exportSection = skTemp
+
 type
   TSections = array[TSymKind, Rope]
   TDocumentor = object of rstgen.RstGenerator
@@ -254,6 +257,15 @@ proc belongsToPackage(conf: ConfigRef; module: PSym): bool =
   result = module.kind == skModule and module.owner != nil and
       module.owner.id == conf.mainPackageId
 
+proc externalDep(d: PDoc; module: PSym): string =
+  if optWholeProject in d.conf.globalOptions:
+    let full = AbsoluteFile toFullPath(d.conf, FileIndex module.position)
+    let tmp = getOutFile2(d.conf, full.relativeTo(d.conf.projectPath), HtmlExt,
+        RelativeDir"htmldocs", sfMainModule notin module.flags)
+    result = relativeTo(tmp, d.thisDir, '/').string
+  else:
+    result = extractFilename toFullPath(d.conf, FileIndex module.position)
+
 proc nodeToHighlightedHtml(d: PDoc; n: PNode; result: var Rope; renderFlags: TRenderFlags = {}) =
   var r: TSrcGen
   var literal = ""
@@ -290,12 +302,7 @@ proc nodeToHighlightedHtml(d: PDoc; n: PNode; result: var Rope; renderFlags: TRe
       if s != nil and s.kind == skType and sfExported in s.flags and
           s.owner != nil and belongsToPackage(d.conf, s.owner) and
           d.target == outHtml:
-
-        let full = AbsoluteFile toFullPath(d.conf, FileIndex s.owner.position)
-        let tmp = getOutFile2(d.conf, full.relativeTo(d.conf.projectPath),
-            HtmlExt, RelativeDir"htmldocs", sfMainModule notin s.owner.flags)
-
-        let external = tmp.relativeTo(d.thisDir, '/')
+        let external = externalDep(d, s.owner)
         result.addf "<a href=\"$1#$2\"><span class=\"Identifier\">$3</span></a>",
           [rope changeFileExt(external, "html").string, rope literal,
            rope(esc(d.target, literal))]
@@ -688,15 +695,32 @@ proc traceDeps(d: PDoc, it: PNode) =
       a.sons[2] = x
       traceDeps(d, a)
   elif it.kind == nkSym and belongsToPackage(d.conf, it.sym):
-    let full = AbsoluteFile toFullPath(d.conf, FileIndex it.sym.position)
-    let tmp = getOutFile2(d.conf, full.relativeTo(d.conf.projectPath), HtmlExt,
-        RelativeDir"htmldocs", sfMainModule notin it.sym.flags)
-    let external = relativeTo(tmp, d.thisDir, '/').string
+    let external = externalDep(d, it.sym)
+    if d.section[k] != nil: add(d.section[k], ", ")
+    dispA(d.conf, d.section[k],
+          "<a class=\"reference external\" href=\"$2\">$1</a>",
+          "$1", [rope esc(d.target, changeFileExt(external, "")),
+          rope changeFileExt(external, "html")])
+
+proc exportSym(d: PDoc; s: PSym) =
+  const k = exportSection
+  if s.kind == skModule and belongsToPackage(d.conf, s):
+    let external = externalDep(d, s)
     if d.section[k] != nil: add(d.section[k], ", ")
     dispA(d.conf, d.section[k],
           "<a class=\"reference external\" href=\"$2\">$1</a>",
           "$1", [rope esc(d.target, changeFileExt(external, "")),
           rope changeFileExt(external, "html")])
+  elif s.owner != nil:
+    let module = originatingModule(s)
+    if belongsToPackage(d.conf, module):
+      let external = externalDep(d, module)
+      if d.section[k] != nil: add(d.section[k], ", ")
+      # XXX proper anchor generation here
+      dispA(d.conf, d.section[k],
+            "<a href=\"$2#$1\"><span class=\"Identifier\">$1</span></a>",
+            "$1", [rope esc(d.target, s.name.s),
+            rope changeFileExt(external, "html")])
 
 proc generateDoc*(d: PDoc, n, orig: PNode) =
   if orig.info.fileIndex != n.info.fileIndex: return
@@ -732,7 +756,11 @@ proc generateDoc*(d: PDoc, n, orig: PNode) =
     if not checkForFalse(n.sons[0].sons[0]):
       generateDoc(d, lastSon(n.sons[0]), orig)
   of nkImportStmt:
-    for i in 0 .. sonsLen(n)-1: traceDeps(d, n.sons[i])
+    for it in n: traceDeps(d, it)
+  of nkExportStmt:
+    for it in n:
+      if it.kind == nkSym: exportSym(d, it.sym)
+  of nkExportExceptStmt: discard "transformed into nkExportStmt by semExportExcept"
   of nkFromStmt, nkImportExceptStmt: traceDeps(d, n.sons[0])
   of nkCallKinds:
     var comm: Rope = nil
@@ -828,8 +856,8 @@ proc generateTags*(d: PDoc, n: PNode, r: var Rope) =
   else: discard
 
 proc genSection(d: PDoc, kind: TSymKind) =
-  const sectionNames: array[skModule..skTemplate, string] = [
-    "Imports", "Types", "Vars", "Lets", "Consts", "Vars", "Procs", "Funcs",
+  const sectionNames: array[skTemp..skTemplate, string] = [
+    "Exports", "Imports", "Types", "Vars", "Lets", "Consts", "Vars", "Procs", "Funcs",
     "Methods", "Iterators", "Converters", "Macros", "Templates"
   ]
   if d.section[kind] == nil: return
diff --git a/compiler/lookups.nim b/compiler/lookups.nim
index ec9c130e3..d2e7fdcfa 100644
--- a/compiler/lookups.nim
+++ b/compiler/lookups.nim
@@ -58,8 +58,8 @@ proc considerQuotedIdent*(c: PContext; n: PNode, origin: PNode = nil): PIdent =
 template addSym*(scope: PScope, s: PSym) =
   strTableAdd(scope.symbols, s)
 
-proc addUniqueSym*(scope: PScope, s: PSym): bool =
-  result = not strTableIncl(scope.symbols, s)
+proc addUniqueSym*(scope: PScope, s: PSym): PSym =
+  result = strTableInclReportConflict(scope.symbols, s)
 
 proc openScope*(c: PContext): PScope {.discardable.} =
   result = PScope(parent: c.currentScope,
@@ -177,24 +177,30 @@ proc ensureNoMissingOrUnusedSymbols(c: PContext; scope: PScope) =
           message(c.config, s.info, hintXDeclaredButNotUsed, getSymRepr(c.config, s))
     s = nextIter(it, scope.symbols)
 
-proc wrongRedefinition*(c: PContext; info: TLineInfo, s: string) =
+proc wrongRedefinition*(c: PContext; info: TLineInfo, s: string;
+                        conflictsWith: TLineInfo) =
   if c.config.cmd != cmdInteractive:
-    localError(c.config, info, "redefinition of '$1'" % s)
+    localError(c.config, info,
+      "redefinition of '$1'; previous declaration here: $2" %
+      [s, c.config $ conflictsWith])
 
 proc addDecl*(c: PContext, sym: PSym, info: TLineInfo) =
-  if not c.currentScope.addUniqueSym(sym):
-    wrongRedefinition(c, info, sym.name.s)
+  let conflict = c.currentScope.addUniqueSym(sym)
+  if conflict != nil:
+    wrongRedefinition(c, info, sym.name.s, conflict.info)
 
 proc addDecl*(c: PContext, sym: PSym) =
-  if not c.currentScope.addUniqueSym(sym):
-    wrongRedefinition(c, sym.info, sym.name.s)
+  let conflict = c.currentScope.addUniqueSym(sym)
+  if conflict != nil:
+    wrongRedefinition(c, sym.info, sym.name.s, conflict.info)
 
 proc addPrelimDecl*(c: PContext, sym: PSym) =
   discard c.currentScope.addUniqueSym(sym)
 
 proc addDeclAt*(c: PContext; scope: PScope, sym: PSym) =
-  if not scope.addUniqueSym(sym):
-    wrongRedefinition(c, sym.info, sym.name.s)
+  let conflict = scope.addUniqueSym(sym)
+  if conflict != nil:
+    wrongRedefinition(c, sym.info, sym.name.s, conflict.info)
 
 proc addInterfaceDeclAux(c: PContext, sym: PSym) =
   if sfExported in sym.flags:
@@ -212,7 +218,7 @@ proc addOverloadableSymAt*(c: PContext; scope: PScope, fn: PSym) =
     return
   let check = strTableGet(scope.symbols, fn.name)
   if check != nil and check.kind notin OverloadableSyms:
-    wrongRedefinition(c, fn.info, fn.name.s)
+    wrongRedefinition(c, fn.info, fn.name.s, check.info)
   else:
     scope.addSym(fn)
 
diff --git a/compiler/semexprs.nim b/compiler/semexprs.nim
index 43f04fc9f..e683984c5 100644
--- a/compiler/semexprs.nim
+++ b/compiler/semexprs.nim
@@ -1560,6 +1560,8 @@ proc semAsgn(c: PContext, n: PNode; mode=asgnNormal): PNode =
           rhsTyp = rhsTyp.lastSon
         if cmpTypes(c, lhs.typ, rhsTyp) in {isGeneric, isEqual}:
           internalAssert c.config, c.p.resultSym != nil
+          # Make sure the type is valid for the result variable
+          typeAllowedCheck(c.config, n.info, rhsTyp, skResult)
           lhs.typ = rhsTyp
           c.p.resultSym.typ = rhsTyp
           c.p.owner.typ.sons[0] = rhsTyp
@@ -2267,6 +2269,7 @@ proc semExportExcept(c: PContext, n: PNode): PNode =
     return n
   let exceptSet = readExceptSet(c, n)
   let exported = moduleName.sym
+  result = newNodeI(nkExportStmt, n.info)
   strTableAdd(c.module.tab, exported)
   var i: TTabIter
   var s = initTabIter(i, exported.tab)
@@ -2274,11 +2277,12 @@ proc semExportExcept(c: PContext, n: PNode): PNode =
     if s.kind in ExportableSymKinds+{skModule} and
        s.name.id notin exceptSet:
       strTableAdd(c.module.tab, s)
+      result.add newSymNode(s, n.info)
     s = nextIter(i, exported.tab)
-  result = n
 
 proc semExport(c: PContext, n: PNode): PNode =
-  var x = newNodeI(n.kind, n.info)
+  result = newNodeI(nkExportStmt, n.info)
+
   for i in 0..<n.len:
     let a = n.sons[i]
     var o: TOverloadIter
@@ -2288,20 +2292,19 @@ proc semExport(c: PContext, n: PNode): PNode =
     elif s.kind == skModule:
       # forward everything from that module:
       strTableAdd(c.module.tab, s)
-      x.add(newSymNode(s, a.info))
       var ti: TTabIter
       var it = initTabIter(ti, s.tab)
       while it != nil:
         if it.kind in ExportableSymKinds+{skModule}:
           strTableAdd(c.module.tab, it)
+          result.add newSymNode(it, a.info)
         it = nextIter(ti, s.tab)
     else:
       while s != nil:
         if s.kind in ExportableSymKinds+{skModule}:
-          x.add(newSymNode(s, a.info))
+          result.add(newSymNode(s, a.info))
           strTableAdd(c.module.tab, s)
         s = nextOverloadIter(o, c, a)
-  result = n
 
 proc shouldBeBracketExpr(n: PNode): bool =
   assert n.kind in nkCallKinds
diff --git a/compiler/semstmts.nim b/compiler/semstmts.nim
index 566b634af..87d144dc6 100644
--- a/compiler/semstmts.nim
+++ b/compiler/semstmts.nim
@@ -1604,7 +1604,7 @@ proc semProcAux(c: PContext, n: PNode, kind: TSymKind,
         localError(c.config, n.sons[pragmasPos].info, errPragmaOnlyInHeaderOfProcX %
           ("'" & proto.name.s & "' from " & c.config$proto.info))
     if sfForward notin proto.flags and proto.magic == mNone:
-      wrongRedefinition(c, n.info, proto.name.s)
+      wrongRedefinition(c, n.info, proto.name.s, proto.info)
     excl(proto.flags, sfForward)
     closeScope(c)         # close scope with wrong parameter symbols
     openScope(c)          # open scope for old (correct) parameter symbols
diff --git a/compiler/semtypes.nim b/compiler/semtypes.nim
index a90a06150..5394e291f 100644
--- a/compiler/semtypes.nim
+++ b/compiler/semtypes.nim
@@ -125,8 +125,8 @@ proc semEnum(c: PContext, n: PNode, prev: PType): PType =
     if sfGenSym notin e.flags:
       if not isPure: addDecl(c, e)
       else: importPureEnumField(c, e)
-    if isPure and strTableIncl(symbols, e):
-      wrongRedefinition(c, e.info, e.name.s)
+    if isPure and (let conflict = strTableInclReportConflict(symbols, e); conflict != nil):
+      wrongRedefinition(c, e.info, e.name.s, conflict.info)
     inc(counter)
   if not hasNull: incl(result.flags, tfNeedsInit)
 
diff --git a/compiler/transf.nim b/compiler/transf.nim
index 347df3e49..0c3ddf27a 100644
--- a/compiler/transf.nim
+++ b/compiler/transf.nim
@@ -914,7 +914,8 @@ proc transform(c: PTransf, n: PNode): PTransNode =
         # ensure that e.g. discard "some comment" gets optimized away
         # completely:
         result = PTransNode(newNode(nkCommentStmt))
-  of nkCommentStmt, nkTemplateDef, nkImportStmt, nkStaticStmt:
+  of nkCommentStmt, nkTemplateDef, nkImportStmt, nkStaticStmt,
+      nkExportStmt, nkExportExceptStmt:
     return n.PTransNode
   of nkConstSection:
     # do not replace ``const c = 3`` with ``const 3 = 3``
diff --git a/lib/core/macros.nim b/lib/core/macros.nim
index aec766068..e7ef89551 100644
--- a/lib/core/macros.nim
+++ b/lib/core/macros.nim
@@ -1321,17 +1321,18 @@ proc customPragmaNode(n: NimNode): NimNode =
       return typ.getImpl()[0][1]
 
   if n.kind in {nnkDotExpr, nnkCheckedFieldExpr}:
-    let name = (if n.kind == nnkCheckedFieldExpr: n[0][1] else: n[1])
+    let name = $(if n.kind == nnkCheckedFieldExpr: n[0][1] else: n[1])
     var typDef = getImpl(getTypeInst(if n.kind == nnkCheckedFieldExpr or n[0].kind == nnkHiddenDeref: n[0][0] else: n[0]))
     while typDef != nil:
       typDef.expectKind(nnkTypeDef)
-      typDef[2].expectKind({nnkRefTy, nnkPtrTy, nnkObjectTy})
-      let isRef = typDef[2].kind in {nnkRefTy, nnkPtrTy}
-      if isRef and typDef[2][0].kind in {nnkSym, nnkBracketExpr}: # defines ref type for another object(e.g. X = ref X)
-        typDef = getImpl(typDef[2][0])
+      let typ = typDef[2]
+      typ.expectKind({nnkRefTy, nnkPtrTy, nnkObjectTy})
+      let isRef = typ.kind in {nnkRefTy, nnkPtrTy}
+      if isRef and typ[0].kind in {nnkSym, nnkBracketExpr}: # defines ref type for another object(e.g. X = ref X)
+        typDef = getImpl(typ[0])
       else: # object definition, maybe an object directly defined as a ref type
         let
-          obj = (if isRef: typDef[2][0] else: typDef[2])
+          obj = (if isRef: typ[0] else: typ)
         var identDefsStack = newSeq[NimNode](obj[2].len)
         for i in 0..<identDefsStack.len: identDefsStack[i] = obj[2][i]
         while identDefsStack.len > 0:
@@ -1339,19 +1340,25 @@ proc customPragmaNode(n: NimNode): NimNode =
           if identDefs.kind == nnkRecCase:
             identDefsStack.add(identDefs[0])
             for i in 1..<identDefs.len:
+              let varNode = identDefs[i]
               # if it is and empty branch, skip
-              if identDefs[i][0].kind == nnkNilLit: continue
-              if identDefs[i][1].kind == nnkIdentDefs:
-                identDefsStack.add(identDefs[i][1])
+              if varNode[0].kind == nnkNilLit: continue
+              if varNode[1].kind == nnkIdentDefs:
+                identDefsStack.add(varNode[1])
               else: # nnkRecList
-                for j in 0..<identDefs[i][1].len:
-                  identDefsStack.add(identDefs[i][1][j])
+                for j in 0 ..< varNode[1].len:
+                  identDefsStack.add(varNode[1][j])
 
           else:
             for i in 0 .. identDefs.len - 3:
-              if identDefs[i].kind == nnkPragmaExpr and
-                identDefs[i][0].kind == nnkIdent and $identDefs[i][0] == $name:
-                return identDefs[i][1]
+              let varNode = identDefs[i]
+              if varNode.kind == nnkPragmaExpr:
+                var varName = varNode[0]
+                if varName.kind == nnkPostfix:
+                  # This is a public field. We are skipping the postfix *
+                  varName = varName[1]
+                if eqIdent(varName.strVal, name):
+                  return varNode[1]
 
         if obj[1].kind == nnkOfInherit: # explore the parent object
           typDef = getImpl(obj[1][0])
diff --git a/lib/packages/docutils/rst.nim b/lib/packages/docutils/rst.nim
index d35f109e7..161509afe 100644
--- a/lib/packages/docutils/rst.nim
+++ b/lib/packages/docutils/rst.nim
@@ -363,6 +363,12 @@ proc addNodes(n: PRstNode): string =
   addNodesAux(n, result)
 
 proc rstnodeToRefnameAux(n: PRstNode, r: var string, b: var bool) =
+  template special(s) =
+    if b:
+      add(r, '-')
+      b = false
+    add(r, s)
+
   if n == nil: return
   if n.kind == rnLeaf:
     for i in countup(0, len(n.text) - 1):
@@ -373,7 +379,7 @@ proc rstnodeToRefnameAux(n: PRstNode, r: var string, b: var bool) =
           b = false
         if len(r) == 0: add(r, 'Z')
         add(r, n.text[i])
-      of 'a'..'z':
+      of 'a'..'z', '\128'..'\255':
         if b:
           add(r, '-')
           b = false
@@ -383,8 +389,27 @@ proc rstnodeToRefnameAux(n: PRstNode, r: var string, b: var bool) =
           add(r, '-')
           b = false
         add(r, chr(ord(n.text[i]) - ord('A') + ord('a')))
+      of '$': special "dollar"
+      of '%': special "percent"
+      of '&': special "amp"
+      of '^': special "roof"
+      of '!': special "emark"
+      of '?': special "qmark"
+      of '*': special "star"
+      of '+': special "plus"
+      of '-': special "minus"
+      of '/': special "slash"
+      of '\\': special "backslash"
+      of '=': special "eq"
+      of '<': special "lt"
+      of '>': special "gt"
+      of '~': special "tilde"
+      of ':': special "colon"
+      of '.': special "dot"
+      of '@': special "at"
+      of '|': special "bar"
       else:
-        if (len(r) > 0): b = true
+        if len(r) > 0: b = true
   else:
     for i in countup(0, len(n) - 1): rstnodeToRefnameAux(n.sons[i], r, b)
 
diff --git a/lib/pure/strscans.nim b/lib/pure/strscans.nim
index 734317e67..77763ff43 100644
--- a/lib/pure/strscans.nim
+++ b/lib/pure/strscans.nim
@@ -317,8 +317,8 @@ macro scanf*(input: string; pattern: static[string]; results: varargs[typed]): b
 
   template at(s: string; i: int): char = (if i < s.len: s[i] else: '\0')
   template matchError() =
-    error("type mismatch between pattern '$" & pattern[p] & "' (position: " & $p & ") and " & repr(getType(results[i])) &
-          " var '" & repr(results[i]) & "'")
+    error("type mismatch between pattern '$" & pattern[p] & "' (position: " & $p &
+      ") and " & $getTypeInst(results[i]) & " var '" & repr(results[i]) & "'")
 
   var i = 0
   var p = 0
diff --git a/tests/ccgbugs/tcodegenbug1.nim b/tests/ccgbugs/tcodegenbug1.nim
index fce74de0c..012a4de47 100644
--- a/tests/ccgbugs/tcodegenbug1.nim
+++ b/tests/ccgbugs/tcodegenbug1.nim
@@ -2,7 +2,8 @@ discard """
   output: '''obj = (inner: (kind: Just, id: 7))
 obj.inner.id = 7
 id = 7
-obj = (inner: (kind: Just, id: 7))'''
+obj = (inner: (kind: Just, id: 7))
+2'''
 """
 
 # bug #6960
@@ -105,3 +106,35 @@ type
 
 proc bug5137(d: MyIntDistinct) =
   discard d.MyInt
+
+#-------------------------------------
+# bug #8979
+
+type
+  MyKind = enum
+    Fixed, Float
+
+  MyObject = object
+    someInt: int
+    case kind: MyKind
+      of Float: index: string
+      of Fixed: nil
+
+  MyResult = object
+    val: array[0..1, string]
+    vis: set[0..1]
+
+import macros
+
+func myfunc(obj: MyObject): MyResult {.raises: [].} =
+  template index: auto =
+    case obj.kind:
+      of Float: $obj.index 
+      of Fixed: "Fixed"
+  macro to_str(a: untyped): string =
+    result = newStrLitNode(a.repr)  
+  result.val[0] = index
+  result.val[1] = to_str(obj.kind + Ola)
+
+let x = MyObject(someInt: 10, kind: Fixed)
+echo myfunc(x).val.len
diff --git a/tests/openarray/t8259.nim b/tests/openarray/t8259.nim
new file mode 100644
index 000000000..40ff2b2f1
--- /dev/null
+++ b/tests/openarray/t8259.nim
@@ -0,0 +1,7 @@
+discard """
+  line: 6
+  errormsg: "invalid type: 'openarray[int]' for result"
+"""
+
+proc foo(a: openArray[int]):auto = a
+echo foo(toOpenArray([1, 2], 0, 2))
diff --git a/tests/pragmas/tcustom_pragma.nim b/tests/pragmas/tcustom_pragma.nim
index d7b199a22..ae0f39631 100644
--- a/tests/pragmas/tcustom_pragma.nim
+++ b/tests/pragmas/tcustom_pragma.nim
@@ -22,7 +22,7 @@ import custom_pragma
 block: # A bit more advanced case
   type
     Subfield {.defaultValue: "catman".} = object
-      c {.serializationKey: "cc".}: float
+      c* {.serializationKey: "cc".}: float
 
     MySerializable = object
       a {.serializationKey"asdf", defaultValue: 5.} : int
diff --git a/tests/stdlib/t8925.nim b/tests/stdlib/t8925.nim
new file mode 100644
index 000000000..d3dc1ea86
--- /dev/null
+++ b/tests/stdlib/t8925.nim
@@ -0,0 +1,16 @@
+discard """
+  file: "strscans.nim"
+  errormsg: "type mismatch between pattern '$i' (position: 1) and HourRange var 'hour'"
+"""
+
+import strscans
+
+type
+  HourRange = range[0..23]
+
+var
+  hour: HourRange
+  timeStr: string
+
+if scanf(timeStr, "$i", hour):
+  discard