summary refs log tree commit diff stats
diff options
context:
space:
mode:
authorJasper Jenkins <jasper.vs.jenkins@gmail.com>2020-01-17 01:34:32 -0800
committerAndreas Rumpf <rumpf_a@web.de>2020-01-17 10:34:31 +0100
commit796aafe7e0856375494a352f738ac14f8de9fd4d (patch)
tree9d2036631f60bd27d7d01296a7b0494e9a7a792e
parent2bf337abaefe862bc7e05cc0c907a3095b1f429c (diff)
downloadNim-796aafe7e0856375494a352f738ac14f8de9fd4d.tar.gz
make case-object transitions explicit, make unknownLineInfo a const, replace a few magic numbers with consts (#13170)
-rw-r--r--compiler/ast.nim94
-rw-r--r--compiler/canonicalizer.nim4
-rw-r--r--compiler/ccgexprs.nim12
-rw-r--r--compiler/ccgstmts.nim2
-rw-r--r--compiler/ccgtrav.nim4
-rw-r--r--compiler/ccgtypes.nim2
-rw-r--r--compiler/cgen.nim2
-rw-r--r--compiler/cgmeth.nim6
-rw-r--r--compiler/closureiters.nim2
-rw-r--r--compiler/lambdalifting.nim6
-rw-r--r--compiler/lineinfos.nim8
-rw-r--r--compiler/lowerings.nim2
-rw-r--r--compiler/modulegraphs.nim2
-rw-r--r--compiler/modules.nim10
-rw-r--r--compiler/msgs.nim10
-rw-r--r--compiler/nim.cfg5
-rw-r--r--compiler/nimblecmd.nim20
-rw-r--r--compiler/parser.nim18
-rw-r--r--compiler/pragmas.nim2
-rw-r--r--compiler/rodimpl.nim10
-rw-r--r--compiler/sem.nim2
-rw-r--r--compiler/semexprs.nim14
-rw-r--r--compiler/semfold.nim2
-rw-r--r--compiler/semgnrc.nim2
-rw-r--r--compiler/semstmts.nim18
-rw-r--r--compiler/semtypes.nim10
-rw-r--r--compiler/sigmatch.nim14
-rw-r--r--compiler/sizealignoffsetimpl.nim4
-rw-r--r--compiler/vm.nim77
-rw-r--r--compiler/vmdef.nim2
-rw-r--r--compiler/vmhooks.nim16
-rw-r--r--compiler/vmmarshal.nim2
-rw-r--r--nimpretty/nimpretty.nim.cfg1
-rw-r--r--nimsuggest/nimsuggest.nim.cfg1
-rw-r--r--tests/compilerapi/tcompilerapi.nim.cfg1
35 files changed, 183 insertions, 204 deletions
diff --git a/compiler/ast.nim b/compiler/ast.nim
index 2cdf40a8f..733f60090 100644
--- a/compiler/ast.nim
+++ b/compiler/ast.nim
@@ -1020,6 +1020,10 @@ const
   skProcKinds* = {skProc, skFunc, skTemplate, skMacro, skIterator,
                   skMethod, skConverter}
 
+  defaultSize = -1
+  defaultAlignment = -1
+  defaultOffset = -1
+
 var ggDebug* {.deprecated.}: bool ## convenience switch for trying out things
 #var
 #  gMainPackageId*: int
@@ -1066,12 +1070,7 @@ when defined(useNodeIds):
   var gNodeId: int
 
 proc newNode*(kind: TNodeKind): PNode =
-  new(result)
-  result.kind = kind
-  #result.info = UnknownLineInfo() inlined:
-  result.info.fileIndex = InvalidFileIdx
-  result.info.col = int16(-1)
-  result.info.line = uint16(0)
+  result = PNode(kind: kind, info: unknownLineInfo)
   when defined(useNodeIds):
     result.id = gNodeId
     if result.id == nodeIdToDebug:
@@ -1091,15 +1090,8 @@ template previouslyInferred*(t: PType): PType =
 proc newSym*(symKind: TSymKind, name: PIdent, owner: PSym,
              info: TLineInfo; options: TOptions = {}): PSym =
   # generates a symbol and initializes the hash field too
-  new(result)
-  result.name = name
-  result.kind = symKind
-  result.flags = {}
-  result.info = info
-  result.options = options
-  result.owner = owner
-  result.offset = -1
-  result.id = getID()
+  result = PSym(name: name, kind: symKind, flags: {}, info: info, id: getID(),
+                options: options, owner: owner, offset: defaultOffset)
   when debugIds:
     registerId(result)
 
@@ -1193,9 +1185,7 @@ proc newSymNode*(sym: PSym, info: TLineInfo): PNode =
   result.info = info
 
 proc newNodeI*(kind: TNodeKind, info: TLineInfo): PNode =
-  new(result)
-  result.kind = kind
-  result.info = info
+  result = PNode(kind: kind, info: info)
   when defined(useNodeIds):
     result.id = gNodeId
     if result.id == nodeIdToDebug:
@@ -1204,9 +1194,7 @@ proc newNodeI*(kind: TNodeKind, info: TLineInfo): PNode =
     inc gNodeId
 
 proc newNodeI*(kind: TNodeKind, info: TLineInfo, children: int): PNode =
-  new(result)
-  result.kind = kind
-  result.info = info
+  result = PNode(kind: kind, info: info)
   if children > 0:
     newSeq(result.sons, children)
   when defined(useNodeIds):
@@ -1217,12 +1205,9 @@ proc newNodeI*(kind: TNodeKind, info: TLineInfo, children: int): PNode =
     inc gNodeId
 
 proc newNode*(kind: TNodeKind, info: TLineInfo, sons: TNodeSeq = @[],
-             typ: PType = nil): PNode =
-  new(result)
-  result.kind = kind
-  result.info = info
-  result.typ = typ
+              typ: PType = nil): PNode =
   # XXX use shallowCopy here for ownership transfer:
+  result = PNode(kind: kind, info: info, typ: typ)
   result.sons = sons
   when defined(useNodeIds):
     result.id = gNodeId
@@ -1321,14 +1306,10 @@ proc `$`*(s: PSym): string =
     result = "<nil>"
 
 proc newType*(kind: TTypeKind, owner: PSym): PType =
-  new(result)
-  result.kind = kind
-  result.owner = owner
-  result.size = -1
-  result.align = -1            # default alignment
-  result.id = getID()
-  result.uniqueId = result.id
-  result.lockLevel = UnspecifiedLockLevel
+  let id = getID()
+  result = PType(kind: kind, owner: owner, size: defaultSize,
+                 align: defaultAlignment, id: id, uniqueId: id,
+                 lockLevel: UnspecifiedLockLevel)
   when debugIds:
     registerId(result)
   when false:
@@ -1543,6 +1524,51 @@ proc copyNode*(src: PNode): PNode =
   of nkStrLit..nkTripleStrLit: result.strVal = src.strVal
   else: discard
 
+template transitionNodeKindCommon(k: TNodeKind) =
+  let obj {.inject.} = n[]
+  n[] = TNode(kind: k, typ: obj.typ, info: obj.info, flags: obj.flags,
+              comment: obj.comment)
+  when defined(useNodeIds):
+    n.id = obj.id
+
+proc transitionSonsKind*(n: PNode, kind: range[nkComesFrom..nkTupleConstr]) =
+  transitionNodeKindCommon(kind)
+  n.sons = obj.sons
+
+proc transitionIntKind*(n: PNode, kind: range[nkCharLit..nkUInt64Lit]) =
+  transitionNodeKindCommon(kind)
+  n.intVal = obj.intVal
+
+proc transitionNoneToSym*(n: PNode) =
+  transitionNodeKindCommon(nkSym)
+
+template transitionSymKindCommon*(k: TSymKind) =
+  let obj {.inject.} = s[]
+  s[] = TSym(kind: k, id: obj.id, magic: obj.magic, typ: obj.typ, name: obj.name,
+             info: obj.info, owner: obj.owner, flags: obj.flags, ast: obj.ast,
+             options: obj.options, position: obj.position, offset: obj.offset,
+             loc: obj.loc, annex: obj.annex, constraint: obj.constraint)
+  when hasFFI:
+    s.cname = obj.cname
+  when defined(nimsuggest):
+    s.allUsages = obj.allUsages
+
+proc transitionGenericParamToType*(s: PSym) =
+  transitionSymKindCommon(skType)
+  s.typeInstCache = obj.typeInstCache
+
+proc transitionRoutineSymKind*(s: PSym, kind: range[skProc..skTemplate]) =
+  transitionSymKindCommon(kind)
+  s.procInstCache = obj.procInstCache
+  s.gcUnsafetyReason = obj.gcUnsafetyReason
+  s.transformedBody = obj.transformedBody
+
+proc transitionToLet*(s: PSym) =
+  transitionSymKindCommon(skLet)
+  s.guard = obj.guard
+  s.bitsize = obj.bitsize
+  s.alignment = obj.alignment
+
 proc shallowCopy*(src: PNode): PNode =
   # does not copy its sons, but provides space for them:
   if src == nil: return nil
