fixes #21306; fixes #20485; don't transform yields in the var section when introducing new local vars [backport: 1.6] (#21489)
* fixes #21306; don't transform yields in the var section when introducing new local vars * adds `inVarSection` so the var section in the var section is freshed * use `isIntroducingNewLocalVars` to avoid yield transformations in var sections * fixes comments
This commit is contained in:
parent
0319824322
commit
f2dad94902
2 changed files with 118 additions and 1 deletions
|
|
@ -50,6 +50,7 @@ type
|
||||||
module: PSym
|
module: PSym
|
||||||
transCon: PTransCon # top of a TransCon stack
|
transCon: PTransCon # top of a TransCon stack
|
||||||
inlining: int # > 0 if we are in inlining context (copy vars)
|
inlining: int # > 0 if we are in inlining context (copy vars)
|
||||||
|
isIntroducingNewLocalVars: bool # true if we are in `introducingNewLocalVars` (don't transform yields)
|
||||||
contSyms, breakSyms: seq[PSym] # to transform 'continue' and 'break'
|
contSyms, breakSyms: seq[PSym] # to transform 'continue' and 'break'
|
||||||
deferDetected, tooEarly: bool
|
deferDetected, tooEarly: bool
|
||||||
graph: ModuleGraph
|
graph: ModuleGraph
|
||||||
|
|
@ -450,7 +451,9 @@ proc transformYield(c: PTransf, n: PNode): PNode =
|
||||||
result.add(c.transCon.forLoopBody)
|
result.add(c.transCon.forLoopBody)
|
||||||
else:
|
else:
|
||||||
# we need to introduce new local variables:
|
# we need to introduce new local variables:
|
||||||
|
c.isIntroducingNewLocalVars = true # don't transform yields when introducing new local vars
|
||||||
result.add(introduceNewLocalVars(c, c.transCon.forLoopBody))
|
result.add(introduceNewLocalVars(c, c.transCon.forLoopBody))
|
||||||
|
c.isIntroducingNewLocalVars = false
|
||||||
|
|
||||||
for idx in 0 ..< result.len:
|
for idx in 0 ..< result.len:
|
||||||
var changeNode = result[idx]
|
var changeNode = result[idx]
|
||||||
|
|
@ -1036,7 +1039,7 @@ proc transform(c: PTransf, n: PNode): PNode =
|
||||||
else:
|
else:
|
||||||
result = transformSons(c, n)
|
result = transformSons(c, n)
|
||||||
of nkYieldStmt:
|
of nkYieldStmt:
|
||||||
if c.inlining > 0:
|
if c.inlining > 0 and not c.isIntroducingNewLocalVars:
|
||||||
result = transformYield(c, n)
|
result = transformYield(c, n)
|
||||||
else:
|
else:
|
||||||
result = transformSons(c, n)
|
result = transformSons(c, n)
|
||||||
|
|
|
||||||
114
tests/iter/t21306.nim
Normal file
114
tests/iter/t21306.nim
Normal file
|
|
@ -0,0 +1,114 @@
|
||||||
|
# bug #21306
|
||||||
|
type
|
||||||
|
FutureState {.pure.} = enum
|
||||||
|
Pending, Finished, Cancelled, Failed
|
||||||
|
|
||||||
|
FutureBase = ref object of RootObj
|
||||||
|
state: FutureState
|
||||||
|
error: ref CatchableError
|
||||||
|
id: uint
|
||||||
|
|
||||||
|
Future[T] = ref object of FutureBase
|
||||||
|
closure: iterator(f: Future[T]): FutureBase {.raises: [Defect, CatchableError, Exception], gcsafe.}
|
||||||
|
value: T
|
||||||
|
|
||||||
|
template setupFutureBase() =
|
||||||
|
new(result)
|
||||||
|
result.state = FutureState.Pending
|
||||||
|
|
||||||
|
proc newFutureImpl[T](): Future[T] =
|
||||||
|
setupFutureBase()
|
||||||
|
|
||||||
|
template newFuture[T](fromProc: static[string] = ""): Future[T] =
|
||||||
|
newFutureImpl[T]()
|
||||||
|
|
||||||
|
proc internalRead[T](fut: Future[T]): T =
|
||||||
|
when T isnot void:
|
||||||
|
return fut.value
|
||||||
|
|
||||||
|
template await[T](f: Future[T]): untyped =
|
||||||
|
when declared(chronosInternalRetFuture):
|
||||||
|
when not declaredInScope(chronosInternalTmpFuture):
|
||||||
|
var chronosInternalTmpFuture {.inject.}: FutureBase = f
|
||||||
|
else:
|
||||||
|
chronosInternalTmpFuture = f
|
||||||
|
|
||||||
|
yield chronosInternalTmpFuture
|
||||||
|
|
||||||
|
when T isnot void:
|
||||||
|
cast[type(f)](chronosInternalTmpFuture).internalRead()
|
||||||
|
|
||||||
|
type
|
||||||
|
VerifierError {.pure.} = enum
|
||||||
|
Invalid
|
||||||
|
MissingParent
|
||||||
|
UnviableFork
|
||||||
|
Duplicate
|
||||||
|
ProcessingCallback = proc() {.gcsafe, raises: [Defect].}
|
||||||
|
BlockVerifier =
|
||||||
|
proc(signedBlock: int):
|
||||||
|
Future[VerifierError] {.gcsafe, raises: [Defect].}
|
||||||
|
|
||||||
|
SyncQueueKind {.pure.} = enum
|
||||||
|
Forward, Backward
|
||||||
|
|
||||||
|
SyncRequest[T] = object
|
||||||
|
kind: SyncQueueKind
|
||||||
|
index: uint64
|
||||||
|
slot: uint64
|
||||||
|
count: uint64
|
||||||
|
item: T
|
||||||
|
|
||||||
|
SyncResult[T] = object
|
||||||
|
request: SyncRequest[T]
|
||||||
|
data: seq[ref int]
|
||||||
|
|
||||||
|
SyncQueue[T] = ref object
|
||||||
|
kind: SyncQueueKind
|
||||||
|
readyQueue: seq[SyncResult[T]]
|
||||||
|
blockVerifier: BlockVerifier
|
||||||
|
|
||||||
|
iterator blocks[T](sq: SyncQueue[T],
|
||||||
|
sr: SyncResult[T]): ref int =
|
||||||
|
case sq.kind
|
||||||
|
of SyncQueueKind.Forward:
|
||||||
|
for i in countup(0, len(sr.data) - 1):
|
||||||
|
yield sr.data[i]
|
||||||
|
of SyncQueueKind.Backward:
|
||||||
|
for i in countdown(len(sr.data) - 1, 0):
|
||||||
|
yield sr.data[i]
|
||||||
|
|
||||||
|
proc push[T](sq: SyncQueue[T]; sr: SyncRequest[T]; data: seq[ref int];
|
||||||
|
processingCb: ProcessingCallback = nil): Future[void] {.
|
||||||
|
stackTrace: off, gcsafe.} =
|
||||||
|
iterator push_436208182(chronosInternalRetFuture: Future[void]): FutureBase {.
|
||||||
|
closure, gcsafe, raises: [Defect, CatchableError, Exception].} =
|
||||||
|
block:
|
||||||
|
template result(): auto {.used.} =
|
||||||
|
{.fatal: "You should not reference the `result` variable inside" &
|
||||||
|
" a void async proc".}
|
||||||
|
|
||||||
|
let item = default(SyncResult[T])
|
||||||
|
for blk in sq.blocks(item):
|
||||||
|
let res = await sq.blockVerifier(blk[])
|
||||||
|
|
||||||
|
var resultFuture = newFuture[void]("push")
|
||||||
|
resultFuture.closure = push_436208182
|
||||||
|
return resultFuture
|
||||||
|
|
||||||
|
type
|
||||||
|
SomeTPeer = ref object
|
||||||
|
score: int
|
||||||
|
|
||||||
|
proc getSlice(): seq[ref int] =
|
||||||
|
discard
|
||||||
|
|
||||||
|
template smokeTest(kkind: SyncQueueKind, start, finish: uint64,
|
||||||
|
chunkSize: uint64) =
|
||||||
|
var queue: SyncQueue[SomeTPeer]
|
||||||
|
var request: SyncRequest[SomeTPeer]
|
||||||
|
discard queue.push(request, getSlice())
|
||||||
|
|
||||||
|
for k in {SyncQueueKind.Forward}:
|
||||||
|
for item in [(uint64(1181), uint64(1399), 41'u64)]:
|
||||||
|
smokeTest(k, item[0], item[1], item[2])
|
||||||
Loading…
Add table
Add a link
Reference in a new issue