summary refs log tree commit diff stats
diff options
context:
space:
mode:
-rw-r--r--compiler/cgmeth.nim3
-rw-r--r--compiler/hlo.nim2
-rw-r--r--compiler/parser.nim8
-rw-r--r--compiler/sem.nim12
-rw-r--r--compiler/semcall.nim2
-rw-r--r--compiler/semexprs.nim27
-rw-r--r--compiler/semfields.nim2
-rw-r--r--compiler/seminst.nim2
-rw-r--r--compiler/semstmts.nim12
-rw-r--r--compiler/semtypes.nim12
-rw-r--r--compiler/types.nim4
-rw-r--r--lib/pure/hashes.nim8
-rw-r--r--lib/pure/random.nim2
-rw-r--r--lib/pure/strutils.nim1
-rw-r--r--lib/pure/unittest.nim12
-rw-r--r--tests/collections/thashes.nim15
-rw-r--r--tests/errmsgs/tshow_asgn.nim15
-rw-r--r--tests/method/tgeneric_methods2.nim15
-rw-r--r--tests/pragmas/tused.nim32
-rw-r--r--tests/stdlib/tunittest.nim15
20 files changed, 144 insertions, 57 deletions
diff --git a/compiler/cgmeth.nim b/compiler/cgmeth.nim
index 1d7f5a6e1..d05e395b9 100644
--- a/compiler/cgmeth.nim
+++ b/compiler/cgmeth.nim
@@ -169,7 +169,8 @@ proc methodDef*(g: ModuleGraph; s: PSym, fromCache: bool) =
       fixupDispatcher(s, disp)
       #echo "fixup ", disp.name.s, " ", disp.id
       when useEffectSystem: checkMethodEffects(disp, s)
-      if sfBase in s.flags and g.methods[i].methods[0] != s:
+      if {sfBase, sfFromGeneric} * s.flags == {sfBase} and
+           g.methods[i].methods[0] != s:
         # already exists due to forwarding definition?
         localError(s.info, "method is not a base")
       return
diff --git a/compiler/hlo.nim b/compiler/hlo.nim
index de0fa6216..9491eef83 100644
--- a/compiler/hlo.nim
+++ b/compiler/hlo.nim
@@ -84,7 +84,7 @@ proc hlo(c: PContext, n: PNode): PNode =
       if isEmptyType(n.typ) and isEmptyType(result.typ):
         discard
       else:
-        result = fitNode(c, n.typ, result)
+        result = fitNode(c, n.typ, result, n.info)
       # optimization has been applied so check again:
       result = commonOptimizations(c.module, result)
       result = hlo(c, result)
diff --git a/compiler/parser.nim b/compiler/parser.nim
index 902bf0fcb..272c1b15f 100644
--- a/compiler/parser.nim
+++ b/compiler/parser.nim
@@ -514,12 +514,12 @@ proc parsePar(p: var TParser): PNode =
     var a = simpleExpr(p)
     if p.tok.tokType == tkEquals:
       # special case: allow assignments
+      let asgn = newNodeP(nkAsgn, p)
       getTok(p)
       optInd(p, result)
       let b = parseExpr(p)
-      let asgn = newNodeI(nkAsgn, a.info, 2)
-      asgn.sons[0] = a
-      asgn.sons[1] = b
+      asgn.add a
+      asgn.add b
       result.add(asgn)
       if p.tok.tokType == tkSemiColon:
         semiStmtList(p, result)
@@ -1184,10 +1184,10 @@ proc parseExprStmt(p: var TParser): PNode =
   #|            ))?
   var a = simpleExpr(p)
   if p.tok.tokType == tkEquals:
+    result = newNodeP(nkAsgn, p)
     getTok(p)
     optInd(p, result)
     var b = parseExpr(p)
-    result = newNodeI(nkAsgn, a.info)
     addSon(result, a)
     addSon(result, b)
   else:
diff --git a/compiler/sem.nim b/compiler/sem.nim
index 682e9d0ca..8da5d4707 100644
--- a/compiler/sem.nim
+++ b/compiler/sem.nim
@@ -32,7 +32,7 @@ proc semExprNoType(c: PContext, n: PNode): PNode
 proc semExprNoDeref(c: PContext, n: PNode, flags: TExprFlags = {}): PNode
 proc semProcBody(c: PContext, n: PNode): PNode
 
