summary refs log tree commit diff stats
diff options
context:
space:
mode:
-rw-r--r--compiler/injectdestructors.nim11
-rw-r--r--compiler/sempass2.nim10
-rw-r--r--compiler/types.nim11
-rw-r--r--tests/destructor/tnewruntime_misc.nim6
4 files changed, 26 insertions, 12 deletions
diff --git a/compiler/injectdestructors.nim b/compiler/injectdestructors.nim
index 6f1da37fb..4f96d236f 100644
--- a/compiler/injectdestructors.nim
+++ b/compiler/injectdestructors.nim
@@ -437,17 +437,6 @@ proc sinkParamIsLastReadCheck(c: var Con, s: PNode) =
      localError(c.graph.config, c.otherRead.info, "sink parameter `" & $s.sym.name.s &
          "` is already consumed at " & toFileLineCol(c. graph.config, s.info))
 
-proc isSinkTypeForParam(t: PType): bool =
-  # a parameter like 'seq[owned T]' must not be used only once, but its
-  # elements must, so we detect this case here:
-  result = t.skipTypes({tyGenericInst, tyAlias}).kind in {tySink, tyOwned}
-  when false:
-    if isSinkType(t):
-      if t.skipTypes({tyGenericInst, tyAlias}).kind in {tyArray, tyVarargs, tyOpenArray, tySequence}:
-        result = false
-      else:
-        result = true
-
 proc passCopyToSink(n: PNode; c: var Con): PNode =
   result = newNodeIT(nkStmtListExpr, n.info, n.typ)
   let tmp = getTemp(c, n.typ, n.info)
diff --git a/compiler/sempass2.nim b/compiler/sempass2.nim
index 8252a7857..c31f86f98 100644
--- a/compiler/sempass2.nim
+++ b/compiler/sempass2.nim
@@ -34,7 +34,7 @@ In the construct let/var x = expr() x's type is marked.
 
 In x = y the type of x is marked.
 
-For every sink parameter of type T T is marked. TODO!
+For every sink parameter of type T T is marked.
 
 For every call f() the return type of f() is marked.
 
@@ -977,6 +977,14 @@ proc trackProc*(c: PContext; s: PSym, body: PNode) =
   var t: TEffects
   initEffects(g, effects, s, t, c)
   track(t, body)
+
+  if s.kind != skMacro:
+    let params = s.typ.n
+    for i in 1 ..< params.len:
+      let param = params[i].sym
+      if isSinkTypeForParam(param.typ):
+        createTypeBoundOps(t.graph, t.c, param.typ, param.info)
+
   if not isEmptyType(s.typ.sons[0]) and
       ({tfNeedsInit, tfNotNil} * s.typ.sons[0].flags != {} or
       s.typ.sons[0].skipTypes(abstractInst).kind == tyVar) and
diff --git a/compiler/types.nim b/compiler/types.nim
index fcf21fc54..11006de30 100644
--- a/compiler/types.nim
+++ b/compiler/types.nim
@@ -1600,3 +1600,14 @@ proc isException*(t: PType): bool =
     if t.sons[0] == nil: break
     t = skipTypes(t.sons[0], abstractPtrs)
   return false
+
+proc isSinkTypeForParam*(t: PType): bool =
+  # a parameter like 'seq[owned T]' must not be used only once, but its
+  # elements must, so we detect this case here:
+  result = t.skipTypes({tyGenericInst, tyAlias}).kind in {tySink, tyOwned}
+  when false:
+    if isSinkType(t):
+      if t.skipTypes({tyGenericInst, tyAlias}).kind in {tyArray, tyVarargs, tyOpenArray, tySequence}:
+        result = false
+      else:
+        result = true
diff --git a/tests/destructor/tnewruntime_misc.nim b/tests/destructor/tnewruntime_misc.nim
index 2bdae5c8b..1fb5b0151 100644
--- a/tests/destructor/tnewruntime_misc.nim
+++ b/tests/destructor/tnewruntime_misc.nim
@@ -52,5 +52,11 @@ type
       x*: int
 var t: MyType
 
+# bug #11254
+proc test(p: owned proc()) =
+  let x = (proc())p
+
+test(proc() = discard)
+
 let (a, d) = allocCounters()
 discard cprintf("%ld  new: %ld\n", a - unpairedEnvAllocs() - d, allocs)