diff options
author | Andreas Rumpf <rumpf_a@web.de> | 2019-05-26 23:10:34 +0200 |
---|---|---|
committer | Andreas Rumpf <rumpf_a@web.de> | 2019-05-27 21:29:02 +0200 |
commit | 49e686ab4e8103173ecb39cc16896eb979ddf9ce (patch) | |
tree | 61c40522d19e63c3bd86251a2a62bb57cf08022a | |
parent | 247fa431de9587b59978a1c8a7b20da6fe44f95e (diff) | |
download | Nim-49e686ab4e8103173ecb39cc16896eb979ddf9ce.tar.gz |
fixes #1286; object case transitions are now sound
-rw-r--r-- | changelog.md | 3 | ||||
-rw-r--r-- | compiler/nim.cfg | 1 | ||||
-rw-r--r-- | doc/manual.rst | 21 | ||||
-rw-r--r-- | lib/pure/asyncnet.nim | 24 | ||||
-rw-r--r-- | lib/pure/collections/critbits.nim | 8 | ||||
-rw-r--r-- | lib/pure/json.nim | 57 | ||||
-rw-r--r-- | lib/pure/net.nim | 28 | ||||
-rw-r--r-- | lib/pure/parsecfg.nim | 30 | ||||
-rw-r--r-- | lib/pure/parsesql.nim | 9 | ||||
-rw-r--r-- | lib/pure/pegs.nim | 94 | ||||
-rw-r--r-- | lib/pure/xmltree.nim | 3 | ||||
-rw-r--r-- | lib/system.nim | 2 | ||||
-rw-r--r-- | lib/system/assign.nim | 8 | ||||
-rw-r--r-- | tests/compilerapi/tcompilerapi.nim.cfg | 1 |
14 files changed, 123 insertions, 166 deletions
diff --git a/changelog.md b/changelog.md index 47d4460df..b55a92b0f 100644 --- a/changelog.md +++ b/changelog.md @@ -115,6 +115,9 @@ ints and floats to string have been deprecated. Use `string.addInt(int)` and `string.addFloat(float)` instead. +- ``case object`` branch transitions via ``system.reset`` are deprecated. + Compile your code with ``-d:nimOldCaseObjects`` for a transition period. + #### Breaking changes in the compiler diff --git a/compiler/nim.cfg b/compiler/nim.cfg index 5104f9fcd..5a30efd6f 100644 --- a/compiler/nim.cfg +++ b/compiler/nim.cfg @@ -12,6 +12,7 @@ define:nimcore @end define:useStdoutAsStdmsg +define:nimOldCaseObjects #define:useNodeIds #gc:markAndSweep diff --git a/doc/manual.rst b/doc/manual.rst index 615b8e302..fafc1ea5b 100644 --- a/doc/manual.rst +++ b/doc/manual.rst @@ -1538,10 +1538,23 @@ the ``case`` statement: The branches in a ``case`` section may be indented too. In the example the ``kind`` field is called the `discriminator`:idx:\: For safety its address cannot be taken and assignments to it are restricted: The -new value must not lead to a change of the active object branch. For an object -branch switch ``system.reset`` has to be used. Also, when the fields of a -particular branch are specified during object construction, the corresponding -discriminator value must be specified as a constant expression. +new value must not lead to a change of the active object branch. Also, when the +fields of a particular branch are specified during object construction, the +corresponding discriminator value must be specified as a constant expression. + +Instead of changing the active object branch, replace the old object in memory +with a new one completely: + +.. code-block:: nim + + var x = Node(kind: nkAdd, leftOp: Node(kind: nkInt, intVal: 4), + rightOp: Node(kind: nkInt, intVal: 2)) + # change the node's contents: + x[] = NodeObj(kind: nkString, strVal: "abc") + + +Starting with version 0.20 ``system.reset`` cannot be used anymore to support +object branch changes as this never was completely memory safe. As a special rule, the discriminator kind can also be bounded using a ``case`` statement. If possible values of the discriminator variable in a diff --git a/lib/pure/asyncnet.nim b/lib/pure/asyncnet.nim index d7cb5a18a..32b7d8da9 100644 --- a/lib/pure/asyncnet.nim +++ b/lib/pure/asyncnet.nim @@ -115,20 +115,16 @@ type AsyncSocketDesc = object fd: SocketHandle closed: bool ## determines whether this socket has been closed - case isBuffered: bool ## determines whether this socket is buffered. - of true: - buffer: array[0..BufferSize, char] - currPos: int # current index in buffer - bufLen: int # current length of buffer - of false: nil - case isSsl: bool - of true: - when defineSsl: - sslHandle: SslPtr - sslContext: SslContext - bioIn: BIO - bioOut: BIO - of false: nil + isBuffered: bool ## determines whether this socket is buffered. + buffer: array[0..BufferSize, char] + currPos: int # current index in buffer + bufLen: int # current length of buffer + isSsl: bool + when defineSsl: + sslHandle: SslPtr + sslContext: SslContext + bioIn: BIO + bioOut: BIO domain: Domain sockType: SockType protocol: Protocol diff --git a/lib/pure/collections/critbits.nim b/lib/pure/collections/critbits.nim index dd91fdb12..af5a36cf2 100644 --- a/lib/pure/collections/critbits.nim +++ b/lib/pure/collections/critbits.nim @@ -57,9 +57,7 @@ proc hasKey*[T](c: CritBitTree[T], key: string): bool {.inline.} = proc rawInsert[T](c: var CritBitTree[T], key: string): Node[T] = if c.root == nil: - new c.root - c.root.isleaf = true - c.root.key = key + c.root = Node[T](isleaf: true, key: key) result = c.root else: var it = c.root @@ -89,9 +87,7 @@ proc rawInsert[T](c: var CritBitTree[T], key: string): Node[T] = var inner: Node[T] new inner - new result - result.isLeaf = true - result.key = key + result = Node[T](isLeaf: true, key: key) inner.otherBits = chr(newOtherBits) inner.byte = newByte inner.child[1 - dir] = result diff --git a/lib/pure/json.nim b/lib/pure/json.nim index 4b58f9f95..ed560d7e4 100644 --- a/lib/pure/json.nim +++ b/lib/pure/json.nim @@ -188,48 +188,35 @@ type proc newJString*(s: string): JsonNode = ## Creates a new `JString JsonNode`. - new(result) - result.kind = JString - result.str = s + result = JsonNode(kind: JString, str: s) proc newJStringMove(s: string): JsonNode = - new(result) - result.kind = JString + result = JsonNode(kind: JString) shallowCopy(result.str, s) proc newJInt*(n: BiggestInt): JsonNode = ## Creates a new `JInt JsonNode`. - new(result) - result.kind = JInt - result.num = n + result = JsonNode(kind: JInt, num: n) proc newJFloat*(n: float): JsonNode = ## Creates a new `JFloat JsonNode`. - new(result) - result.kind = JFloat - result.fnum = n + result = JsonNode(kind: JFloat, fnum: n) proc newJBool*(b: bool): JsonNode = ## Creates a new `JBool JsonNode`. - new(result) - result.kind = JBool - result.bval = b + result = JsonNode(kind: JBool, bval: b) proc newJNull*(): JsonNode = ## Creates a new `JNull JsonNode`. - new(result) + result = JsonNode(kind: JNull) proc newJObject*(): JsonNode = ## Creates a new `JObject JsonNode` - new(result) - result.kind = JObject - result.fields = initOrderedTable[string, JsonNode](4) + result = JsonNode(kind: JObject, fields: initOrderedTable[string, JsonNode](4)) proc newJArray*(): JsonNode = ## Creates a new `JArray JsonNode` - new(result) - result.kind = JArray - result.elems = @[] + result = JsonNode(kind: JArray, elems: @[]) proc getStr*(n: JsonNode, default: string = ""): string = ## Retrieves the string value of a `JString JsonNode`. @@ -309,45 +296,31 @@ proc add*(obj: JsonNode, key: string, val: JsonNode) = proc `%`*(s: string): JsonNode = ## Generic constructor for JSON data. Creates a new `JString JsonNode`. - new(result) - result.kind = JString - result.str = s + result = JsonNode(kind: JString, str: s) proc `%`*(n: uint): JsonNode = ## Generic constructor for JSON data. Creates a new `JInt JsonNode`. - new(result) - result.kind = JInt - result.num = BiggestInt(n) + result = JsonNode(kind: JInt, num: BiggestInt(n)) proc `%`*(n: int): JsonNode = ## Generic constructor for JSON data. Creates a new `JInt JsonNode`. - new(result) - result.kind = JInt - result.num = n + result = JsonNode(kind: JInt, num: n) proc `%`*(n: BiggestUInt): JsonNode = ## Generic constructor for JSON data. Creates a new `JInt JsonNode`. - new(result) - result.kind = JInt - result.num = BiggestInt(n) + result = JsonNode(kind: JInt, num: BiggestInt(n)) proc `%`*(n: BiggestInt): JsonNode = ## Generic constructor for JSON data. Creates a new `JInt JsonNode`. - new(result) - result.kind = JInt - result.num = n + result = JsonNode(kind: JInt, num: n) proc `%`*(n: float): JsonNode = ## Generic constructor for JSON data. Creates a new `JFloat JsonNode`. - new(result) - result.kind = JFloat - result.fnum = n + result = JsonNode(kind: JFloat, fnum: n) proc `%`*(b: bool): JsonNode = ## Generic constructor for JSON data. Creates a new `JBool JsonNode`. - new(result) - result.kind = JBool - result.bval = b + result = JsonNode(kind: JBool, bval: b) proc `%`*(keyVals: openArray[tuple[key: string, val: JsonNode]]): JsonNode = ## Generic constructor for JSON data. Creates a new `JObject JsonNode` diff --git a/lib/pure/net.nim b/lib/pure/net.nim index 69a221a6c..7dc2d318b 100644 --- a/lib/pure/net.nim +++ b/lib/pure/net.nim @@ -117,21 +117,17 @@ const type SocketImpl* = object ## socket type fd: SocketHandle - case isBuffered: bool # determines whether this socket is buffered. - of true: - buffer: array[0..BufferSize, char] - currPos: int # current index in buffer - bufLen: int # current length of buffer - of false: nil + isBuffered: bool # determines whether this socket is buffered. + buffer: array[0..BufferSize, char] + currPos: int # current index in buffer + bufLen: int # current length of buffer when defineSsl: - case isSsl: bool - of true: - sslHandle: SSLPtr - sslContext: SSLContext - sslNoHandshake: bool # True if needs handshake. - sslHasPeekChar: bool - sslPeekChar: char - of false: nil + isSsl: bool + sslHandle: SSLPtr + sslContext: SSLContext + sslNoHandshake: bool # True if needs handshake. + sslHasPeekChar: bool + sslPeekChar: char lastError: OSErrorCode ## stores the last error on this socket domain: Domain sockType: SockType @@ -235,7 +231,7 @@ proc parseIPv4Address(addressStr: string): IpAddress = currentByte:uint16 = 0 separatorValid = false - result.family = IpAddressFamily.IPv4 + result = IpAddress(family: IpAddressFamily.IPv4) for i in 0 .. high(addressStr): if addressStr[i] in strutils.Digits: # Character is a number @@ -264,7 +260,7 @@ proc parseIPv4Address(addressStr: string): IpAddress = proc parseIPv6Address(addressStr: string): IpAddress = ## Parses IPv6 adresses ## Raises ValueError on errors - result.family = IpAddressFamily.IPv6 + result = IpAddress(family: IpAddressFamily.IPv6) if addressStr.len < 2: raise newException(ValueError, "Invalid IP Address") diff --git a/lib/pure/parsecfg.nim b/lib/pure/parsecfg.nim index d85359953..90ec1a8cd 100644 --- a/lib/pure/parsecfg.nim +++ b/lib/pure/parsecfg.nim @@ -391,29 +391,27 @@ proc ignoreMsg*(c: CfgParser, e: CfgEvent): string {.rtl, extern: "npc$1".} = proc getKeyValPair(c: var CfgParser, kind: CfgEventKind): CfgEvent = if c.tok.kind == tkSymbol: + result = CfgEvent(kind: cfgKeyValuePair, key: c.tok.literal, value: "") result.kind = kind - result.key = c.tok.literal - result.value = "" rawGetTok(c, c.tok) if c.tok.kind in {tkEquals, tkColon}: rawGetTok(c, c.tok) if c.tok.kind == tkSymbol: result.value = c.tok.literal else: - reset result - result.kind = cfgError - result.msg = errorStr(c, "symbol expected, but found: " & c.tok.literal) + result = CfgEvent(kind: cfgError, + msg: errorStr(c, "symbol expected, but found: " & c.tok.literal)) rawGetTok(c, c.tok) else: - result.kind = cfgError - result.msg = errorStr(c, "symbol expected, but found: " & c.tok.literal) + result = CfgEvent(kind: cfgError, + msg: errorStr(c, "symbol expected, but found: " & c.tok.literal)) rawGetTok(c, c.tok) proc next*(c: var CfgParser): CfgEvent {.rtl, extern: "npc$1".} = ## retrieves the first/next event. This controls the parser. case c.tok.kind of tkEof: - result.kind = cfgEof + result = CfgEvent(kind: cfgEof) of tkDashDash: rawGetTok(c, c.tok) result = getKeyValPair(c, cfgOption) @@ -422,21 +420,19 @@ proc next*(c: var CfgParser): CfgEvent {.rtl, extern: "npc$1".} = of tkBracketLe: rawGetTok(c, c.tok) if c.tok.kind == tkSymbol: - result.kind = cfgSectionStart - result.section = c.tok.literal + result = CfgEvent(kind: cfgSectionStart, section: c.tok.literal) else: - result.kind = cfgError - result.msg = errorStr(c, "symbol expected, but found: " & c.tok.literal) + result = CfgEvent(kind: cfgError, + msg: errorStr(c, "symbol expected, but found: " & c.tok.literal)) rawGetTok(c, c.tok) if c.tok.kind == tkBracketRi: rawGetTok(c, c.tok) else: - reset(result) - result.kind = cfgError - result.msg = errorStr(c, "']' expected, but found: " & c.tok.literal) + result = CfgEvent(kind: cfgError, + msg: errorStr(c, "']' expected, but found: " & c.tok.literal)) of tkInvalid, tkEquals, tkColon, tkBracketRi: - result.kind = cfgError - result.msg = errorStr(c, "invalid token: " & c.tok.literal) + result = CfgEvent(kind: cfgError, + msg: errorStr(c, "invalid token: " & c.tok.literal)) rawGetTok(c, c.tok) # ---------------- Configuration file related operations ---------------- diff --git a/lib/pure/parsesql.nim b/lib/pure/parsesql.nim index abe712e7f..8cc0ffedf 100644 --- a/lib/pure/parsesql.nim +++ b/lib/pure/parsesql.nim @@ -554,17 +554,14 @@ type tok: Token proc newNode*(k: SqlNodeKind): SqlNode = - new(result) - result.kind = k + result = SqlNode(kind: k) proc newNode*(k: SqlNodeKind, s: string): SqlNode = - new(result) - result.kind = k + result = SqlNode(kind: k) result.strVal = s proc newNode*(k: SqlNodeKind, sons: seq[SqlNode]): SqlNode = - new(result) - result.kind = k + result = SqlNode(kind: k) result.sons = sons proc len*(n: SqlNode): int = diff --git a/lib/pure/pegs.nim b/lib/pure/pegs.nim index 26ebb916e..3e28307a1 100644 --- a/lib/pure/pegs.nim +++ b/lib/pure/pegs.nim @@ -142,34 +142,29 @@ proc rule*(nt: NonTerminal): Peg = nt.rule proc term*(t: string): Peg {.nosideEffect, rtl, extern: "npegs$1Str".} = ## constructs a PEG from a terminal string if t.len != 1: - result.kind = pkTerminal - result.term = t + result = Peg(kind: pkTerminal, term: t) else: - result.kind = pkChar - result.ch = t[0] + result = Peg(kind: pkChar, ch: t[0]) proc termIgnoreCase*(t: string): Peg {. nosideEffect, rtl, extern: "npegs$1".} = ## constructs a PEG from a terminal string; ignore case for matching - result.kind = pkTerminalIgnoreCase - result.term = t + result = Peg(kind: pkTerminalIgnoreCase, term: t) proc termIgnoreStyle*(t: string): Peg {. nosideEffect, rtl, extern: "npegs$1".} = ## constructs a PEG from a terminal string; ignore style for matching - result.kind = pkTerminalIgnoreStyle - result.term = t + result = Peg(kind: pkTerminalIgnoreStyle, term: t) proc term*(t: char): Peg {.nosideEffect, rtl, extern: "npegs$1Char".} = ## constructs a PEG from a terminal char assert t != '\0' - result.kind = pkChar - result.ch = t + result = Peg(kind: pkChar, ch: t) proc charSet*(s: set[char]): Peg {.nosideEffect, rtl, extern: "npegs$1".} = ## constructs a PEG from a character set `s` assert '\0' notin s - result.kind = pkCharChoice + result = Peg(kind: pkCharChoice) new(result.charChoice) result.charChoice[] = s @@ -189,8 +184,7 @@ proc addChoice(dest: var Peg, elem: Peg) = else: add(dest, elem) template multipleOp(k: PegKind, localOpt: untyped) = - result.kind = k - result.sons = @[] + result = Peg(kind: k, sons: @[]) for x in items(a): if x.kind == k: for y in items(x.sons): @@ -230,8 +224,7 @@ proc `?`*(a: Peg): Peg {.nosideEffect, rtl, extern: "npegsOptional".} = # a? ? --> a? result = a else: - result.kind = pkOption - result.sons = @[a] + result = Peg(kind: pkOption, sons: @[a]) proc `*`*(a: Peg): Peg {.nosideEffect, rtl, extern: "npegsGreedyRep".} = ## constructs a "greedy repetition" for the PEG `a` @@ -240,27 +233,22 @@ proc `*`*(a: Peg): Peg {.nosideEffect, rtl, extern: "npegsGreedyRep".} = assert false # produces endless loop! of pkChar: - result.kind = pkGreedyRepChar - result.ch = a.ch + result = Peg(kind: pkGreedyRepChar, ch: a.ch) of pkCharChoice: - result.kind = pkGreedyRepSet - result.charChoice = a.charChoice # copying a reference suffices! + result = Peg(kind: pkGreedyRepSet, charChoice: a.charChoice) of pkAny, pkAnyRune: - result.kind = pkGreedyAny + result = Peg(kind: pkGreedyAny) else: - result.kind = pkGreedyRep - result.sons = @[a] + result = Peg(kind: pkGreedyRep, sons: @[a]) proc `!*`*(a: Peg): Peg {.nosideEffect, rtl, extern: "npegsSearch".} = ## constructs a "search" for the PEG `a` - result.kind = pkSearch - result.sons = @[a] + result = Peg(kind: pkSearch, sons: @[a]) proc `!*\`*(a: Peg): Peg {.noSideEffect, rtl, extern: "npgegsCapturedSearch".} = ## constructs a "captured search" for the PEG `a` - result.kind = pkCapturedSearch - result.sons = @[a] + result = Peg(kind: pkCapturedSearch, sons: @[a]) proc `+`*(a: Peg): Peg {.nosideEffect, rtl, extern: "npegsGreedyPosRep".} = ## constructs a "greedy positive repetition" with the PEG `a` @@ -268,50 +256,48 @@ proc `+`*(a: Peg): Peg {.nosideEffect, rtl, extern: "npegsGreedyPosRep".} = proc `&`*(a: Peg): Peg {.nosideEffect, rtl, extern: "npegsAndPredicate".} = ## constructs an "and predicate" with the PEG `a` - result.kind = pkAndPredicate - result.sons = @[a] + result = Peg(kind: pkAndPredicate, sons: @[a]) proc `!`*(a: Peg): Peg {.nosideEffect, rtl, extern: "npegsNotPredicate".} = ## constructs a "not predicate" with the PEG `a` - result.kind = pkNotPredicate - result.sons = @[a] + result = Peg(kind: pkNotPredicate, sons: @[a]) proc any*: Peg {.inline.} = ## constructs the PEG `any character`:idx: (``.``) - result.kind = pkAny + result = Peg(kind: pkAny) proc anyRune*: Peg {.inline.} = ## constructs the PEG `any rune`:idx: (``_``) - result.kind = pkAnyRune + result = Peg(kind: pkAnyRune) proc newLine*: Peg {.inline.} = ## constructs the PEG `newline`:idx: (``\n``) - result.kind = pkNewLine + result = Peg(kind: pkNewLine) proc unicodeLetter*: Peg {.inline.} = ## constructs the PEG ``\letter`` which matches any Unicode letter. - result.kind = pkLetter + result = Peg(kind: pkLetter) proc unicodeLower*: Peg {.inline.} = ## constructs the PEG ``\lower`` which matches any Unicode lowercase letter. - result.kind = pkLower + result = Peg(kind: pkLower) proc unicodeUpper*: Peg {.inline.} = ## constructs the PEG ``\upper`` which matches any Unicode uppercase letter. - result.kind = pkUpper + result = Peg(kind: pkUpper) proc unicodeTitle*: Peg {.inline.} = ## constructs the PEG ``\title`` which matches any Unicode title letter. - result.kind = pkTitle + result = Peg(kind: pkTitle) proc unicodeWhitespace*: Peg {.inline.} = ## constructs the PEG ``\white`` which matches any Unicode ## whitespace character. - result.kind = pkWhitespace + result = Peg(kind: pkWhitespace) proc startAnchor*: Peg {.inline.} = ## constructs the PEG ``^`` which matches the start of the input. - result.kind = pkStartAnchor + result = Peg(kind: pkStartAnchor) proc endAnchor*: Peg {.inline.} = ## constructs the PEG ``$`` which matches the end of the input. @@ -319,29 +305,25 @@ proc endAnchor*: Peg {.inline.} = proc capture*(a: Peg): Peg {.nosideEffect, rtl, extern: "npegsCapture".} = ## constructs a capture with the PEG `a` - result.kind = pkCapture - result.sons = @[a] + result = Peg(kind: pkCapture, sons: @[a]) proc backref*(index: range[1..MaxSubpatterns]): Peg {. nosideEffect, rtl, extern: "npegs$1".} = ## constructs a back reference of the given `index`. `index` starts counting ## from 1. - result.kind = pkBackRef - result.index = index-1 + result = Peg(kind: pkBackRef, index: index-1) proc backrefIgnoreCase*(index: range[1..MaxSubpatterns]): Peg {. nosideEffect, rtl, extern: "npegs$1".} = ## constructs a back reference of the given `index`. `index` starts counting ## from 1. Ignores case for matching. - result.kind = pkBackRefIgnoreCase - result.index = index-1 + result = Peg(kind: pkBackRefIgnoreCase, index: index-1) proc backrefIgnoreStyle*(index: range[1..MaxSubpatterns]): Peg {. nosideEffect, rtl, extern: "npegs$1".}= ## constructs a back reference of the given `index`. `index` starts counting ## from 1. Ignores style for matching. - result.kind = pkBackRefIgnoreStyle - result.index = index-1 + result = Peg(kind: pkBackRefIgnoreStyle, index: index-1) proc spaceCost(n: Peg): int = case n.kind @@ -366,16 +348,12 @@ proc nonterminal*(n: NonTerminal): Peg {. when false: echo "inlining symbol: ", n.name result = n.rule # inlining of rule enables better optimizations else: - result.kind = pkNonTerminal - result.nt = n + result = Peg(kind: pkNonTerminal, nt: n) proc newNonTerminal*(name: string, line, column: int): NonTerminal {. nosideEffect, rtl, extern: "npegs$1".} = ## constructs a nonterminal symbol - new(result) - result.name = name - result.line = line - result.col = column + result = NonTerminal(name: name, line: line, col: column) template letters*: Peg = ## expands to ``charset({'A'..'Z', 'a'..'z'})`` @@ -585,8 +563,14 @@ template matchOrParse(mopProc: untyped) = if p.index >= c.ml: return -1 var (a, b) = c.matches[p.index] var n: Peg - n.kind = succ(pkTerminal, ord(p.kind)-ord(pkBackRef)) - n.term = s.substr(a, b) + case p.kind + of pkBackRef: + n = Peg(kind: pkTerminal, term: s.substr(a, b)) + of pkBackRefIgnoreStyle: + n = Peg(kind: pkTerminalIgnoreStyle, term: s.substr(a, b)) + of pkBackRefIgnoreCase: + n = Peg(kind: pkTerminalIgnoreCase, term: s.substr(a, b)) + else: assert(false, "impossible case") mopProc(s, n, start, c) case p.kind diff --git a/lib/pure/xmltree.nim b/lib/pure/xmltree.nim index c353f2786..6863d1889 100644 --- a/lib/pure/xmltree.nim +++ b/lib/pure/xmltree.nim @@ -70,8 +70,7 @@ const proc newXmlNode(kind: XmlNodeKind): XmlNode = ## Creates a new ``XmlNode``. - new(result) - result.k = kind + result = XmlNode(k: kind) proc newElement*(tag: string): XmlNode = ## Creates a new ``XmlNode`` of kind ``xnElement`` with the given `tag`. diff --git a/lib/system.nim b/lib/system.nim index 421973cce..37229fa0c 100644 --- a/lib/system.nim +++ b/lib/system.nim @@ -266,8 +266,6 @@ proc new*[T](a: var ref T, finalizer: proc (x: ref T) {.nimcall.}) {. proc reset*[T](obj: var T) {.magic: "Reset", noSideEffect.} ## Resets an object `obj` to its initial (binary zero) value. - ## - ## This needs to be called before any possible `object branch transition`:idx:. proc wasMoved*[T](obj: var T) {.magic: "WasMoved", noSideEffect.} = ## Resets an object `obj` to its initial (binary zero) value to signify diff --git a/lib/system/assign.nim b/lib/system/assign.nim index d4826fe0c..fd6a0ac56 100644 --- a/lib/system/assign.nim +++ b/lib/system/assign.nim @@ -232,5 +232,9 @@ proc FieldDiscriminantCheck(oldDiscVal, newDiscVal: int, L: int) {.compilerProc.} = var oldBranch = selectBranch(oldDiscVal, L, a) var newBranch = selectBranch(newDiscVal, L, a) - if newBranch != oldBranch and oldDiscVal != 0: - sysFatal(FieldError, "assignment to discriminant changes object branch") + when defined(nimOldCaseObjects): + if newBranch != oldBranch and oldDiscVal != 0: + sysFatal(FieldError, "assignment to discriminant changes object branch") + else: + if newBranch != oldBranch: + sysFatal(FieldError, "assignment to discriminant changes object branch") diff --git a/tests/compilerapi/tcompilerapi.nim.cfg b/tests/compilerapi/tcompilerapi.nim.cfg new file mode 100644 index 000000000..08e3312be --- /dev/null +++ b/tests/compilerapi/tcompilerapi.nim.cfg @@ -0,0 +1 @@ +define:nimOldCaseObjects |