diff --git a/compiler/canonicalizer.nim b/compiler/canonicalizer.nim
index 76c2872f7..de0d0f30e 100644
--- a/compiler/canonicalizer.nim
+++ b/compiler/canonicalizer.nim
@@ -282,7 +282,7 @@ proc encodeType(w: PRodWriter, t: PType, result: var string) =
   result.add('+')
   encodeVInt(t.id, result)
   if t.n != nil:
-    encodeNode(w, unknownLineInfo(), t.n, result)
+    encodeNode(w, unknownLineInfo, t.n, result)
   if t.flags != {}:
     result.add('$')
     encodeVInt(cast[int32](t.flags), result)
@@ -364,7 +364,7 @@ proc encodeSym(w: PRodWriter, s: PSym, result: var string) =
   if s.annex != nil: encodeLib(w, s.annex, s.info, result)
   if s.constraint != nil:
     result.add('#')
-    encodeNode(w, unknownLineInfo(), s.constraint, result)
+    encodeNode(w, unknownLineInfo, s.constraint, result)
   # lazy loading will soon reload the ast lazily, so the ast needs to be
   # the last entry of a symbol:
   if s.ast != nil:
diff --git a/compiler/ccgexprs.nim b/compiler/ccgexprs.nim
index fb29a9907..87a936048 100644
--- a/compiler/ccgexprs.nim
+++ b/compiler/ccgexprs.nim
@@ -1457,7 +1457,7 @@ proc genArrToSeq(p: BProc, n: PNode, d: var TLoc) =
       genAssignment(p, elem, arr, {needToCopy})
   else:
     var i: TLoc
-    getTemp(p, getSysType(p.module.g.graph, unknownLineInfo(), tyInt), i)
+    getTemp(p, getSysType(p.module.g.graph, unknownLineInfo, tyInt), i)
     linefmt(p, cpsStmts, "for ($1 = 0; $1 < $2; $1++) {$n",  [i.r, L])
     initLoc(elem, locExpr, lodeTyp elemType(skipTypes(n.typ, abstractInst)), OnHeap)
     elem.r = ropecg(p.module, "$1$3[$2]", [rdLoc(d), rdLoc(i), dataField(p)])
@@ -1847,10 +1847,10 @@ proc genSetOp(p: BProc, e: PNode, d: var TLoc, op: TMagic) =
       initLocExpr(p, e[1], a)
       putIntoDest(p, d, e, ropecg(p.module, "#cardSet($1, $2)", [rdCharLoc(a), size]))
     of mLtSet, mLeSet:
-      getTemp(p, getSysType(p.module.g.graph, unknownLineInfo(), tyInt), i) # our counter
+      getTemp(p, getSysType(p.module.g.graph, unknownLineInfo, tyInt), i) # our counter
       initLocExpr(p, e[1], a)
       initLocExpr(p, e[2], b)
-      if d.k == locNone: getTemp(p, getSysType(p.module.g.graph, unknownLineInfo(), tyBool), d)
+      if d.k == locNone: getTemp(p, getSysType(p.module.g.graph, unknownLineInfo, tyBool), d)
       if op == mLtSet:
         linefmt(p, cpsStmts, lookupOpr[mLtSet],
            [rdLoc(i), size, rdLoc(d), rdLoc(a), rdLoc(b)])
@@ -1866,7 +1866,7 @@ proc genSetOp(p: BProc, e: PNode, d: var TLoc, op: TMagic) =
       putIntoDest(p, d, e, ropecg(p.module, "(#nimCmpMem($1, $2, $3)==0)", [a.rdCharLoc, b.rdCharLoc, size]))
     of mMulSet, mPlusSet, mMinusSet, mSymDiffSet:
       # we inline the simple for loop for better code generation:
-      getTemp(p, getSysType(p.module.g.graph, unknownLineInfo(), tyInt), i) # our counter
+      getTemp(p, getSysType(p.module.g.graph, unknownLineInfo, tyInt), i) # our counter
       initLocExpr(p, e[1], a)
       initLocExpr(p, e[2], b)
       if d.k == locNone: getTemp(p, setType, d)
@@ -2319,7 +2319,7 @@ proc genSetConstr(p: BProc, e: PNode, d: var TLoc) =
           [rdLoc(d), getTypeDesc(p.module, e.typ)])
       for it in e.sons:
         if it.kind == nkRange:
