From 6c2e56b2a2e406a73b65da897e1824b14cc504a7 Mon Sep 17 00:00:00 2001 From: nitely Date: Sun, 30 Nov 2025 18:13:18 -0300 Subject: [PATCH 1/6] Fix #24670; Closure iterator wrong line info traceback under ORC --- compiler/injectdestructors.nim | 4 +- lib/pure/asyncmacro.nim | 9 +- tests/arc/t24670.nim | 161 +++++++++++++++++++++++++++++++++ 3 files changed, 168 insertions(+), 6 deletions(-) create mode 100644 tests/arc/t24670.nim diff --git a/compiler/injectdestructors.nim b/compiler/injectdestructors.nim index 7fca0ab2e7dfc..1622d30f815d3 100644 --- a/compiler/injectdestructors.nim +++ b/compiler/injectdestructors.nim @@ -233,7 +233,9 @@ proc genOp(c: var Con; op: PSym; dest: PNode): PNode = else: addrExp = newNodeIT(nkHiddenAddr, dest.info, makePtrType(c, dest.typ)) addrExp.add(dest) - result = newTree(nkCall, newSymNode(op), addrExp) + result = newTreeI(nkCall, dest.info) + result.add newSymNode(op) + result.add addrExp proc genOp(c: var Con; t: PType; kind: TTypeAttachedOp; dest, ri: PNode): PNode = var op = getAttachedOp(c.graph, t, kind) diff --git a/lib/pure/asyncmacro.nim b/lib/pure/asyncmacro.nim index 30c5e8f539973..66bb516eb09d2 100644 --- a/lib/pure/asyncmacro.nim +++ b/lib/pure/asyncmacro.nim @@ -162,16 +162,15 @@ template await*(f: typed): untyped {.used.} = static: error "await expects Future[T], got " & $typeof(f) -template await*[T](f: Future[T]): auto {.used.} = +template await*[T](f: Future[T]): auto {.used, callsite.} = when not defined(nimHasTemplateRedefinitionPragma): {.pragma: redefine.} template yieldFuture {.redefine.} = yield FutureBase() when compiles(yieldFuture): - var internalTmpFuture: FutureBase = f - yield internalTmpFuture - {.line: instantiationInfo(fullPaths = true).}: - (cast[typeof(f)](internalTmpFuture)).read() + let fut = f + yield FutureBase(fut) + fut.read() else: macro errorAsync(futureError: Future[T]) = error( diff --git a/tests/arc/t24670.nim b/tests/arc/t24670.nim new file mode 100644 index 0000000000000..70a19bd92e324 --- /dev/null +++ b/tests/arc/t24670.nim @@ -0,0 +1,161 @@ +discard """ + output: ''' +2 +1 +2 +1 +2 +1 +''' + matrix: "--mm:arc; --mm:orc; --gc:refc" +""" + +proc read() = + if true: + raise newException(ValueError, "foo") + +block: + iterator count1(): int {.closure.} = + yield 1 + read() + + iterator count0(): int {.closure.} = + try: + yield 2 + for x in count1(): echo x + except Exception: + raise + + proc main = + for x in count0(): echo x + + try: + main() + doAssert false + except ValueError as err: + let expected = """ +t24670.nim(33) t24670 +t24670.nim(30) main +t24670.nim(25) count0 +t24670.nim(20) count1 +t24670.nim(15) read +[[reraised from: +t24670.nim(33) t24670 +t24670.nim(30) main +t24670.nim(22) count0 +]] +""" + doAssert err.getStackTrace() == expected, err.getStackTrace() + +block: + iterator count1(): int {.closure.} = + yield 1 + read() + + iterator count0(): int {.closure.} = + try: + yield 2 + var it = count1 + echo it() + echo it() + except Exception: + raise + + proc main = + var it = count0 + echo it() + echo it() + + try: + main() + doAssert false + except ValueError as err: + let expected = """ +t24670.nim(70) t24670 +t24670.nim(67) main +t24670.nim(60) count0 +t24670.nim(53) count1 +t24670.nim(15) read +[[reraised from: +t24670.nim(70) t24670 +t24670.nim(67) main +t24670.nim(55) count0 +]] +""" + doAssert err.getStackTrace() == expected, err.getStackTrace() + +block: + iterator count1(): int {.closure.} = + yield 1 + read() + + iterator count0(): int {.closure.} = + try: + yield 2 + var foo = count1 + while true: + echo foo() + if finished(foo): break + except Exception: + raise + + proc main = + var foo = count0 + while true: + echo foo() + if finished(foo): break + + try: + main() + doAssert false + except ValueError as err: + let expected = """ +t24670.nim(109) t24670 +t24670.nim(105) main +t24670.nim(97) count0 +t24670.nim(90) count1 +t24670.nim(15) read +[[reraised from: +t24670.nim(109) t24670 +t24670.nim(105) main +t24670.nim(92) count0 +]] +""" + doAssert err.getStackTrace() == expected, err.getStackTrace() + +block: + iterator count1(): int {.closure.} = + yield 1 + read() + + iterator count0(): int {.closure.} = + try: + var it = count1 + yield it() + yield it() + finally: + var it = count1 + yield it() + yield it() + + proc main = + for x in count0(): + discard x + + try: + main() + doAssert false + except ValueError as err: + let expected = """ +t24670.nim(146) t24670 +t24670.nim(143) main +t24670.nim(139) count0 +t24670.nim(129) count1 +t24670.nim(15) read +[[reraised from: +t24670.nim(146) t24670 +t24670.nim(143) main +t24670.nim(131) count0 +]] +""" + doAssert err.getStackTrace() == expected, err.getStackTrace() From f61e83cbab6c5533c53f76aa6deb3bf983dcea78 Mon Sep 17 00:00:00 2001 From: nitely Date: Thu, 4 Dec 2025 01:26:54 -0300 Subject: [PATCH 2/6] wip --- compiler/injectdestructors.nim | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/compiler/injectdestructors.nim b/compiler/injectdestructors.nim index 1622d30f815d3..35a21ea109ad0 100644 --- a/compiler/injectdestructors.nim +++ b/compiler/injectdestructors.nim @@ -233,9 +233,7 @@ proc genOp(c: var Con; op: PSym; dest: PNode): PNode = else: addrExp = newNodeIT(nkHiddenAddr, dest.info, makePtrType(c, dest.typ)) addrExp.add(dest) - result = newTreeI(nkCall, dest.info) - result.add newSymNode(op) - result.add addrExp + result = newTreeI(nkCall, newSymNode(op, dest.info), addrExp) proc genOp(c: var Con; t: PType; kind: TTypeAttachedOp; dest, ri: PNode): PNode = var op = getAttachedOp(c.graph, t, kind) From 4b492246fa917b05c3f5b7f3625544c6e58ddacc Mon Sep 17 00:00:00 2001 From: nitely Date: Thu, 4 Dec 2025 01:27:53 -0300 Subject: [PATCH 3/6] wip --- compiler/injectdestructors.nim | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/compiler/injectdestructors.nim b/compiler/injectdestructors.nim index 35a21ea109ad0..e73f3c578865a 100644 --- a/compiler/injectdestructors.nim +++ b/compiler/injectdestructors.nim @@ -233,7 +233,7 @@ proc genOp(c: var Con; op: PSym; dest: PNode): PNode = else: addrExp = newNodeIT(nkHiddenAddr, dest.info, makePtrType(c, dest.typ)) addrExp.add(dest) - result = newTreeI(nkCall, newSymNode(op, dest.info), addrExp) + result = newTree(nkCall, newSymNode(op, dest.info), addrExp) proc genOp(c: var Con; t: PType; kind: TTypeAttachedOp; dest, ri: PNode): PNode = var op = getAttachedOp(c.graph, t, kind) From 572605aec6b6f879c9ffae8d4e859045c8559504 Mon Sep 17 00:00:00 2001 From: nitely Date: Thu, 4 Dec 2025 01:58:24 -0300 Subject: [PATCH 4/6] use line --- lib/pure/asyncmacro.nim | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/lib/pure/asyncmacro.nim b/lib/pure/asyncmacro.nim index 66bb516eb09d2..1e5f480394697 100644 --- a/lib/pure/asyncmacro.nim +++ b/lib/pure/asyncmacro.nim @@ -162,7 +162,7 @@ template await*(f: typed): untyped {.used.} = static: error "await expects Future[T], got " & $typeof(f) -template await*[T](f: Future[T]): auto {.used, callsite.} = +template await*[T](f: Future[T]): auto {.used.} = when not defined(nimHasTemplateRedefinitionPragma): {.pragma: redefine.} template yieldFuture {.redefine.} = yield FutureBase() @@ -170,7 +170,8 @@ template await*[T](f: Future[T]): auto {.used, callsite.} = when compiles(yieldFuture): let fut = f yield FutureBase(fut) - fut.read() + {.line: instantiationInfo(fullPaths = true).}: + fut.read() else: macro errorAsync(futureError: Future[T]) = error( From 4ad6eb1ea3ba0a352ff1cc74c727097bafc0b51a Mon Sep 17 00:00:00 2001 From: nitely Date: Thu, 4 Dec 2025 03:48:16 -0300 Subject: [PATCH 5/6] wip --- lib/pure/asyncmacro.nim | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/lib/pure/asyncmacro.nim b/lib/pure/asyncmacro.nim index 1e5f480394697..52725564db23a 100644 --- a/lib/pure/asyncmacro.nim +++ b/lib/pure/asyncmacro.nim @@ -168,10 +168,12 @@ template await*[T](f: Future[T]): auto {.used.} = template yieldFuture {.redefine.} = yield FutureBase() when compiles(yieldFuture): - let fut = f - yield FutureBase(fut) {.line: instantiationInfo(fullPaths = true).}: - fut.read() + let internalTmpFuture: FutureBase = f + yield internalTmpFuture + {.line: instantiationInfo(fullPaths = true).}: + let ff = cast[typeof(f)](internalTmpFuture) + ff.read() else: macro errorAsync(futureError: Future[T]) = error( From 34e9bfbdc5d4f65549776eaf2b2a99c5cb5c5fc7 Mon Sep 17 00:00:00 2001 From: nitely Date: Thu, 4 Dec 2025 10:34:27 -0300 Subject: [PATCH 6/6] wip --- lib/pure/asyncfutures.nim | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/lib/pure/asyncfutures.nim b/lib/pure/asyncfutures.nim index 41f1f70a37521..da93a4eebf1a9 100644 --- a/lib/pure/asyncfutures.nim +++ b/lib/pure/asyncfutures.nim @@ -302,8 +302,7 @@ proc isInternal(entry: StackTraceEntry): bool = # --excessiveStackTrace:off const internals = [ "asyncdispatch.nim", - "asyncfutures.nim", - "threadimpl.nim", # XXX ? + "asyncfutures.nim" ] let (filename, procname) = getFilenameProcname(entry) for line in internals: