* Copy params which are captured in closures. Fixes #7048 * Forgot to emit a newline; minor adjustments to the test
This commit is contained in:
parent
cd65e5328d
commit
ca18dc2505
2 changed files with 63 additions and 1 deletions
|
|
@ -94,6 +94,7 @@ type
|
||||||
options: TOptions
|
options: TOptions
|
||||||
module: BModule
|
module: BModule
|
||||||
g: PGlobals
|
g: PGlobals
|
||||||
|
generatedParamCopies: IntSet
|
||||||
beforeRetNeeded: bool
|
beforeRetNeeded: bool
|
||||||
unique: int # for temp identifier generation
|
unique: int # for temp identifier generation
|
||||||
blocks: seq[TBlock]
|
blocks: seq[TBlock]
|
||||||
|
|
@ -924,7 +925,7 @@ const
|
||||||
|
|
||||||
proc needsNoCopy(p: PProc; y: PNode): bool =
|
proc needsNoCopy(p: PProc; y: PNode): bool =
|
||||||
return y.kind in nodeKindsNeedNoCopy or
|
return y.kind in nodeKindsNeedNoCopy or
|
||||||
(mapType(y.typ) != etyBaseIndex and
|
((mapType(y.typ) != etyBaseIndex or y.sym.kind == skParam) and
|
||||||
(skipTypes(y.typ, abstractInst).kind in
|
(skipTypes(y.typ, abstractInst).kind in
|
||||||
{tyRef, tyPtr, tyLent, tyVar, tyCString, tyProc} + IntegralTypes))
|
{tyRef, tyPtr, tyLent, tyVar, tyCString, tyProc} + IntegralTypes))
|
||||||
|
|
||||||
|
|
@ -1232,12 +1233,29 @@ proc genProcForSymIfNeeded(p: PProc, s: PSym) =
|
||||||
if owner != nil: add(owner.locals, newp)
|
if owner != nil: add(owner.locals, newp)
|
||||||
else: attachProc(p, newp, s)
|
else: attachProc(p, newp, s)
|
||||||
|
|
||||||
|
proc genCopyForParamIfNeeded(p: PProc, n: PNode) =
|
||||||
|
let s = n.sym
|
||||||
|
if p.prc == s.owner or needsNoCopy(p, n):
|
||||||
|
return
|
||||||
|
var owner = p.up
|
||||||
|
while true:
|
||||||
|
if owner == nil:
|
||||||
|
internalError(p.config, n.info, "couldn't find the owner proc of the closed over param: " & s.name.s)
|
||||||
|
if owner.prc == s.owner:
|
||||||
|
if not owner.generatedParamCopies.containsOrIncl(s.id):
|
||||||
|
let copy = "$1 = nimCopy(null, $1, $2);$n" % [s.loc.r, genTypeInfo(p, s.typ)]
|
||||||
|
add(owner.locals, owner.indentLine(copy))
|
||||||
|
return
|
||||||
|
owner = owner.up
|
||||||
|
|
||||||
proc genSym(p: PProc, n: PNode, r: var TCompRes) =
|
proc genSym(p: PProc, n: PNode, r: var TCompRes) =
|
||||||
var s = n.sym
|
var s = n.sym
|
||||||
case s.kind
|
case s.kind
|
||||||
of skVar, skLet, skParam, skTemp, skResult, skForVar:
|
of skVar, skLet, skParam, skTemp, skResult, skForVar:
|
||||||
if s.loc.r == nil:
|
if s.loc.r == nil:
|
||||||
internalError(p.config, n.info, "symbol has no generated name: " & s.name.s)
|
internalError(p.config, n.info, "symbol has no generated name: " & s.name.s)
|
||||||
|
if s.kind == skParam:
|
||||||
|
genCopyForParamIfNeeded(p, n)
|
||||||
let k = mapType(p, s.typ)
|
let k = mapType(p, s.typ)
|
||||||
if k == etyBaseIndex:
|
if k == etyBaseIndex:
|
||||||
r.typ = etyBaseIndex
|
r.typ = etyBaseIndex
|
||||||
|
|
|
||||||
|
|
@ -49,3 +49,47 @@ for i in 1 .. 10:
|
||||||
let results = runCallbacks()
|
let results = runCallbacks()
|
||||||
|
|
||||||
doAssert(expected == $results)
|
doAssert(expected == $results)
|
||||||
|
|
||||||
|
block issue7048:
|
||||||
|
block:
|
||||||
|
proc foo(x: seq[int]): auto =
|
||||||
|
proc bar: int = x[1]
|
||||||
|
bar
|
||||||
|
|
||||||
|
var stuff = @[1, 2]
|
||||||
|
let f = foo(stuff)
|
||||||
|
stuff[1] = 321
|
||||||
|
doAssert f() == 2
|
||||||
|
|
||||||
|
block:
|
||||||
|
proc foo(x: tuple[things: string]; y: array[3, int]): auto =
|
||||||
|
proc very: auto =
|
||||||
|
proc deeply: auto =
|
||||||
|
proc nested: (char, int) = (x.things[0], y[1])
|
||||||
|
nested
|
||||||
|
deeply
|
||||||
|
very()
|
||||||
|
|
||||||
|
var
|
||||||
|
stuff = (things: "NIM")
|
||||||
|
stuff2 = [32, 64, 96]
|
||||||
|
let f = foo(stuff, stuff2)
|
||||||
|
stuff.things = "VIM"
|
||||||
|
stuff2[1] *= 10
|
||||||
|
doAssert f()() == ('N', 64)
|
||||||
|
doAssert (stuff.things[0], stuff2[1]) == ('V', 640)
|
||||||
|
|
||||||
|
block:
|
||||||
|
proc foo(x: ptr string): auto =
|
||||||
|
proc bar(): int = len(x[])
|
||||||
|
bar
|
||||||
|
|
||||||
|
var
|
||||||
|
s1 = "xyz"
|
||||||
|
s2 = "stuff"
|
||||||
|
p = addr s1
|
||||||
|
|
||||||
|
let f = foo(p)
|
||||||
|
p = addr s2
|
||||||
|
doAssert len(p[]) == 5
|
||||||
|
doAssert f() == 3
|
||||||
Loading…
Add table
Add a link
Reference in a new issue