-          getTemp(p, getSysType(p.module.g.graph, unknownLineInfo(), tyInt), idx) # our counter
+          getTemp(p, getSysType(p.module.g.graph, unknownLineInfo, tyInt), idx) # our counter
           initLocExpr(p, it[0], a)
           initLocExpr(p, it[1], b)
           lineF(p, cpsStmts, "for ($1 = $3; $1 <= $4; $1++) $n" &
@@ -2335,7 +2335,7 @@ proc genSetConstr(p: BProc, e: PNode, d: var TLoc) =
       lineF(p, cpsStmts, "$1 = 0;$n", [rdLoc(d)])
       for it in e.sons:
         if it.kind == nkRange:
-          getTemp(p, getSysType(p.module.g.graph, unknownLineInfo(), tyInt), idx) # our counter
+          getTemp(p, getSysType(p.module.g.graph, unknownLineInfo, tyInt), idx) # our counter
           initLocExpr(p, it[0], a)
           initLocExpr(p, it[1], b)
           lineF(p, cpsStmts, "for ($1 = $3; $1 <= $4; $1++) $n" &
diff --git a/compiler/ccgstmts.nim b/compiler/ccgstmts.nim
index 30444e2aa..ec13b991d 100644
--- a/compiler/ccgstmts.nim
+++ b/compiler/ccgstmts.nim
@@ -558,7 +558,7 @@ proc genComputedGoto(p: BProc; n: PNode) =
       let it = n[j]
       if it.kind in {nkLetSection, nkVarSection}:
         let asgn = copyNode(it)
-        asgn.kind = nkAsgn
+        asgn.transitionSonsKind(nkAsgn)
         asgn.sons.setLen 2
         for sym, value in it.fieldValuePairs:
           if value.kind != nkEmpty:
diff --git a/compiler/ccgtrav.nim b/compiler/ccgtrav.nim
index 510f81557..63b1cb88a 100644
--- a/compiler/ccgtrav.nim
+++ b/compiler/ccgtrav.nim
@@ -75,7 +75,7 @@ proc genTraverseProc(c: TTraversalClosure, accessor: Rope, typ: PType) =
   of tyArray:
     let arraySize = lengthOrd(c.p.config, typ[0])
     var i: TLoc
-    getTemp(p, getSysType(c.p.module.g.graph, unknownLineInfo(), tyInt), i)
+    getTemp(p, getSysType(c.p.module.g.graph, unknownLineInfo, tyInt), i)
     let oldCode = p.s(cpsStmts)
     linefmt(p, cpsStmts, "for ($1 = 0; $1 < $2; $1++) {$n",
             [i.r, arraySize])
@@ -119,7 +119,7 @@ proc genTraverseProcSeq(c: TTraversalClosure, accessor: Rope, typ: PType) =
   var p = c.p
   assert typ.kind == tySequence
   var i: TLoc
-  getTemp(p, getSysType(c.p.module.g.graph, unknownLineInfo(), tyInt), i)
+  getTemp(p, getSysType(c.p.module.g.graph, unknownLineInfo, tyInt), i)
   let oldCode = p.s(cpsStmts)
   var a: TLoc
   a.r = accessor
diff --git a/compiler/ccgtypes.nim b/compiler/ccgtypes.nim
index 9a1f8cc46..56f227e37 100644
--- a/compiler/ccgtypes.nim
+++ b/compiler/ccgtypes.nim
@@ -696,7 +696,7 @@ proc getTypeDescAux(m: BModule, origTyp: PType, check: var IntSet): Rope =
     var etB = et.skipTypes(abstractInst)
     if mapType(m.config, t) == ctPtrToArray:
       if etB.kind == tySet:
-        et = getSysType(m.g.graph, unknownLineInfo(), tyUInt8)
+        et = getSysType(m.g.graph, unknownLineInfo, tyUInt8)
       else:
         et = elemType(etB)
       etB = et.skipTypes(abstractInst)
diff --git a/compiler/cgen.nim b/compiler/cgen.nim
index ee4634aad..a36b6aa29 100644
--- a/compiler/cgen.nim
+++ b/compiler/cgen.nim
@@ -480,7 +480,7 @@ proc getIntTemp(p: BProc, result: var TLoc) =
   linefmt(p, cpsLocals, "NI $1;$n", [result.r])
   result.k = locTemp
   result.storage = OnStack
-  result.lode = lodeTyp getSysType(p.module.g.graph, unknownLineInfo(), tyInt)
+  result.lode = lodeTyp getSysType(p.module.g.graph, unknownLineInfo, tyInt)
   result.flags = {}
 
 proc localVarDecl(p: BProc; n: PNode): Rope =
diff --git a/compiler/cgmeth.nim b/compiler/cgmeth.nim
index f1fb1716a..a71ac6ea7 100644
--- a/compiler/cgmeth.nim
+++ b/compiler/cgmeth.nim
@@ -230,9 +230,9 @@ proc genDispatcher(g: ModuleGraph; methods: seq[PSym], relevantCols: IntSet): PS
   var paramLen = base.typ.len
   var nilchecks = newNodeI(nkStmtList, base.info)
   var disp = newNodeI(nkIfStmt, base.info)
-  var ands = getSysMagic(g, unknownLineInfo(), "and", mAnd)
-  var iss = getSysMagic(g, unknownLineInfo(), "of", mOf)
-  let boolType = getSysType(g, unknownLineInfo(), tyBool)
+  var ands = getSysMagic(g, unknownLineInfo, "and", mAnd)
+  var iss = getSysMagic(g, unknownLineInfo, "of", mOf)
+  let boolType = getSysType(g, unknownLineInfo, tyBool)
   for col in 1..<paramLen:
     if contains(relevantCols, col):
       let param = base.typ.n[col].sym
diff --git a/compiler/closureiters.nim b/compiler/closureiters.nim
index 03545e151..ef08a7bae 100644
--- a/compiler/closureiters.nim
+++ b/compiler/closureiters.nim
@@ -778,7 +778,7 @@ proc lowerStmtListExprs(ctx: var Ctx, n: PNode, needsSplit: var bool): PNode =
       result = newNodeI(nkStmtListExpr, n.info)
       result.typ = n.typ
       let (st, ex) = exprToStmtList(n[1])
-      n.kind = nkBlockStmt
+      n.transitionSonsKind(nkBlockStmt)
       n.typ = nil
       n[1] = st
       result.add(n)
diff --git a/compiler/lambdalifting.nim b/compiler/lambdalifting.nim
index 1921a1e18..01def12ad 100644
--- a/compiler/lambdalifting.nim
+++ b/compiler/lambdalifting.nim
@@ -837,12 +837,12 @@ proc liftIterToProc*(g: ModuleGraph; fn: PSym; body: PNode; ptrType: PType): PNo
   # pretend 'fn' is a closure iterator for the analysis:
   let oldKind = fn.kind
   let oldCC = fn.typ.callConv
-  fn.kind = skIterator
+  fn.transitionRoutineSymKind(skIterator)
   fn.typ.callConv = ccClosure
   d.ownerToType[fn.id] = ptrType
   detectCapturedVars(body, fn, d)
   result = liftCapturedVars(body, fn, d, c)
-  fn.kind = oldKind
+  fn.transitionRoutineSymKind(oldKind)
   fn.typ.callConv = oldCC
 
 proc liftLambdas*(g: ModuleGraph; fn: PSym, body: PNode; tooEarly: var bool): PNode =
@@ -959,7 +959,7 @@ proc liftForLoop*(g: ModuleGraph; body: PNode; owner: PSym): PNode =
   var vpart = newNodeI(if body.len == 3: nkIdentDefs else: nkVarTuple, body.info)
   for i in 0..<body.len-2:
     if body[i].kind == nkSym:
-      body[i].sym.kind = skLet
+      body[i].sym.transitionToLet()
     vpart.add body[i]
 
   vpart.add newNodeI(nkEmpty, body.info) # no explicit type
diff --git a/compiler/lineinfos.nim b/compiler/lineinfos.nim
index b5742e669..9095dd13d 100644
--- a/compiler/lineinfos.nim
+++ b/compiler/lineinfos.nim
@@ -236,11 +236,7 @@ proc raiseRecoverableError*(msg: string) {.noinline.} =
 
 const
   InvalidFileIdx* = FileIndex(-1)
-
-proc unknownLineInfo*(): TLineInfo =
-  result.line = uint16(0)
-  result.col = int16(-1)
-  result.fileIndex = InvalidFileIdx
+  unknownLineInfo* = TLineInfo(line: 0, col: -1, fileIndex: InvalidFileIdx)
 
 type
   Severity* {.pure.} = enum ## VS Code only supports these three
@@ -267,7 +263,7 @@ type
 
 proc initMsgConfig*(): MsgConfig =
   result.msgContext = @[]
-  result.lastError = unknownLineInfo()
+  result.lastError = unknownLineInfo
   result.filenameToIndexTbl = initTable[string, FileIndex]()
   result.fileInfos = @[]
   result.errorOutputs = {eStdOut, eStdErr}
diff --git a/compiler/lowerings.nim b/compiler/lowerings.nim
index d069bba84..b3b6cbb5c 100644
--- a/compiler/lowerings.nim
+++ b/compiler/lowerings.nim
@@ -323,7 +323,7 @@ proc genDeref*(n: PNode; k = nkHiddenDeref): PNode =
   result.add n
 
 proc callCodegenProc*(g: ModuleGraph; name: string;
-                      info: TLineInfo = unknownLineInfo();
+                      info: TLineInfo = unknownLineInfo;
                       arg1, arg2, arg3, optionalArgs: PNode = nil): PNode =
   result = newNodeI(nkCall, info)
   let sym = magicsys.getCompilerProc(g, name)
diff --git a/compiler/modulegraphs.nim b/compiler/modulegraphs.nim
index 2dfd79144..3a6d28708 100644
--- a/compiler/modulegraphs.nim
+++ b/compiler/modulegraphs.nim
@@ -163,7 +163,7 @@ proc stopCompile*(g: ModuleGraph): bool {.inline.} =
   result = g.doStopCompile != nil and g.doStopCompile()
 
 proc createMagic*(g: ModuleGraph; name: string, m: TMagic): PSym =
-  result = newSym(skProc, getIdent(g.cache, name), nil, unknownLineInfo(), {})
+  result = newSym(skProc, getIdent(g.cache, name), nil, unknownLineInfo, {})
   result.magic = m
 
 proc newModuleGraph*(cache: IdentCache; config: ConfigRef): ModuleGraph =
diff --git a/compiler/modules.nim b/compiler/modules.nim
index 174d2117c..9ef9dfead 100644
--- a/compiler/modules.nim
+++ b/compiler/modules.nim
@@ -55,16 +55,14 @@ proc partialInitModule(result: PSym; graph: ModuleGraph; fileIdx: FileIndex; fil
   strTableAdd(packSym.tab, result)
 
 proc newModule(graph: ModuleGraph; fileIdx: FileIndex): PSym =
+  let filename = AbsoluteFile toFullPath(graph.config, fileIdx)
   # We cannot call ``newSym`` here, because we have to circumvent the ID
   # mechanism, which we do in order to assign each module a persistent ID.
-  new(result)
-  result.id = -1             # for better error checking
-  result.kind = skModule
-  let filename = AbsoluteFile toFullPath(graph.config, fileIdx)
-  result.name = getIdent(graph.cache, splitFile(filename).name)
+  result = PSym(kind: skModule, id: -1, # for better error checking
+                name: getIdent(graph.cache, splitFile(filename).name),
+                info: newLineInfo(fileIdx, 1, 1))
   if not isNimIdentifier(result.name.s):
     rawMessage(graph.config, errGenerated, "invalid module name: " & result.name.s)
-  result.info = newLineInfo(fileIdx, 1, 1)
   partialInitModule(result, graph, fileIdx, filename)
 
 proc compileModule*(graph: ModuleGraph; fileIdx: FileIndex; flags: TSymFlags): PSym =
diff --git a/compiler/msgs.nim b/compiler/msgs.nim
index 5fba33ab6..91fad9ac1 100644
--- a/compiler/msgs.nim
+++ b/compiler/msgs.nim
@@ -157,7 +157,7 @@ proc popInfoContext*(conf: ConfigRef) =
 
 proc getInfoContext*(conf: ConfigRef; index: int): TLineInfo =
   let i = if index < 0: conf.m.msgContext.len + index else: index
-  if i >=% conf.m.msgContext.len: result = unknownLineInfo()
+  if i >=% conf.m.msgContext.len: result = unknownLineInfo
   else: result = conf.m.msgContext[i].info
 
 const
@@ -405,14 +405,14 @@ proc rawMessage*(conf: ConfigRef; msg: TMsgKind, args: openArray[string]) =
   case msg
   of errMin..errMax:
     sev = Severity.Error
-    writeContext(conf, unknownLineInfo())
+    writeContext(conf, unknownLineInfo)
     title = ErrorTitle
     color = ErrorColor
   of warnMin..warnMax:
     sev = Severity.Warning
     if optWarns notin conf.options: return
     if msg notin conf.notes: return
-    writeContext(conf, unknownLineInfo())
+    writeContext(conf, unknownLineInfo)
     title = WarningTitle
     color = WarningColor
     kind = WarningsToStr[ord(msg) - ord(warnMin)]
@@ -428,7 +428,7 @@ proc rawMessage*(conf: ConfigRef; msg: TMsgKind, args: openArray[string]) =
   let s = msgKindToString(msg) % args
 
   if conf.structuredErrorHook != nil:
-    conf.structuredErrorHook(conf, unknownLineInfo(),
+    conf.structuredErrorHook(conf, unknownLineInfo,
       s & (if kind.len > 0: KindFormat % kind else: ""), sev)
 
   if not ignoreMsgBecauseOfIdeTools(conf, msg):
@@ -561,7 +561,7 @@ proc internalError*(conf: ConfigRef; info: TLineInfo, errMsg: string) =
 
 proc internalError*(conf: ConfigRef; errMsg: string) =
   if conf.cmd == cmdIdeTools and conf.structuredErrorHook.isNil: return
-  writeContext(conf, unknownLineInfo())
+  writeContext(conf, unknownLineInfo)
   rawMessage(conf, errInternal, errMsg)
 
 template assertNotNil*(conf: ConfigRef; e): untyped =
diff --git a/compiler/nim.cfg b/compiler/nim.cfg
index 05f4ed5e9..f913e76a3 100644
--- a/compiler/nim.cfg
+++ b/compiler/nim.cfg
@@ -15,7 +15,6 @@ define:nimcore
 @end
 
 define:useStdoutAsStdmsg
-define:nimOldCaseObjects
 
 @if nimHasStyleChecks:
   styleCheck:error
@@ -23,7 +22,3 @@ define:nimOldCaseObjects
 
 #define:useNodeIds
 #gc:markAndSweep
-
-@if nimHasWarningCaseTransition:
-warning[CaseTransition]:off
-@end
diff --git a/compiler/nimblecmd.nim b/compiler/nimblecmd.nim
index c84a0f3c2..fbc3fcee1 100644
--- a/compiler/nimblecmd.nim
+++ b/compiler/nimblecmd.nim
@@ -147,16 +147,16 @@ when isMainModule:
 
   let conf = newConfigRef()
   var rr = newStringTable()
-  addPackage conf, rr, "irc-#a111", unknownLineInfo()
-  addPackage conf, rr, "irc-#head", unknownLineInfo()
-  addPackage conf, rr, "irc-0.1.0", unknownLineInfo()
-  #addPackage conf, rr, "irc", unknownLineInfo()
-  #addPackage conf, rr, "another", unknownLineInfo()
-  addPackage conf, rr, "another-0.1", unknownLineInfo()
-
-  addPackage conf, rr, "ab-0.1.3", unknownLineInfo()
-  addPackage conf, rr, "ab-0.1", unknownLineInfo()
-  addPackage conf, rr, "justone-1.0", unknownLineInfo()
+  addPackage conf, rr, "irc-#a111", unknownLineInfo
+  addPackage conf, rr, "irc-#head", unknownLineInfo
+  addPackage conf, rr, "irc-0.1.0", unknownLineInfo
+  #addPackage conf, rr, "irc", unknownLineInfo
+  #addPackage conf, rr, "another", unknownLineInfo
+  addPackage conf, rr, "another-0.1", unknownLineInfo
+
+  addPackage conf, rr, "ab-0.1.3", unknownLineInfo
+  addPackage conf, rr, "ab-0.1", unknownLineInfo
+  addPackage conf, rr, "justone-1.0", unknownLineInfo
 
   doAssert toSeq(rr.chosen) ==
     @["irc-#head", "another-0.1", "ab-0.1.3", "justone-1.0"]
diff --git a/compiler/parser.nim b/compiler/parser.nim
index cf95eb26c..4ea751057 100644
--- a/compiler/parser.nim
+++ b/compiler/parser.nim
@@ -427,7 +427,7 @@ proc exprColonEqExprListAux(p: var TParser, endTok: TTokType, result: PNode) =
     getTok(p)
     # (1,) produces a tuple expression
     if endTok == tkParRi and p.tok.tokType == tkParRi and result.kind == nkPar:
-      result.kind = nkTupleConstr
+      result.transitionSonsKind(nkTupleConstr)
     skipComment(p, a)
   optPar(p)
   eat(p, endTok)
@@ -472,12 +472,12 @@ proc setOrTableConstr(p: var TParser): PNode =
   optInd(p, result)
   if p.tok.tokType == tkColon:
     getTok(p) # skip ':'
-    result.kind = nkTableConstr
+    result.transitionSonsKind(nkTableConstr)
   else:
     # progress guaranteed
     while p.tok.tokType notin {tkCurlyRi, tkEof}:
       var a = exprColonEqExpr(p)
-      if a.kind == nkExprColonExpr: result.kind = nkTableConstr
+      if a.kind == nkExprColonExpr: result.transitionSonsKind(nkTableConstr)
       result.add(a)
       if p.tok.tokType != tkComma: break
       getTok(p)
@@ -534,7 +534,7 @@ proc semiStmtList(p: var TParser, result: PNode) =
     optInd(p, result)
     result.add(complexOrSimpleStmt(p))
   dec p.inSemiStmtList
-  result.kind = nkStmtListExpr
+  result.transitionSonsKind(nkStmtListExpr)
 
 proc parsePar(p: var TParser): PNode =
   #| parKeyw = 'discard' | 'include' | 'if' | 'while' | 'case' | 'try'
@@ -595,7 +595,7 @@ proc parsePar(p: var TParser): PNode =
         skipComment(p, a)
         # (1,) produces a tuple expression:
         if p.tok.tokType == tkParRi:
-          result.kind = nkTupleConstr
+          result.transitionSonsKind(nkTupleConstr)
         # progress guaranteed
         while p.tok.tokType != tkParRi and p.tok.tokType != tkEof:
           var a = exprColonEqExpr(p)
@@ -778,7 +778,7 @@ proc primarySuffix(p: var TParser, r: PNode,
         break
       result = namedParams(p, result, nkCall, tkParRi)
       if result.len > 1 and result[1].kind == nkExprColonExpr:
-        result.kind = nkObjConstr
+        result.transitionSonsKind(nkObjConstr)
     of tkDot:
       # progress guaranteed
       result = dotExpr(p, result)
@@ -1275,8 +1275,8 @@ proc primary(p: var TParser, mode: TPrimaryMode): PNode =
   of tkFunc: result = parseProcExpr(p, mode notin {pmTypeDesc, pmTypeDef}, nkFuncDef)
   of tkIterator:
     result = parseProcExpr(p, mode notin {pmTypeDesc, pmTypeDef}, nkLambda)
-    if result.kind == nkLambda: result.kind = nkIteratorDef
-    else: result.kind = nkIteratorTy
+    if result.kind == nkLambda: result.transitionSonsKind(nkIteratorDef)
+    else: result.transitionSonsKind(nkIteratorTy)
   of tkEnum:
     if mode == pmTypeDef:
       prettySection:
@@ -1479,7 +1479,7 @@ proc parseImport(p: var TParser, kind: TNodeKind): PNode =
   result.add(a)
   if p.tok.tokType in {tkComma, tkExcept}:
     if p.tok.tokType == tkExcept:
-      result.kind = succ(kind)
+      result.transitionSonsKind(succ(kind))
     getTok(p)
     optInd(p, result)
     while true:
diff --git a/compiler/pragmas.nim b/compiler/pragmas.nim
index 0004fe94b..ab0af80ea 100644
--- a/compiler/pragmas.nim
+++ b/compiler/pragmas.nim
@@ -736,7 +736,7 @@ proc semCustomPragma(c: PContext, n: PNode): PNode =
     result = result[0]
   elif n.kind == nkExprColonExpr and r.len == 2:
     # pragma(arg) -> pragma: arg
-    result.kind = n.kind
+    result.transitionSonsKind(n.kind)
 
 proc singlePragma(c: PContext, sym: PSym, n: PNode, i: var int,
                   validPragmas: TSpecialWords,
diff --git a/compiler/rodimpl.nim b/compiler/rodimpl.nim
index d79dd1deb..7a0f6fcef 100644
--- a/compiler/rodimpl.nim
+++ b/compiler/rodimpl.nim
@@ -173,7 +173,7 @@ proc encodeLoc(g: ModuleGraph; loc: TLoc, result: var string) =
     encodeVInt(cast[int32](loc.flags), result)
   if loc.lode != nil:
     result.add('^')
-    encodeNode(g, unknownLineInfo(), loc.lode, result)
+    encodeNode(g, unknownLineInfo, loc.lode, result)
   if loc.r != nil:
     result.add('!')
     encodeStr($loc.r, result)
@@ -200,7 +200,7 @@ proc encodeType(g: ModuleGraph, t: PType, result: var string) =
     result.add('+')
     encodeVInt(t.id, result)
   if t.n != nil:
-    encodeNode(g, unknownLineInfo(), t.n, result)
+    encodeNode(g, unknownLineInfo, t.n, result)
   if t.flags != {}:
     result.add('$')
     encodeVInt(cast[int32](t.flags), result)
@@ -318,7 +318,7 @@ proc encodeSym(g: ModuleGraph, s: PSym, result: var string) =
   if s.annex != nil: encodeLib(g, s.annex, s.info, result)
   if s.constraint != nil:
     result.add('#')
-    encodeNode(g, unknownLineInfo(), s.constraint, result)
+    encodeNode(g, unknownLineInfo, s.constraint, result)
   case s.kind
   of skType, skGenericParam:
     for t in s.typeInstCache:
@@ -605,7 +605,7 @@ proc loadType(g; id: int; info: TLineInfo): PType =
     result.id = result.uniqueId
   # here this also avoids endless recursion for recursive type
   g.incr.r.types.add(result.uniqueId, result)
-  if b.s[b.pos] == '(': result.n = decodeNode(g, b, unknownLineInfo())
+  if b.s[b.pos] == '(': result.n = decodeNode(g, b, unknownLineInfo)
   if b.s[b.pos] == '$':
     inc(b.pos)
     result.flags = cast[TTypeFlags](int32(decodeVInt(b.s, b.pos)))
@@ -752,7 +752,7 @@ proc loadSymFromBlob(g; b; info: TLineInfo): PSym =
   result.annex = decodeLib(g, b, info)
   if b.s[b.pos] == '#':
     inc(b.pos)
-    result.constraint = decodeNode(g, b, unknownLineInfo())
+    result.constraint = decodeNode(g, b, unknownLineInfo)
   case result.kind
   of skType, skGenericParam:
     while b.s[b.pos] == '\14':
diff --git a/compiler/sem.nim b/compiler/sem.nim
index 7fdd83bdd..7cd0aa6f2 100644
--- a/compiler/sem.nim
+++ b/compiler/sem.nim
@@ -416,7 +416,7 @@ proc semAfterMacroCall(c: PContext, call, macroResult: PNode,
       # More restrictive version.
       result = semExprWithType(c, result, flags)
     of tyTypeDesc:
-      if result.kind == nkStmtList: result.kind = nkStmtListType
+      if result.kind == nkStmtList: result.transitionSonsKind(nkStmtListType)
       var typ = semTypeNode(c, result, nil)
       if typ == nil:
         localError(c.config, result.info, "expression has no type: " &
diff --git a/compiler/semexprs.nim b/compiler/semexprs.nim
index 3662b397c..cbdb5ce77 100644
--- a/compiler/semexprs.nim
+++ b/compiler/semexprs.nim
@@ -884,7 +884,7 @@ proc semIndirectOp(c: PContext, n: PNode, flags: TExprFlags): PNode =
     if n0.kind == nkDotCall:
       # it is a static call!
       result = n0
-      result.kind = nkCall
+      result.transitionSonsKind(nkCall)
       result.flags.incl nfExplicitCall
       for i in 1..<n.len: result.add n[i]
       return semExpr(c, result, flags)
@@ -1509,7 +1509,7 @@ proc semSubscript(c: PContext, n: PNode, flags: TExprFlags): PNode =
         else:
           # We are processing macroOrTmpl[] not in call. Transform it to the
           # macro or template call with generic arguments here.
-          n.kind = nkCall
+          n.transitionSonsKind(nkCall)
           case s.kind
           of skMacro: result = semMacroExpr(c, n, n, s, flags)
           of skTemplate: result = semTemplateExpr(c, n, s, flags)
@@ -1646,7 +1646,7 @@ proc semAsgn(c: PContext, n: PNode; mode=asgnNormal): PNode =
       # possible:
       a = dotTransformation(c, n[0])
       if a.kind == nkDotCall:
-        a.kind = nkCall
+        a.transitionSonsKind(nkCall)
         a = semExprWithType(c, a, {efLValue})
   of nkBracketExpr:
     # a[i] = x
@@ -2429,7 +2429,7 @@ proc semTupleFieldsConstr(c: PContext, n: PNode, flags: TExprFlags): PNode =
 
 proc semTuplePositionsConstr(c: PContext, n: PNode, flags: TExprFlags): PNode =
   result = n                  # we don't modify n, but compute the type:
-  result.kind = nkTupleConstr
+  result.transitionSonsKind(nkTupleConstr)
   var typ = newTypeS(tyTuple, c)  # leave typ.n nil!
   for i in 0..<n.len:
     n[i] = semExprWithType(c, n[i], flags*{efAllowDestructor})
@@ -2455,8 +2455,8 @@ proc semBlock(c: PContext, n: PNode; flags: TExprFlags): PNode =
     onDef(n[0].info, labl)
   n[1] = semExpr(c, n[1], flags)
   n.typ = n[1].typ
-  if isEmptyType(n.typ): n.kind = nkBlockStmt
-  else: n.kind = nkBlockExpr
+  if isEmptyType(n.typ): n.transitionSonsKind(nkBlockStmt)
+  else: n.transitionSonsKind(nkBlockExpr)
   closeScope(c)
   dec(c.p.nestedBlockCounter)
 
@@ -2608,7 +2608,7 @@ proc semExpr(c: PContext, n: PNode, flags: TExprFlags = {}): PNode =
   of nkDotExpr:
     result = semFieldAccess(c, n, flags)
     if result.kind == nkDotCall:
-      result.kind = nkCall
+      result.transitionSonsKind(nkCall)
       result = semExpr(c, result, flags)
   of nkBind:
     message(c.config, n.info, warnDeprecated, "bind is deprecated")
diff --git a/compiler/semfold.nim b/compiler/semfold.nim
index bacc5e9c6..e8ca42db3 100644
--- a/compiler/semfold.nim
+++ b/compiler/semfold.nim
@@ -451,7 +451,7 @@ proc foldConv(n, a: PNode; g: ModuleGraph; check = false): PNode =
       if check: rangeCheck(n, val, g)
       result = newIntNodeT(val, n, g)
       if dstTyp.kind in {tyUInt..tyUInt64}:
-        result.kind = nkUIntLit
+        result.transitionIntKind(nkUIntLit)
     else:
       result = a
       result.typ = n.typ
diff --git a/compiler/semgnrc.nim b/compiler/semgnrc.nim
index 59be8d597..a494db475 100644
--- a/compiler/semgnrc.nim
+++ b/compiler/semgnrc.nim
@@ -163,7 +163,7 @@ proc fuzzyLookup(c: PContext, n: PNode, flags: TSemGenericFlags,
         let syms = semGenericStmtSymbol(c, n, s, ctx, flags, fromDotExpr=true)
         if syms.kind == nkSym:
           let choice = symChoice(c, n, s, scForceOpen)
-          choice.kind = nkClosedSymChoice
+          choice.transitionSonsKind(nkClosedSymChoice)
           result = newDot(result, choice)
         else:
           result = newDot(result, syms)
diff --git a/compiler/semstmts.nim b/compiler/semstmts.nim
index 475ec32a4..69022f4ad 100644
--- a/compiler/semstmts.nim
+++ b/compiler/semstmts.nim
@@ -129,7 +129,7 @@ proc fixNilType(c: PContext; n: PNode) =
     if n.kind != nkNilLit and n.typ != nil:
       localError(c.config, n.info, errDiscardValueX % n.typ.typeToString)
   elif n.kind in {nkStmtList, nkStmtListExpr}:
-    n.kind = nkStmtList
+    n.transitionSonsKind(nkStmtList)
     for it in n: fixNilType(c, it)
   n.typ = nil
 
@@ -172,7 +172,7 @@ proc semIf(c: PContext, n: PNode; flags: TExprFlags): PNode =
   if isEmptyType(typ) or typ.kind in {tyNil, tyUntyped} or
       (not hasElse and efInTypeof notin flags):
     for it in n: discardCheck(c, it.lastSon, flags)
-    result.kind = nkIfStmt
+    result.transitionSonsKind(nkIfStmt)
     # propagate any enforced VoidContext:
     if typ == c.enforceVoidContext: result.typ = c.enforceVoidContext
   else:
@@ -180,7 +180,7 @@ proc semIf(c: PContext, n: PNode; flags: TExprFlags): PNode =
       let j = it.len-1
       if not endsInNoReturn(it[j]):
         it[j] = fitNode(c, typ, it[j], it[j].info)
-    result.kind = nkIfExpr
+    result.transitionSonsKind(nkIfExpr)
     result.typ = typ
 
 proc semTry(c: PContext, n: PNode; flags: TExprFlags): PNode =
@@ -867,7 +867,7 @@ proc semFor(c: PContext, n: PNode; flags: TExprFlags): PNode =
       call[0].sym.magic in {mFields, mFieldPairs, mOmpParFor}:
     if call[0].sym.magic == mOmpParFor:
       result = semForVars(c, n, flags)
-      result.kind = nkParForStmt
+      result.transitionSonsKind(nkParForStmt)
     else:
       result = semForFields(c, n, call[0].sym.magic)
   elif isCallExpr and isClosureIterator(call[0].typ.skipTypes(abstractInst)):
@@ -1970,7 +1970,7 @@ proc semProcAux(c: PContext, n: PNode, kind: TSymKind,
   if n[patternPos].kind != nkEmpty:
     c.patterns.add(s)
   if isAnon:
-    n.kind = nkLambda
+    n.transitionSonsKind(nkLambda)
     result.typ = s.typ
     if optOwnedRefs in c.config.globalOptions:
       result.typ = makeVarType(c, result.typ, tyOwned)
@@ -1989,7 +1989,7 @@ proc semIterator(c: PContext, n: PNode): PNode =
   if n[namePos].kind == nkSym:
     # gensym'ed iterators might need to become closure iterators:
     n[namePos].sym.owner = getCurrOwner(c)
-    n[namePos].sym.kind = skIterator
+    n[namePos].sym.transitionRoutineSymKind(skIterator)
   result = semProcAux(c, n, skIterator, iteratorPragmas)
   # bug #7093: if after a macro transformation we don't have an
   # nkIteratorDef aynmore, return. The iterator then might have been
@@ -2166,7 +2166,7 @@ proc semStmtList(c: PContext, n: PNode, flags: TExprFlags): PNode =
   const
     LastBlockStmts = {nkRaiseStmt, nkReturnStmt, nkBreakStmt, nkContinueStmt}
   result = n
-  result.kind = nkStmtList
+  result.transitionSonsKind(nkStmtList)
   var voidContext = false
   var last = n.len-1
   # by not allowing for nkCommentStmt etc. we ensure nkStmtListExpr actually
@@ -2203,12 +2203,12 @@ proc semStmtList(c: PContext, n: PNode, flags: TExprFlags): PNode =
       n.typ = c.enforceVoidContext
     if i == last and (n.len == 1 or ({efWantValue, efInTypeof} * flags != {})):
       n.typ = n[i].typ
-      if not isEmptyType(n.typ): n.kind = nkStmtListExpr
+      if not isEmptyType(n.typ): n.transitionSonsKind(nkStmtListExpr)
     elif i != last or voidContext:
       discardCheck(c, n[i], flags)
     else:
       n.typ = n[i].typ
-      if not isEmptyType(n.typ): n.kind = nkStmtListExpr
+      if not isEmptyType(n.typ): n.transitionSonsKind(nkStmtListExpr)
     if n[i].kind in LastBlockStmts or
         n[i].kind in nkCallKinds and n[i][0].kind == nkSym and
         sfNoReturn in n[i][0].sym.flags:
diff --git a/compiler/semtypes.nim b/compiler/semtypes.nim
index f1acaf8ea..2dcee1420 100644
--- a/compiler/semtypes.nim
+++ b/compiler/semtypes.nim
@@ -381,7 +381,7 @@ proc semTypeIdent(c: PContext, n: PNode): PSym =
         if result.typ.kind == tyGenericParam and result.typ.len == 0 and
            tfWildcard in result.typ.flags:
           # collapse the wild-card param to a type
-          result.kind = skType
+          result.transitionGenericParamToType()
           result.typ.flags.excl tfWildcard
           return
         else:
@@ -405,7 +405,7 @@ proc semTypeIdent(c: PContext, n: PNode): PSym =
         reset(n[])
         when defined(useNodeIds):
           n.id = oldId
-        n.kind = nkSym
+        n.transitionNoneToSym()
         n.sym = result
         n.info = oldInfo
         n.typ = result.typ
@@ -1127,7 +1127,7 @@ proc liftParamType(c: PContext, procKind: TSymKind, genericParams: PNode,
     onUse(paramType.sym.info, paramType.sym)
     if tfWildcard in paramType.flags:
       paramType.flags.excl tfWildcard
-      paramType.sym.kind = skType
+      paramType.sym.transitionGenericParamToType()
 
   else: discard
 
@@ -1326,7 +1326,7 @@ proc semProcTypeNode(c: PContext, n, genericParams: PNode,
         result.flags.incl tfUnresolved
 
       if tfWildcard in n.sym.typ.flags:
-        n.sym.kind = skType
+        n.sym.transitionGenericParamToType()
         n.sym.typ.flags.excl tfWildcard
 
 proc semStmtListType(c: PContext, n: PNode, prev: PType): PType =
@@ -1696,7 +1696,7 @@ proc semTypeNode(c: PContext, n: PNode, prev: PType): PType =
           result = semTypeExpr(c, n, prev)
   of nkWhenStmt:
     var whenResult = semWhen(c, n, false)
-    if whenResult.kind == nkStmtList: whenResult.kind = nkStmtListType
+    if whenResult.kind == nkStmtList: whenResult.transitionSonsKind(nkStmtListType)
     result = semTypeNode(c, whenResult, prev)
   of nkBracketExpr:
     checkMinSonsLen(n, 2, c.config)
diff --git a/compiler/sigmatch.nim b/compiler/sigmatch.nim
index 469bbf98a..c87b76622 100644
--- a/compiler/sigmatch.nim
+++ b/compiler/sigmatch.nim
@@ -1714,7 +1714,7 @@ proc typeRel(c: var TCandidate, f, aOrig: PType,
       if result == isGeneric:
         var concrete = a
         if tfWildcard in a.flags:
-          a.sym.kind = skType
+          a.sym.transitionGenericParamToType()
           a.flags.excl tfWildcard
         else:
           concrete = concreteType(c, a, f)
@@ -1943,7 +1943,7 @@ proc localConvMatch(c: PContext, m: var TCandidate, f, a: PType,
     # resulting type must be consistent with the other arguments:
     var r = typeRel(m, f[0], result.typ)
     if r < isGeneric: return nil
-    if result.kind == nkCall: result.kind = nkHiddenCallConv
+    if result.kind == nkCall: result.transitionSonsKind(nkHiddenCallConv)
     inc(m.convMatches)
     if r == isGeneric:
       result.typ = getInstantiatedType(c, arg, m, base(f))
@@ -2602,7 +2602,7 @@ when not declared(tests):
   template tests(s: untyped) = discard
 
 tests:
-  var dummyOwner = newSym(skModule, getIdent("test_module"), nil, UnknownLineInfo())
+  var dummyOwner = newSym(skModule, getIdent("test_module"), nil, unknownLineInfo)
 
   proc `|` (t1, t2: PType): PType =
     result = newType(tyOr, dummyOwner)
@@ -2625,7 +2625,7 @@ tests:
   proc array(x: int, t: PType): PType =
     result = newType(tyArray, dummyOwner)
 
-    var n = newNodeI(nkRange, UnknownLineInfo())
+    var n = newNodeI(nkRange, unknownLineInfo)
     n.add newIntNode(nkIntLit, 0)
     n.add newIntNode(nkIntLit, x)
     let range = newType(tyRange, dummyOwner)
@@ -2643,14 +2643,14 @@ tests:
       number = int | float
 
     var TFoo = newType(tyObject, dummyOwner)
-    TFoo.sym = newSym(skType, getIdent"TFoo", dummyOwner, UnknownLineInfo())
+    TFoo.sym = newSym(skType, getIdent"TFoo", dummyOwner, unknownLineInfo)
 
     var T1 = newType(tyGenericParam, dummyOwner)
-    T1.sym = newSym(skType, getIdent"T1", dummyOwner, UnknownLineInfo())
+    T1.sym = newSym(skType, getIdent"T1", dummyOwner, unknownLineInfo)
     T1.sym.position = 0
 
     var T2 = newType(tyGenericParam, dummyOwner)
-    T2.sym = newSym(skType, getIdent"T2", dummyOwner, UnknownLineInfo())
+    T2.sym = newSym(skType, getIdent"T2", dummyOwner, unknownLineInfo)
     T2.sym.position = 1
 
     setup:
diff --git a/compiler/sizealignoffsetimpl.nim b/compiler/sizealignoffsetimpl.nim
index adbd02026..ee88e276f 100644
--- a/compiler/sizealignoffsetimpl.nim
+++ b/compiler/sizealignoffsetimpl.nim
@@ -366,11 +366,11 @@ proc computeSizeAlign(conf: ConfigRef; typ: PType) =
           OffsetAccum(maxAlign: 1)
       if tfUnion in typ.flags:
         if tfPacked in typ.flags:
-          let info = if typ.sym != nil: typ.sym.info else: unknownLineInfo()
+          let info = if typ.sym != nil: typ.sym.info else: unknownLineInfo
           localError(conf, info, "union type may not be packed.")
           accum = OffsetAccum(offset: szUnknownSize, maxAlign: szUnknownSize)
         elif accum.offset != 0:
-          let info = if typ.sym != nil: typ.sym.info else: unknownLineInfo()
+          let info = if typ.sym != nil: typ.sym.info else: unknownLineInfo
           localError(conf, info, "union type may not have an object header")
           accum = OffsetAccum(offset: szUnknownSize, maxAlign: szUnknownSize)
         else:
diff --git a/compiler/vm.nim b/compiler/vm.nim
index 7d3d608ff..d190c4645 100644
--- a/compiler/vm.nim
+++ b/compiler/vm.nim
@@ -108,12 +108,12 @@ proc bailOut(c: PCtx; tos: PStackFrame) =
 when not defined(nimComputedGoto):
   {.pragma: computedGoto.}
 
-proc myreset(n: var TFullReg) = reset(n)
+proc ensureKind(n: var TFullReg, kind: TRegisterKind) =
+  if n.kind != kind:
+    n = TFullReg(kind: kind)
 
 template ensureKind(k: untyped) {.dirty.} =
-  if regs[ra].kind != k:
-    myreset(regs[ra])
-    regs[ra].kind = k
+  ensureKind(regs[ra], k)
 
 template decodeB(k: untyped) {.dirty.} =
   let rb = instr.regB
@@ -146,10 +146,7 @@ proc derefPtrToReg(address: BiggestInt, typ: PType, r: var TFullReg, isAssign: b
     if isAssign:
       cast[ptr T](address)[] = T(r.field)
     else:
-      # ensureKind(rkind)
-      if r.kind != rkind:
-        myreset(r)
-        r.kind = rkind
+      r.ensureKind(rkind)
       let val = cast[ptr T](address)[]
       when T is SomeInteger:
         r.field = BiggestInt(val)
@@ -180,8 +177,7 @@ proc createStrKeepNode(x: var TFullReg; keepNode=true) =
   elif x.node.kind == nkNilLit and keepNode:
     when defined(useNodeIds):
       let id = x.node.id
-    system.reset(x.node[])
-    x.node.kind = nkStrLit
+    x.node[] = TNode(kind: nkStrLit)
     when defined(useNodeIds):
       x.node.id = id
   elif x.node.kind notin {nkStrLit..nkTripleStrLit} or
@@ -201,9 +197,7 @@ template createSet(x) =
   x.node = newNode(nkCurly)
 
 proc moveConst(x: var TFullReg, y: TFullReg) =
-  if x.kind != y.kind:
-    myreset(x)
-    x.kind = y.kind
+  x.ensureKind(y.kind)
   case x.kind
   of rkNone: discard
   of rkInt: x.intVal = y.intVal
@@ -239,9 +233,7 @@ proc copyValue(src: PNode): PNode =
       result[i] = copyValue(src[i])
 
 proc asgnComplex(x: var TFullReg, y: TFullReg) =
-  if x.kind != y.kind:
-    myreset(x)
-    x.kind = y.kind
+  x.ensureKind(y.kind)
   case x.kind
   of rkNone: discard
   of rkInt: x.intVal = y.intVal
@@ -251,9 +243,7 @@ proc asgnComplex(x: var TFullReg, y: TFullReg) =
   of rkNodeAddr: x.nodeAddr = y.nodeAddr
 
 proc fastAsgnComplex(x: var TFullReg, y: TFullReg) =
-  if x.kind != y.kind:
-    myreset(x)
-    x.kind = y.kind
+  x.ensureKind(y.kind)
   case x.kind
   of rkNone: discard
   of rkInt: x.intVal = y.intVal
@@ -267,8 +257,7 @@ proc writeField(n: var PNode, x: TFullReg) =
   of rkNone: discard
   of rkInt:
     if n.kind == nkNilLit:
-      n[].reset
-      n.kind = nkIntLit # ideally, `nkPtrLit`
+      n[] = TNode(kind: nkIntLit) # ideally, `nkPtrLit`
     n.intVal = x.intVal
   of rkFloat: n.floatVal = x.floatVal
   of rkNode: n = copyValue(x.node)
@@ -276,26 +265,21 @@ proc writeField(n: var PNode, x: TFullReg) =
   of rkNodeAddr: n = x.nodeAddr[]
 
 proc putIntoReg(dest: var TFullReg; n: PNode) =
-  template funInt() =
-    dest.kind = rkInt
-    dest.intVal = n.intVal
   case n.kind
   of nkStrLit..nkTripleStrLit:
-    dest.kind = rkNode
-    createStr(dest)
-    dest.node.strVal = n.strVal
+    dest = TFullReg(kind: rkNode, node: newStrNode(nkStrLit, n.strVal))
   of nkIntLit: # use `nkPtrLit` once this is added
     if dest.kind == rkNode: dest.node = n
     elif n.typ != nil and n.typ.kind in PtrLikeKinds:
       dest = TFullReg(kind: rkNode, node: n)
-    else: funInt()
-  of {nkCharLit..nkUInt64Lit} - {nkIntLit}: funInt()
+    else:
+      dest = TFullReg(kind: rkInt, intVal: n.intVal)
+  of {nkCharLit..nkUInt64Lit} - {nkIntLit}:
+    dest = TFullReg(kind: rkInt, intVal: n.intVal)
   of nkFloatLit..nkFloat128Lit:
-    dest.kind = rkFloat
-    dest.floatVal = n.floatVal
+    dest = TFullReg(kind: rkFloat, floatVal: n.floatVal)
   else:
-    dest.kind = rkNode
-    dest.node = n
+    dest = TFullReg(kind: rkNode, node: n)
 
 proc regToNode(x: TFullReg): PNode =
   case x.kind
@@ -413,9 +397,7 @@ proc cleanUpOnReturn(c: PCtx; f: PStackFrame): int =
 
 proc opConv(c: PCtx; dest: var TFullReg, src: TFullReg, desttyp, srctyp: PType): bool =
   if desttyp.kind == tyString:
-    if dest.kind != rkNode:
-      myreset(dest)
-      dest.kind = rkNode
+    dest.ensureKind(rkNode)
     dest.node = newNode(nkStrLit)
     let styp = srctyp.skipTypes(abstractRange)
     case styp.kind
@@ -460,8 +442,7 @@ proc opConv(c: PCtx; dest: var TFullReg, src: TFullReg, desttyp, srctyp: PType):
   else:
     case skipTypes(desttyp, abstractVarRange).kind
     of tyInt..tyInt64:
-      if dest.kind != rkInt:
-        myreset(dest); dest.kind = rkInt
+      dest.ensureKind(rkInt)
       case skipTypes(srctyp, abstractRange).kind
       of tyFloat..tyFloat64:
         dest.intVal = int(src.floatVal)
@@ -470,8 +451,7 @@ proc opConv(c: PCtx; dest: var TFullReg, src: TFullReg, desttyp, srctyp: PType):
       if toInt128(dest.intVal) < firstOrd(c.config, desttyp) or toInt128(dest.intVal) > lastOrd(c.config, desttyp):
         return true
     of tyUInt..tyUInt64:
-      if dest.kind != rkInt:
-        myreset(dest); dest.kind = rkInt
+      dest.ensureKind(rkInt)
       case skipTypes(srctyp, abstractRange).kind
       of tyFloat..tyFloat64:
         dest.intVal = int(src.floatVal)
@@ -484,8 +464,7 @@ proc opConv(c: PCtx; dest: var TFullReg, src: TFullReg, desttyp, srctyp: PType):
         value = (value shl destDist) shr destDist
         dest.intVal = cast[BiggestInt](value)
     of tyFloat..tyFloat64:
-      if dest.kind != rkFloat:
-        myreset(dest); dest.kind = rkFloat
+      dest.ensureKind(rkFloat)
       case skipTypes(srctyp, abstractRange).kind
       of tyInt..tyInt64, tyUInt..tyUInt64, tyEnum, tyBool, tyChar:
         dest.floatVal = toBiggestFloat(src.intVal)
@@ -1206,8 +1185,7 @@ proc rawExecute(c: PCtx, start: int, tos: PStackFrame): TFullReg =
       var rcAddr = addr(regs[rc])
       if rcAddr.kind == rkRegisterAddr: rcAddr = rcAddr.regAddr
       elif regs[rc].kind != rkFloat:
-        myreset(regs[rc])
-        regs[rc].kind = rkFloat
+        regs[rc] = TFullReg(kind: rkFloat)
       regs[ra].intVal = parseBiggestFloat(regs[rb].node.strVal,
                                           rcAddr.floatVal, regs[rd].intVal.int)
     of opcRangeChck:
@@ -1267,8 +1245,7 @@ proc rawExecute(c: PCtx, start: int, tos: PStackFrame): TFullReg =
         for i in 1..rc-1:
           newFrame.slots[i] = regs[rb+i]
         if isClosure:
-          newFrame.slots[rc].kind = rkNode
-          newFrame.slots[rc].node = regs[rb].node[1]
+          newFrame.slots[rc] = TFullReg(kind: rkNode, node: regs[rb].node[1])
         tos = newFrame
         move(regs, newFrame.slots)
         # -1 for the following 'inc pc'
@@ -1432,7 +1409,7 @@ proc rawExecute(c: PCtx, start: int, tos: PStackFrame): TFullReg =
       let rb = instr.regBx - wordExcess
       let cnst = c.constants[rb]
       if fitsRegister(cnst.typ):
-        myreset(regs[ra])
+        reset(regs[ra])
         putIntoReg(regs[ra], cnst)
       else:
         ensureKind(rkNode)
@@ -2259,13 +2236,12 @@ proc setupMacroParam(x: PNode, typ: PType): TFullReg =
   of tyStatic:
     putIntoReg(result, prepareVMValue(x))
   else:
-    result.kind = rkNode
     var n = x
     if n.kind in {nkHiddenSubConv, nkHiddenStdConv}: n = n[1]
     n = n.canonValue
     n.flags.incl nfIsRef
     n.typ = x.typ
-    result.node = n
+    result = TFullReg(kind: rkNode, node: n)
 
 iterator genericParamsInMacroCall*(macroSym: PSym, call: PNode): (PSym, PNode) =
   let gp = macroSym.ast[genericParamsPos]
@@ -2317,8 +2293,7 @@ proc evalMacroCall*(module: PSym; g: ModuleGraph;
   #InternalAssert tos.slots.len >= L
 
   # return value:
-  tos.slots[0].kind = rkNode
-  tos.slots[0].node = newNodeI(nkEmpty, n.info)
+  tos.slots[0] = TFullReg(kind: rkNode, node: newNodeI(nkEmpty, n.info))
 
   # setup parameters:
   for i in 1..<sym.typ.len:
diff --git a/compiler/vmdef.nim b/compiler/vmdef.nim
index b46d8a293..6c359c9b1 100644
--- a/compiler/vmdef.nim
+++ b/compiler/vmdef.nim
@@ -260,7 +260,7 @@ proc newCtx*(module: PSym; cache: IdentCache; g: ModuleGraph): PCtx =
   PCtx(code: @[], debug: @[],
     globals: newNode(nkStmtListExpr), constants: newNode(nkStmtList), types: @[],
     prc: PProc(blocks: @[]), module: module, loopIterations: MaxLoopIterations,
-    comesFromHeuristic: unknownLineInfo(), callbacks: @[], errorFlag: "",
+    comesFromHeuristic: unknownLineInfo, callbacks: @[], errorFlag: "",
     cache: cache, config: g.config, graph: g)
 
 proc refresh*(c: PCtx, module: PSym) =
diff --git a/compiler/vmhooks.nim b/compiler/vmhooks.nim
index 39e435e4b..412c93a77 100644
--- a/compiler/vmhooks.nim
+++ b/compiler/vmhooks.nim
@@ -12,9 +12,7 @@ import pathutils
 template setX(k, field) {.dirty.} =
   var s: seq[TFullReg]
   move(s, cast[seq[TFullReg]](a.slots))
-  if s[a.ra].kind != k:
-    myreset(s[a.ra])
-    s[a.ra].kind = k
+  s[a.ra].ensureKind(k)
   s[a.ra].field = v
 
 proc setResult*(a: VmArgs; v: BiggestInt) = setX(rkInt, intVal)
@@ -26,18 +24,14 @@ proc setResult*(a: VmArgs; v: bool) =
 proc setResult*(a: VmArgs; v: string) =
   var s: seq[TFullReg]
   move(s, cast[seq[TFullReg]](a.slots))
-  if s[a.ra].kind != rkNode:
-    myreset(s[a.ra])
-    s[a.ra].kind = rkNode
+  s[a.ra].ensureKind(rkNode)
   s[a.ra].node = newNode(nkStrLit)
   s[a.ra].node.strVal = v
 
 proc setResult*(a: VmArgs; n: PNode) =
   var s: seq[TFullReg]
   move(s, cast[seq[TFullReg]](a.slots))
-  if s[a.ra].kind != rkNode:
-    myreset(s[a.ra])
-    s[a.ra].kind = rkNode
+  s[a.ra].ensureKind(rkNode)
   s[a.ra].node = n
 
 proc setResult*(a: VmArgs; v: AbsoluteDir) = setResult(a, v.string)
@@ -45,9 +39,7 @@ proc setResult*(a: VmArgs; v: AbsoluteDir) = setResult(a, v.string)
 proc setResult*(a: VmArgs; v: seq[string]) =
   var s: seq[TFullReg]
   move(s, cast[seq[TFullReg]](a.slots))
-  if s[a.ra].kind != rkNode:
-    myreset(s[a.ra])
-    s[a.ra].kind = rkNode
+  s[a.ra].ensureKind(rkNode)
   var n = newNode(nkBracket)
   for x in v: n.add newStrNode(nkStrLit, x)
   s[a.ra].node = n
diff --git a/compiler/vmmarshal.nim b/compiler/vmmarshal.nim
index 541fef890..ffadab4f4 100644
--- a/compiler/vmmarshal.nim
+++ b/compiler/vmmarshal.nim
@@ -224,7 +224,7 @@ proc loadAny(p: var JsonParser, t: PType,
       if pos >= result.len:
         setLen(result.sons, pos + 1)
       let fieldNode = newNode(nkExprColonExpr)
-      fieldNode.add newSymNode(newSym(skField, ident, nil, unknownLineInfo()))
+      fieldNode.add newSymNode(newSym(skField, ident, nil, unknownLineInfo))
       fieldNode.add loadAny(p, field.typ, tab, cache, conf)
       result[pos] = fieldNode
     if p.kind == jsonObjectEnd: next(p)
diff --git a/nimpretty/nimpretty.nim.cfg b/nimpretty/nimpretty.nim.cfg
index 138bce52e..25336d924 100644
--- a/nimpretty/nimpretty.nim.cfg
+++ b/nimpretty/nimpretty.nim.cfg
@@ -1,2 +1 @@
 --define: nimpretty
---define: nimOldCaseObjects
diff --git a/nimsuggest/nimsuggest.nim.cfg b/nimsuggest/nimsuggest.nim.cfg
index 302c30965..394449740 100644
--- a/nimsuggest/nimsuggest.nim.cfg
+++ b/nimsuggest/nimsuggest.nim.cfg
@@ -22,4 +22,3 @@ define:nimcore
 #define:noDocgen
 --path:"$nim"
 --threads:on
---define:nimOldCaseObjects
diff --git a/tests/compilerapi/tcompilerapi.nim.cfg b/tests/compilerapi/tcompilerapi.nim.cfg
deleted file mode 100644
index 08e3312be..000000000
--- a/tests/compilerapi/tcompilerapi.nim.cfg
+++ /dev/null
@@ -1 +0,0 @@
-define:nimOldCaseObjects