mirror of
https://github.com/nim-lang/Nim.git
synced 2026-08-04 22:48:38 +00:00
fixes regressions
This commit is contained in:
@@ -342,6 +342,11 @@ type
|
||||
nfLazyBody # IC: this node is a placeholder for a routine body (bodyPos son)
|
||||
# not yet materialized. Reading its children (via `len`/`safeLen`)
|
||||
# triggers `forceLazyBodyHook`. Process-local, stripped on serialize.
|
||||
nfBroadcast # this `nkBracket` is a *broadcast* default array: a single son
|
||||
# standing for `lengthOrd` identical zero copies (see
|
||||
# `broadcastArrayThreshold`). The flag disambiguates it from an
|
||||
# ordinary 1-element collection (e.g. a seq value that happens to
|
||||
# carry an array type), so it must survive copies + serialization.
|
||||
|
||||
TNodeFlags* = set[TNodeFlag]
|
||||
TTypeFlag* = enum # keep below 32 for efficiency reasons (now: 47)
|
||||
@@ -869,7 +874,8 @@ const
|
||||
nfFromTemplate, nfDefaultRefsParam,
|
||||
nfExecuteOnReload, nfLastRead,
|
||||
nfFirstWrite, nfSkipFieldChecking,
|
||||
nfDisabledOpenSym, nfLazyType}
|
||||
nfDisabledOpenSym, nfLazyType,
|
||||
nfBroadcast}
|
||||
namePos* = 0
|
||||
patternPos* = 1 # empty except for term rewriting macros
|
||||
genericParamsPos* = 2
|
||||
|
||||
@@ -1474,6 +1474,7 @@ proc genFlags*(s: set[TNodeFlag]; dest: var string) =
|
||||
of nfDisabledOpenSym: dest.add "d3"
|
||||
of nfLazyType: dest.add "l1"
|
||||
of nfLazyBody: discard # process-local placeholder; never serialized
|
||||
of nfBroadcast: dest.add "v"
|
||||
|
||||
|
||||
proc parse*(t: typedesc[TNodeFlag]; s: string): set[TNodeFlag] =
|
||||
@@ -1534,6 +1535,7 @@ proc parse*(t: typedesc[TNodeFlag]; s: string): set[TNodeFlag] =
|
||||
inc i
|
||||
else: result.incl nfSem
|
||||
of 't': result.incl nfTransf
|
||||
of 'v': result.incl nfBroadcast
|
||||
of 'w': result.incl nfFirstWrite
|
||||
else: discard
|
||||
inc i
|
||||
|
||||
@@ -29,7 +29,7 @@ const
|
||||
|
||||
nimEnableCovariance* = defined(nimEnableCovariance)
|
||||
|
||||
icFormatVersion* = "28"
|
||||
icFormatVersion* = "29"
|
||||
## Version of the IC cache format (the sem-NIF module layout written by
|
||||
## ast2nif.nim plus the iface/impl/edges side files). Bump it whenever
|
||||
## that layout changes: `commandIc` wipes a nimcache whose `ic.version`
|
||||
|
||||
@@ -641,22 +641,25 @@ const broadcastArrayThreshold* = 32
|
||||
## (`.s.bif`/`.t.bif`), in the VM, and in the generated C (`{0}` zero-fills).
|
||||
|
||||
proc isDefaultBroadcastArray*(n: PNode; conf: ConfigRef): bool =
|
||||
## True iff `n` is a broadcast default array: one son that stands for
|
||||
## `lengthOrd` identical copies. A normal post-sem array literal always has
|
||||
## exactly `lengthOrd` sons, so `len == 1 < lengthOrd` is an unambiguous marker.
|
||||
result = n != nil and n.kind == nkBracket and n.len == 1 and n.typ != nil and
|
||||
n.typ.skipTypes(abstractInst).kind == tyArray and
|
||||
lengthOrd(conf, n.typ.skipTypes(abstractInst)) > One
|
||||
## True iff `n` is a broadcast default array: a single son standing for
|
||||
## `lengthOrd` identical zero copies. Identified by the explicit `nfBroadcast`
|
||||
## marker (set by `getNullValue`), NOT by `len == 1 < lengthOrd` — the latter
|
||||
## also matches an ordinary 1-element collection that happens to be an
|
||||
## `nkBracket` carrying an array type, e.g. a `@[a, b, c]` seq value shrunk to
|
||||
## length 1 by `setLen`/`delete` (its VM node keeps the array-literal type).
|
||||
result = n != nil and n.kind == nkBracket and nfBroadcast in n.flags
|
||||
|
||||
proc expandBroadcastArray*(n: PNode; conf: ConfigRef) =
|
||||
## Materialise a broadcast default array (see `isDefaultBroadcastArray`) into a
|
||||
## full `lengthOrd`-son `nkBracket`, each son a copy of the single default
|
||||
## element. Used by VM ops that index-address, mutate, or measure such a node;
|
||||
## the common read-only paths leave it compact.
|
||||
## the common read-only paths leave it compact. Clears `nfBroadcast` since the
|
||||
## node is now a fully materialised literal.
|
||||
if isDefaultBroadcastArray(n, conf):
|
||||
let total = toInt(lengthOrd(conf, n.typ.skipTypes(abstractInst)))
|
||||
let elem = n[0]
|
||||
for i in 1 ..< total: n.add copyTree(elem)
|
||||
n.flags.excl nfBroadcast
|
||||
|
||||
# -------------- type equality -----------------------------------------------
|
||||
|
||||
|
||||
@@ -2039,6 +2039,10 @@ proc getNullValue(c: PCtx; typ: PType, info: TLineInfo; conf: ConfigRef): PNode
|
||||
if n <= broadcastArrayThreshold:
|
||||
for i in 1..<n:
|
||||
result.add getNullValue(c, elemType(t), info, conf)
|
||||
else:
|
||||
# Broadcast form: mark the single-son node so `isDefaultBroadcastArray`
|
||||
# recognises it unambiguously (see `nfBroadcast`).
|
||||
result.flags.incl nfBroadcast
|
||||
of tyTuple:
|
||||
result = newNodeIT(nkTupleConstr, info, t)
|
||||
for a in t.kids:
|
||||
|
||||
@@ -28,3 +28,17 @@ block:
|
||||
fun[(int, string)]()
|
||||
fun[ref Foo]()
|
||||
fun[seq[int]]()
|
||||
|
||||
block: # shrinking an `@[...]` seq literal in the VM
|
||||
# A `@[a, b, c]` seq value keeps the array-literal type in the VM; shrinking it
|
||||
# to length 1 must not be misread as a broadcast default array (was: the whole
|
||||
# thing collapsed to `len` copies of the first element).
|
||||
proc shrink =
|
||||
var s = @[10, 20, 30]
|
||||
s.setLen(1)
|
||||
doAssert s == @[10]
|
||||
var t = @["foo", "bar"]
|
||||
t.delete(1)
|
||||
doAssert t == @["foo"]
|
||||
static: shrink()
|
||||
shrink()
|
||||
|
||||
Reference in New Issue
Block a user