fixes #26000; Cannot add members to enum-indexed array of seqs at compile time

This commit is contained in:
ringabout
2026-07-16 18:31:45 +08:00
parent 2463ef970d
commit 98f12776df
2 changed files with 125 additions and 4 deletions

View File

@@ -851,14 +851,26 @@ proc genBinaryStmt(c: PCtx; n: PNode; opc: TOpcode) =
c.freeTemp(tmp)
c.freeTemp(dest)
proc genMutatingValue(c: PCtx; n: PNode): TRegister =
## Loads the value of an in-place mutation target while keeping it attached to
## its original storage. Compound lvalues must be resolved through their
## address: a normal value load can return a detached copy (for example, when
## indexing a broadcast default array).
if needsAsgnPatch(n):
let address = c.genx(n, {gfNodeAddr})
result = c.getTemp(n.typ)
c.gABC(n, opcLdDeref, result, address)
c.freeTemp(address)
else:
result = c.genx(n)
proc genBinaryStmtVar(c: PCtx; n: PNode; opc: TOpcode) =
var x = n[1]
if x.kind in {nkAddr, nkHiddenAddr}: x = x[0]
let
dest = c.genx(x)
dest = c.genMutatingValue(x)
tmp = c.genx(n[2])
c.gABC(n, opc, dest, tmp, 0)
#c.genAsgnPatch(n[1], dest)
c.freeTemp(tmp)
c.freeTemp(dest)
@@ -1160,12 +1172,20 @@ proc genMagic(c: PCtx; n: PNode; dest: var TDest; flags: TGenFlags = {}, m: TMag
c.freeTemp(right)
c.freeTemp(d)
of mIncl, mExcl:
of mIncl:
unused(c, n, dest)
var d = c.genMutatingValue(n[1])
var tmp = c.genx(n[2])
c.genSetType(n[1], d)
c.gABC(n, opcIncl, d, tmp)
c.freeTemp(d)
c.freeTemp(tmp)
of mExcl:
unused(c, n, dest)
var d = c.genx(n[1])
var tmp = c.genx(n[2])
c.genSetType(n[1], d)
c.gABC(n, if m == mIncl: opcIncl else: opcExcl, d, tmp)
c.gABC(n, opcExcl, d, tmp)
c.freeTemp(d)
c.freeTemp(tmp)
of mCard: genCard(c, n, dest)

View File

@@ -0,0 +1,101 @@
type
Container = object
numbers: seq[int]
text: string
chars: set[char]
Variant = object
case enabled: bool
of false:
numbers: seq[int]
else:
discard
Index = enum
index0, index1, index2, index3, index4, index5, index6, index7,
index8, index9, index10, index11, index12, index13, index14, index15,
index16, index17, index18, index19, index20, index21, index22, index23,
index24, index25, index26, index27, index28, index29, index30, index31,
index32
Outer = object
values: array[33, seq[int]]
proc directSeq(): array[33, seq[int]] =
result[32].add 1
proc directStringChar(): array[33, string] =
result[32].add 'a'
proc directStringString(): array[33, string] =
result[32].add "ab"
proc directSet(): array[33, set[char]] =
result[32].incl 'a'
proc fieldSeq(): array[33, Container] =
result[32].numbers.add 1
proc fieldStringChar(): array[33, Container] =
result[32].text.add 'a'
proc fieldStringString(): array[33, Container] =
result[32].text.add "ab"
proc fieldSet(): array[33, Container] =
result[32].chars.incl 'a'
proc nestedSeq(): array[33, array[33, seq[int]]] =
result[32][32].add 1
proc checkedFieldSeq(): array[33, Variant] =
result[32].numbers.add 1
proc enumIndexSeq(): array[Index, seq[int]] =
result[index32].add 1
proc rangeIndexSeq(): array[10..42, seq[int]] =
result[42].add 1
proc firstIndexSeq(): array[33, seq[int]] =
result[0].add 1
proc middleIndexSeq(): array[33, seq[int]] =
result[16].add 1
proc objectArraySeq(): Outer =
result.values[32].add 1
proc singleEvaluation(): tuple[values: array[33, seq[int]], evaluations: int] =
var evaluations = 0
proc index(): int =
inc evaluations
32
result.values[index()].add 1
result.evaluations = evaluations
proc test =
let direct = directSeq()
doAssert direct[0].len == 0
doAssert direct[31].len == 0
doAssert direct[32] == @[1]
doAssert directStringChar()[32] == "a"
doAssert directStringString()[32] == "ab"
doAssert 'a' in directSet()[32]
doAssert fieldSeq()[32].numbers == @[1]
doAssert fieldStringChar()[32].text == "a"
doAssert fieldStringString()[32].text == "ab"
doAssert 'a' in fieldSet()[32].chars
doAssert nestedSeq()[32][32] == @[1]
doAssert checkedFieldSeq()[32].numbers == @[1]
doAssert enumIndexSeq()[index32] == @[1]
doAssert rangeIndexSeq()[42] == @[1]
doAssert firstIndexSeq()[0] == @[1]
doAssert middleIndexSeq()[16] == @[1]
doAssert objectArraySeq().values[32] == @[1]
let evaluated = singleEvaluation()
doAssert evaluated.values[32] == @[1]
doAssert evaluated.evaluations == 1
static: test()
test()