summary refs log tree commit diff stats
path: root/compiler
diff options
context:
space:
mode:
authorrec <44084068+recloser@users.noreply.github.com>2018-12-20 08:24:57 +0100
committerAndreas Rumpf <rumpf_a@web.de>2018-12-20 08:24:57 +0100
commitca18dc2505d3e3429860bef89d7e6a353cf935de (patch)
tree80f79e8838619ae7b527161f82bdff3c118fb727 /compiler
parentcd65e5328dc82ca74a2905641a12e2c84a82d1de (diff)
downloadNim-ca18dc2505d3e3429860bef89d7e6a353cf935de.tar.gz
Make copies for params which are captured in closures. Fixes #7048 (#10050)
* Copy params which are captured in closures. Fixes #7048
* Forgot to emit a newline; minor adjustments to the test
Diffstat (limited to 'compiler')
-rw-r--r--compiler/jsgen.nim20
1 files changed, 19 insertions, 1 deletions
diff --git a/compiler/jsgen.nim b/compiler/jsgen.nim
index cd51aaddd..daaa145e1 100644
--- a/compiler/jsgen.nim
+++ b/compiler/jsgen.nim
@@ -94,6 +94,7 @@ type
     options: TOptions
     module: BModule
     g: PGlobals
+    generatedParamCopies: IntSet
     beforeRetNeeded: bool
     unique: int    # for temp identifier generation
     blocks: seq[TBlock]
@@ -924,7 +925,7 @@ const
 
 proc needsNoCopy(p: PProc; y: PNode): bool =
   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
             {tyRef, tyPtr, tyLent, tyVar, tyCString, tyProc} + IntegralTypes))
 
@@ -1232,12 +1233,29 @@ proc genProcForSymIfNeeded(p: PProc, s: PSym) =
     if owner != nil: add(owner.locals, newp)
     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) =
   var s = n.sym
   case s.kind
   of skVar, skLet, skParam, skTemp, skResult, skForVar:
     if s.loc.r == nil:
       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)
     if k == etyBaseIndex:
       r.typ = etyBaseIndex