summary refs log tree commit diff stats
diff options
context:
space:
mode:
authorringabout <43030857+ringabout@users.noreply.github.com>2024-05-27 22:58:43 +0800
committerGitHub <noreply@github.com>2024-05-27 16:58:43 +0200
commitcc5ce72376872c7080543593ee5e7234b16a62bd (patch)
tree95f7365b324ce01f37ef2b38da39e90237424211
parentc615828ccb2b309ac03aab93d94b40af6b4079ff (diff)
downloadNim-cc5ce72376872c7080543593ee5e7234b16a62bd.tar.gz
fixes #23635; tasks.toTask Doesn't Expect a Dot Expression (#23641)
fixes #23635

---------

Co-authored-by: Andreas Rumpf <rumpf_a@web.de>
-rw-r--r--lib/std/tasks.nim24
-rw-r--r--tests/stdlib/ttasks.nim36
2 files changed, 56 insertions, 4 deletions
diff --git a/lib/std/tasks.nim b/lib/std/tasks.nim
index 1892acd72..7e59747f5 100644
--- a/lib/std/tasks.nim
+++ b/lib/std/tasks.nim
@@ -110,6 +110,19 @@ template addAllNode(assignParam: NimNode, procParam: NimNode) =
   tempAssignList.add newLetStmt(tempNode, newDotExpr(objTemp, formalParams[i][0]))
   scratchRecList.add newIdentDefs(newIdentNode(formalParams[i][0].strVal), assignParam)
 
+proc analyseRootSym(s: NimNode): NimNode =
+  result = s
+  while true:
+    case result.kind
+    of nnkBracketExpr, nnkDerefExpr, nnkHiddenDeref,
+        nnkAddr, nnkHiddenAddr,
+        nnkObjDownConv, nnkObjUpConv:
+      result = result[0]
+    of nnkDotExpr, nnkCheckedFieldExpr, nnkHiddenStdConv, nnkHiddenSubConv:
+      result = result[1]
+    else:
+      break
+
 macro toTask*(e: typed{nkCall | nkInfix | nkPrefix | nkPostfix | nkCommand | nkCallStrLit}): Task =
   ## Converts the call and its arguments to `Task`.
   runnableExamples:
@@ -121,11 +134,14 @@ macro toTask*(e: typed{nkCall | nkInfix | nkPrefix | nkPostfix | nkCommand | nkC
   let retType = getTypeInst(e)
   let returnsVoid = retType.typeKind == ntyVoid
 
+  let rootSym = analyseRootSym(e[0])
+  expectKind rootSym, nnkSym
+
   when compileOption("threads"):
-    if not isGcSafe(e[0]):
+    if not isGcSafe(rootSym):
       error("'toTask' takes a GC safe call expression", e)
 
-  if hasClosure(e[0]):
+  if hasClosure(rootSym):
     error("closure call is not allowed", e)
 
   if e.len > 1:
@@ -209,7 +225,7 @@ macro toTask*(e: typed{nkCall | nkInfix | nkPrefix | nkPostfix | nkCommand | nkC
     let funcCall = newCall(e[0], callNode)
     functionStmtList.add tempAssignList
 
-    let funcName = genSym(nskProc, e[0].strVal)
+    let funcName = genSym(nskProc, rootSym.strVal)
     let destroyName = genSym(nskProc, "destroyScratch")
     let objTemp2 = genSym(ident = "obj")
     let tempNode = quote("@") do:
@@ -241,7 +257,7 @@ macro toTask*(e: typed{nkCall | nkInfix | nkPrefix | nkPostfix | nkCommand | nkC
       Task(callback: `funcName`, args: `scratchIdent`, destroy: `destroyName`)
   else:
     let funcCall = newCall(e[0])
-    let funcName = genSym(nskProc, e[0].strVal)
+    let funcName = genSym(nskProc, rootSym.strVal)
 
     if returnsVoid:
       result = quote do:
diff --git a/tests/stdlib/ttasks.nim b/tests/stdlib/ttasks.nim
index 347c3347a..ba65590d9 100644
--- a/tests/stdlib/ttasks.nim
+++ b/tests/stdlib/ttasks.nim
@@ -523,3 +523,39 @@ block:
       doAssert resB == "abcdef"
 
     testReturnValues()
+
+
+block: # bug #23635
+  block:
+    type
+      Store = object
+        run: proc (a: int) {.nimcall, gcsafe.}
+
+    block:
+      var count = 0
+      proc hello(a: int) =
+        inc count, a
+
+      var store = Store()
+      store.run = hello
+
+      let b = toTask store.run(13)
+      b.invoke()
+      doAssert count == 13
+
+  block:
+    type
+      Store = object
+        run: proc () {.nimcall, gcsafe.}
+
+    block:
+      var count = 0
+      proc hello() =
+        inc count, 1
+
+      var store = Store()
+      store.run = hello
+
+      let b = toTask store.run()
+      b.invoke()
+      doAssert count == 1