-proc fitNode(c: PContext, formal: PType, arg: PNode): PNode
+proc fitNode(c: PContext, formal: PType, arg: PNode; info: TLineInfo): PNode
 proc changeType(n: PNode, newType: PType, check: bool)
 
 proc semLambda(c: PContext, n: PNode, flags: TExprFlags): PNode
@@ -69,7 +69,7 @@ template semIdeForTemplateOrGeneric(c: PContext; n: PNode;
       #  echo "passing to safeSemExpr: ", renderTree(n)
       discard safeSemExpr(c, n)
 
-proc fitNode(c: PContext, formal: PType, arg: PNode): PNode =
+proc fitNode(c: PContext, formal: PType, arg: PNode; info: TLineInfo): PNode =
   if arg.typ.isNil:
     localError(arg.info, errExprXHasNoType,
                renderTree(arg, {renderNoComments}))
@@ -79,7 +79,7 @@ proc fitNode(c: PContext, formal: PType, arg: PNode): PNode =
   else:
     result = indexTypesMatch(c, formal, arg.typ, arg)
     if result == nil:
-      typeMismatch(arg, formal, arg.typ)
+      typeMismatch(info, formal, arg.typ)
       # error correction:
       result = copyTree(arg)
       result.typ = formal
@@ -367,7 +367,7 @@ proc semAfterMacroCall(c: PContext, n: PNode, s: PSym,
       #result = symNodeFromType(c, typ, n.info)
     else:
       result = semExpr(c, result, flags)
-      result = fitNode(c, s.typ.sons[0], result)
+      result = fitNode(c, s.typ.sons[0], result, result.info)
       #GlobalError(s.info, errInvalidParamKindX, typeToString(s.typ.sons[0]))
   dec(evalTemplateCounter)
   discard c.friendModules.pop()
@@ -390,12 +390,12 @@ proc semMacroExpr(c: PContext, n, nOrig: PNode, sym: PSym,
   popInfoContext()
 
 proc forceBool(c: PContext, n: PNode): PNode =
-  result = fitNode(c, getSysType(tyBool), n)
+  result = fitNode(c, getSysType(tyBool), n, n.info)
   if result == nil: result = n
 
 proc semConstBoolExpr(c: PContext, n: PNode): PNode =
   let nn = semExprWithType(c, n)
-  result = fitNode(c, getSysType(tyBool), nn)
+  result = fitNode(c, getSysType(tyBool), nn, nn.info)
   if result == nil:
     localError(n.info, errConstExprExpected)
     return nn
diff --git a/compiler/semcall.nim b/compiler/semcall.nim
index fe73d60e6..98667b085 100644
--- a/compiler/semcall.nim
+++ b/compiler/semcall.nim
@@ -327,7 +327,7 @@ proc inferWithMetatype(c: PContext, formal: PType,
     result.typ = generateTypeInstance(c, m.bindings, arg.info,
                                       formal.skipTypes({tyCompositeTypeClass}))
   else:
-    typeMismatch(arg, formal, arg.typ)
+    typeMismatch(arg.info, formal, arg.typ)
     # error correction:
     result = copyTree(arg)
     result.typ = formal
diff --git a/compiler/semexprs.nim b/compiler/semexprs.nim
index 6db7724f9..ba60442d6 100644
--- a/compiler/semexprs.nim
+++ b/compiler/semexprs.nim
@@ -194,13 +194,13 @@ proc semConv(c: PContext, n: PNode): PNode =
     of convOK:
       # handle SomeProcType(SomeGenericProc)
       if op.kind == nkSym and op.sym.isGenericRoutine:
-        result.sons[1] = fitNode(c, result.typ, result.sons[1])
+        result.sons[1] = fitNode(c, result.typ, result.sons[1], result.info)
       elif op.kind == nkPar and targetType.kind == tyTuple:
-        op = fitNode(c, targetType, op)
+        op = fitNode(c, targetType, op, result.info)
     of convNotNeedeed:
       message(n.info, hintConvFromXtoItselfNotNeeded, result.typ.typeToString)
     of convNotLegal:
-      result = fitNode(c, result.typ, result.sons[1])
+      result = fitNode(c, result.typ, result.sons[1], result.info)
       if result == nil:
         localError(n.info, errGenerated, msgKindToString(errIllegalConvFromXtoY)%
           [op.typ.typeToString, result.typ.typeToString])
@@ -445,7 +445,7 @@ proc semArrayConstr(c: PContext, n: PNode, flags: TExprFlags): PNode =
       x = n.sons[i]
       if x.kind == nkExprColonExpr and sonsLen(x) == 2:
         var idx = semConstExpr(c, x.sons[0])
-        idx = fitNode(c, indexType, idx)
+        idx = fitNode(c, indexType, idx, x.info)
         if lastIndex+1 != getOrdValue(idx):
           localError(x.info, errInvalidOrderInArrayConstructor)
         x = x.sons[1]
@@ -458,7 +458,7 @@ proc semArrayConstr(c: PContext, n: PNode, flags: TExprFlags): PNode =
       inc(lastIndex)
     addSonSkipIntLit(result.typ, typ)
     for i in 0 .. <result.len:
-      result.sons[i] = fitNode(c, typ, result.sons[i])
+      result.sons[i] = fitNode(c, typ, result.sons[i], result.sons[i].info)
   result.typ.sons[0] = makeRangeType(c, 0, sonsLen(result) - 1, n.info)
 
 proc fixAbstractType(c: PContext, n: PNode) =
@@ -1393,9 +1393,9 @@ proc semAsgn(c: PContext, n: PNode; mode=asgnNormal): PNode =
           c.p.resultSym.typ = rhs.typ
           c.p.owner.typ.sons[0] = rhs.typ
         else:
-          typeMismatch(n, lhs.typ, rhs.typ)
+          typeMismatch(n.info, lhs.typ, rhs.typ)
 
-    n.sons[1] = fitNode(c, le, rhs)
+    n.sons[1] = fitNode(c, le, rhs, n.info)
     if tfHasAsgn in lhs.typ.flags and not lhsIsResult and
         mode != noOverloadedAsgn:
       return overloadedAsgn(c, lhs, n.sons[1])
@@ -1494,7 +1494,7 @@ proc semYield(c: PContext, n: PNode): PNode =
     let restype = iterType.sons[0]
     if restype != nil:
       if restype.kind != tyExpr:
-        n.sons[0] = fitNode(c, restype, n.sons[0])
+        n.sons[0] = fitNode(c, restype, n.sons[0], n.info)
       if n.sons[0].typ == nil: internalError(n.info, "semYield")
 
       if resultTypeIsInferrable(restype):
@@ -1929,13 +1929,14 @@ proc semSetConstr(c: PContext, n: PNode): PNode =
     addSonSkipIntLit(result.typ, typ)
     for i in countup(0, sonsLen(n) - 1):
       var m: PNode
+      let info = n.sons[i].info
       if isRange(n.sons[i]):
-        m = newNodeI(nkRange, n.sons[i].info)
-        addSon(m, fitNode(c, typ, n.sons[i].sons[1]))
-        addSon(m, fitNode(c, typ, n.sons[i].sons[2]))
+        m = newNodeI(nkRange, info)
+        addSon(m, fitNode(c, typ, n.sons[i].sons[1], info))
+        addSon(m, fitNode(c, typ, n.sons[i].sons[2], info))
       elif n.sons[i].kind == nkRange: m = n.sons[i] # already semchecked
       else:
-        m = fitNode(c, typ, n.sons[i])
+        m = fitNode(c, typ, n.sons[i], info)
       addSon(result, m)
 
 proc semTableConstr(c: PContext, n: PNode): PNode =
@@ -2081,7 +2082,7 @@ proc semObjConstr(c: PContext, n: PNode, flags: TExprFlags): PNode =
       t = skipTypes(t.sons[0], skipPtrs)
     if f != nil and fieldVisible(c, f):
       it.sons[0] = newSymNode(f)
-      e = fitNode(c, f.typ, e)
+      e = fitNode(c, f.typ, e, it.info)
       # small hack here in a nkObjConstr the ``nkExprColonExpr`` node can have
       # 3 children the last being the field check
       if check != nil:
diff --git a/compiler/semfields.nim b/compiler/semfields.nim
index 5ac1ad11a..06826ef75 100644
--- a/compiler/semfields.nim
+++ b/compiler/semfields.nim
@@ -128,7 +128,7 @@ proc semForFields(c: PContext, n: PNode, m: TMagic): PNode =
   for i in 1..call.len-1:
     var tupleTypeB = skipTypes(call.sons[i].typ, abstractVar-{tyTypeDesc})
     if not sameType(tupleTypeA, tupleTypeB):
-      typeMismatch(call.sons[i], tupleTypeA, tupleTypeB)
+      typeMismatch(call.sons[i].info, tupleTypeA, tupleTypeB)
 
   inc(c.p.nestedLoopCounter)
   if tupleTypeA.kind == tyTuple:
diff --git a/compiler/seminst.nim b/compiler/seminst.nim
index 82d27cf10..78dd7efe5 100644
--- a/compiler/seminst.nim
+++ b/compiler/seminst.nim
@@ -209,7 +209,7 @@ proc instantiateProcType(c: PContext, pt: TIdTable,
       param.owner = prc
       param.typ = result.sons[i]
       if oldParam.ast != nil:
-        param.ast = fitNode(c, param.typ, oldParam.ast)
+        param.ast = fitNode(c, param.typ, oldParam.ast, oldParam.ast.info)
 
       # don't be lazy here and call replaceTypeVarsN(cl, originalParams[i])!
       result.n.sons[i] = newSymNode(param)
diff --git a/compiler/semstmts.nim b/compiler/semstmts.nim
index c28dbf82f..0507ed504 100644
--- a/compiler/semstmts.nim
+++ b/compiler/semstmts.nim
@@ -191,7 +191,7 @@ proc semIf(c: PContext, n: PNode): PNode =
   else:
     for it in n:
       let j = it.len-1
-      it.sons[j] = fitNode(c, typ, it.sons[j])
+      it.sons[j] = fitNode(c, typ, it.sons[j], it.sons[j].info)
     result.kind = nkIfExpr
     result.typ = typ
 
@@ -257,7 +257,7 @@ proc semCase(c: PContext, n: PNode): PNode =
     for i in 1..n.len-1:
       var it = n.sons[i]
       let j = it.len-1
-      it.sons[j] = fitNode(c, typ, it.sons[j])
+      it.sons[j] = fitNode(c, typ, it.sons[j], it.sons[j].info)
     result.typ = typ
 
 proc semTry(c: PContext, n: PNode): PNode =
@@ -330,15 +330,15 @@ proc semTry(c: PContext, n: PNode): PNode =
       result.typ = enforceVoidContext
   else:
     if n.lastSon.kind == nkFinally: discardCheck(c, n.lastSon.lastSon)
-    n.sons[0] = fitNode(c, typ, n.sons[0])
+    n.sons[0] = fitNode(c, typ, n.sons[0], n.sons[0].info)
     for i in 1..last:
       var it = n.sons[i]
       let j = it.len-1
-      it.sons[j] = fitNode(c, typ, it.sons[j])
+      it.sons[j] = fitNode(c, typ, it.sons[j], it.sons[j].info)
     result.typ = typ
 
 proc fitRemoveHiddenConv(c: PContext, typ: PType, n: PNode): PNode =
-  result = fitNode(c, typ, n)
+  result = fitNode(c, typ, n, n.info)
   if result.kind in {nkHiddenStdConv, nkHiddenSubConv}:
     let r1 = result.sons[1]
     if r1.kind in {nkCharLit..nkUInt64Lit} and typ.skipTypes(abstractRange).kind in {tyFloat..tyFloat128}:
@@ -492,7 +492,7 @@ proc semVarOrLet(c: PContext, n: PNode, symkind: TSymKind): PNode =
         else:
           # BUGFIX: ``fitNode`` is needed here!
           # check type compatibility between def.typ and typ
-          def = fitNode(c, typ, def)
+          def = fitNode(c, typ, def, def.info)
           #changeType(def.skipConv, typ, check=true)
       else:
         typ = skipIntLit(def.typ)
diff --git a/compiler/semtypes.nim b/compiler/semtypes.nim
index 97af2c5cc..77ccce5d4 100644
--- a/compiler/semtypes.nim
+++ b/compiler/semtypes.nim
@@ -449,8 +449,8 @@ proc semBranchRange(c: PContext, t, a, b: PNode, covered: var BiggestInt): PNode
   checkMinSonsLen(t, 1)
   let ac = semConstExpr(c, a)
   let bc = semConstExpr(c, b)
-  let at = fitNode(c, t.sons[0].typ, ac).skipConvTakeType
-  let bt = fitNode(c, t.sons[0].typ, bc).skipConvTakeType
+  let at = fitNode(c, t.sons[0].typ, ac, ac.info).skipConvTakeType
+  let bt = fitNode(c, t.sons[0].typ, bc, bc.info).skipConvTakeType
 
   result = newNodeI(nkRange, a.info)
   result.add(at)
@@ -472,7 +472,7 @@ proc semCaseBranchSetElem(c: PContext, t, b: PNode,
     checkSonsLen(b, 2)
     result = semBranchRange(c, t, b.sons[0], b.sons[1], covered)
   else:
-    result = fitNode(c, t.sons[0].typ, b)
+    result = fitNode(c, t.sons[0].typ, b, b.info)
     inc(covered)
 
 proc semCaseBranch(c: PContext, t, branch: PNode, branchIndex: int,
@@ -493,7 +493,7 @@ proc semCaseBranch(c: PContext, t, branch: PNode, branchIndex: int,
         return
       elif r.kind notin {nkCurly, nkBracket} or len(r) == 0:
         checkMinSonsLen(t, 1)
-        branch.sons[i] = skipConv(fitNode(c, t.sons[0].typ, r))
+        branch.sons[i] = skipConv(fitNode(c, t.sons[0].typ, r, r.info))
         inc(covered)
       else:
         # first element is special and will overwrite: branch.sons[i]:
@@ -947,7 +947,7 @@ proc semProcTypeNode(c: PContext, n, genericParams: PNode,
         # example code that triggers it:
         # proc sort[T](cmp: proc(a, b: T): int = cmp)
         if not containsGenericType(typ):
-          def = fitNode(c, typ, def)
+          def = fitNode(c, typ, def, def.info)
     if not hasType and not hasDefault:
       if isType: localError(a.info, "':' expected")
       if kind in {skTemplate, skMacro}:
@@ -1479,7 +1479,7 @@ proc semGenericParamList(c: PContext, n: PNode, father: PType = nil): PNode =
         # from manyloc/named_argument_bug/triengine:
         def.typ = def.typ.skipTypes({tyTypeDesc})
         if not containsGenericType(def.typ):
-          def = fitNode(c, typ, def)
+          def = fitNode(c, typ, def, def.info)
 
     if typ == nil:
       typ = newTypeS(tyGenericParam, c)
diff --git a/compiler/types.nim b/compiler/types.nim
index b237753ae..df1d3e3ca 100644
--- a/compiler/types.nim
+++ b/compiler/types.nim
@@ -1515,7 +1515,7 @@ proc skipHiddenSubConv*(n: PNode): PNode =
   else:
     result = n
 
-proc typeMismatch*(n: PNode, formal, actual: PType) =
+proc typeMismatch*(info: TLineInfo, formal, actual: PType) =
   if formal.kind != tyError and actual.kind != tyError:
     let named = typeToString(formal)
     let desc = typeToString(formal, preferDesc)
@@ -1537,4 +1537,4 @@ proc typeMismatch*(n: PNode, formal, actual: PType) =
         msg.add "\n.tag effect is 'any tag allowed'"
       of efLockLevelsDiffer:
         msg.add "\nlock levels differ"
-    localError(n.info, errGenerated, msg)
+    localError(info, errGenerated, msg)
diff --git a/lib/pure/hashes.nim b/lib/pure/hashes.nim
index 17d1c6442..d5759e507 100644
--- a/lib/pure/hashes.nim
+++ b/lib/pure/hashes.nim
@@ -112,6 +112,14 @@ proc hash*(x: int64): Hash {.inline.} =
   ## efficient hashing of int64 integers
   result = toU32(x)
 
+proc hash*(x: uint): Hash {.inline.} =
+  ## efficient hashing of unsigned integers
+  result = cast[int](x)
+
+proc hash*(x: uint64): Hash {.inline.} =
+  ## efficient hashing of uint64 integers
+  result = toU32(cast[int](x))
+
 proc hash*(x: char): Hash {.inline.} =
   ## efficient hashing of characters
   result = ord(x)
diff --git a/lib/pure/random.nim b/lib/pure/random.nim
index 8d463576a..1f750edcd 100644
--- a/lib/pure/random.nim
+++ b/lib/pure/random.nim
@@ -95,7 +95,7 @@ proc random*(max: float): float {.benign.} =
 
 proc random*[T](x: Slice[T]): T =
   ## For a slice `a .. b` returns a value in the range `a .. b-1`.
-  result = random(x.b - x.a) + x.a
+  result = T(random(x.b - x.a)) + x.a
 
 proc random*[T](a: openArray[T]): T =
   ## returns a random element from the openarray `a`.
diff --git a/lib/pure/strutils.nim b/lib/pure/strutils.nim
index 9c9da92c6..9b2526337 100644
--- a/lib/pure/strutils.nim
+++ b/lib/pure/strutils.nim
@@ -1652,6 +1652,7 @@ proc escape*(s: string, prefix = "\"", suffix = "\""): string {.noSideEffect,
   ## The procedure has been designed so that its output is usable for many
   ## different common syntaxes. The resulting string is prefixed with
   ## `prefix` and suffixed with `suffix`. Both may be empty strings.
+  ## **Note**: This is not correct for producing Ansi C code!
   result = newStringOfCap(s.len + s.len shr 2)
   result.add(prefix)
   for c in items(s):
diff --git a/lib/pure/unittest.nim b/lib/pure/unittest.nim
index 01af0f839..49e24037a 100644
--- a/lib/pure/unittest.nim
+++ b/lib/pure/unittest.nim
@@ -95,7 +95,7 @@ proc shouldRun(testName: string): bool =
   result = true
 
 proc startSuite(name: string) =
-  template rawPrint() = echo("\n[Suite] ", name) 
+  template rawPrint() = echo("\n[Suite] ", name)
   when not defined(ECMAScript):
     if colorOutput:
       styledEcho styleBright, fgBlue, "\n[Suite] ", resetStyle, name
@@ -134,15 +134,15 @@ template suite*(name, body) {.dirty.} =
   ##    [OK] (2 + -2) != 4
   block:
     bind startSuite
-    template setup(setupBody: untyped) {.dirty.} =
-      var testSetupIMPLFlag = true
+    template setup(setupBody: untyped) {.dirty, used.} =
+      var testSetupIMPLFlag {.used.} = true
       template testSetupIMPL: untyped {.dirty.} = setupBody
 
-    template teardown(teardownBody: untyped) {.dirty.} =
-      var testTeardownIMPLFlag = true
+    template teardown(teardownBody: untyped) {.dirty, used.} =
+      var testTeardownIMPLFlag {.used.} = true
       template testTeardownIMPL: untyped {.dirty.} = teardownBody
 
-    let testInSuiteImplFlag = true
+    let testInSuiteImplFlag {.used.} = true
     startSuite name
     body
 
diff --git a/tests/collections/thashes.nim b/tests/collections/thashes.nim
index b9c639414..76b99313c 100644
--- a/tests/collections/thashes.nim
+++ b/tests/collections/thashes.nim
@@ -72,4 +72,19 @@ block:
   var t = initTable[int, int]()
   t[0] = 0
 
+# Check hashability of all integer types (issue #5429)
+block:
+  let intTables = (
+    newTable[int, string](),
+    newTable[int8, string](),
+    newTable[int16, string](),
+    newTable[int32, string](),
+    newTable[int64, string](),
+    newTable[uint, string](),
+    newTable[uint8, string](),
+    newTable[uint16, string](),
+    newTable[uint32, string](),
+    newTable[uint64, string](),
+  )
+
 echo "true"
diff --git a/tests/errmsgs/tshow_asgn.nim b/tests/errmsgs/tshow_asgn.nim
new file mode 100644
index 000000000..250f786e2
--- /dev/null
+++ b/tests/errmsgs/tshow_asgn.nim
@@ -0,0 +1,15 @@
+discard """
+  errormsg: "type mismatch: got (int) but expected 'cshort = int16'"
+  line: 12
+  column: 10
+  file: "tshow_asgn.nim"
+"""
+
+# bug #5430
+
+proc random*[T](x: Slice[T]): T =
+  ## For a slice `a .. b` returns a value in the range `a .. b-1`.
+  result = int(x.b - x.a) + x.a
+
+let slice = 10.cshort..15.cshort
+discard slice.random
diff --git a/tests/method/tgeneric_methods2.nim b/tests/method/tgeneric_methods2.nim
new file mode 100644
index 000000000..6e761dc48
--- /dev/null
+++ b/tests/method/tgeneric_methods2.nim
@@ -0,0 +1,15 @@
+#5432
+type
+  Iterator[T] = ref object of RootObj
+
+# base methods with `T` in the return type are okay
+method methodThatWorks*[T](i: Iterator[T]): T {.base.} =
+  discard
+
+# base methods without `T` (void or basic types) fail
+method methodThatFails*[T](i: Iterator[T]) {.base.} =
+  discard
+
+type
+  SpecificIterator1 = ref object of Iterator[string]
+  SpecificIterator2 = ref object of Iterator[int]
diff --git a/tests/pragmas/tused.nim b/tests/pragmas/tused.nim
index f3126bd45..4a317f874 100644
--- a/tests/pragmas/tused.nim
+++ b/tests/pragmas/tused.nim
@@ -1,13 +1,35 @@
 discard """
-  output: '''8'''
+  nimout: '''
+compile start
+tused.nim(15, 8) Hint: 'tused.echoSub(a: int, b: int)' is declared but not used [XDeclaredButNotUsed]
+compile end'''
+  output: "8\n8"
 """
 
-template implementArithOps(T) =
+static:
+  echo "compile start"
+
+template implementArithOpsOld(T) =
+  proc echoAdd(a, b: T) =
+    echo a + b
+  proc echoSub(a, b: T) =
+    echo a - b
+
+template implementArithOpsNew(T) =
   proc echoAdd(a, b: T) {.used.} =
     echo a + b
   proc echoSub(a, b: T) {.used.} =
     echo a - b
 
-# no warning produced for the unused 'echoSub'
-implementArithOps(int)
-echoAdd 3, 5
+block:
+  # should produce warning for the unused 'echoSub'
+  implementArithOpsOld(int)
+  echoAdd 3, 5
+
+block:
+  # no warning produced for the unused 'echoSub'
+  implementArithOpsNew(int)
+  echoAdd 3, 5
+
+static:
+  echo "compile end"
diff --git a/tests/stdlib/tunittest.nim b/tests/stdlib/tunittest.nim
index e87cd3508..3f8601323 100644
--- a/tests/stdlib/tunittest.nim
+++ b/tests/stdlib/tunittest.nim
@@ -1,5 +1,11 @@
+discard """
+  nimout: "compile start\ncompile end"
+"""
+
 import unittest, sequtils
 
+static:
+  echo "compile start"
 
 proc doThings(spuds: var int): int =
   spuds = 24
@@ -10,9 +16,9 @@ test "#964":
   check spuds == 24
 
 
-from strutils import toUpper
+from strutils import toUpperAscii
 test "#1384":
-  check(@["hello", "world"].map(toUpper) == @["HELLO", "WORLD"])
+  check(@["hello", "world"].map(toUpperAscii) == @["HELLO", "WORLD"])
 
 
 import options
@@ -57,7 +63,7 @@ suite "suite with only teardown":
 
 suite "suite with only setup":
   setup:
-    var testVar = "from setup"
+    var testVar {.used.} = "from setup"
 
   test "unittest with only setup 1":
     check testVar == "from setup"
@@ -89,3 +95,6 @@ suite "bug #4494":
       var tags = @[1, 2, 3, 4, 5]
       check:
         allIt(0..3, tags[it] != tags[it + 1])
+
+static:
+  echo "compile end"