Merge remote-tracking branch 'origin/devel' into pr_so_so

This commit is contained in:
ringabout
2026-04-06 16:17:43 +08:00
4 changed files with 50 additions and 2 deletions

View File

@@ -408,6 +408,12 @@ Consider:
proc isTypeOf(n: PNode): bool =
n.kind == nkSym and n.sym.magic in {mTypeOf, mType}
proc isEnvTypeForRoutine(envTyp: PType; routine: PSym): bool =
## True if `envTyp` is (maybe wrapped) env object type owned by `routine`, as
## created by `getEnvTypeForOwner` / `createEnvObj`.
let obj = envTyp.skipTypes({tyOwned, tyRef, tyPtr})
result = obj.kind == tyObject and obj.owner.id == routine.id
proc addClosureParam(c: var DetectionPass; fn: PSym; info: TLineInfo) =
var cp = getEnvParam(fn)
let owner = if fn.kind == skIterator: fn else: fn.skipGenericOwner
@@ -418,7 +424,13 @@ proc addClosureParam(c: var DetectionPass; fn: PSym; info: TLineInfo) =
cp.typ = t
addHiddenParam(fn, cp)
elif cp.typ != t and fn.kind != skIterator:
localError(c.graph.config, fn.info, "internal error: inconsistent environment type")
# Nested `liftLambdas` uses a fresh `DetectionPass`, so `getEnvTypeForOwner`
# can allocate another PType for the same logical env; the hidden param from
# the inner pass is authoritative (bug #21242).
if isEnvTypeForRoutine(cp.typ, owner) and isEnvTypeForRoutine(t, owner):
c.ownerToType[owner.id] = cp.typ
else:
localError(c.graph.config, fn.info, "internal error: inconsistent environment type")
#echo "adding closure to ", fn.name.s
proc iterEnvHasUpField(g: ModuleGraph, iter: PSym): bool =

View File

@@ -1101,7 +1101,7 @@ proc semForVars(c: PContext, n: PNode; flags: TExprFlags): PNode =
iterBase.skipModifier
else:
skipTypes(iterBase, {tyAlias, tySink, tyOwned})
var iter = iterType
var iter = skipTypes(iterType, {tyGenericInst})
var iterAfterVarLent = iter.skipTypes({tyGenericInst, tyAlias, tyLent, tyVar})
# n.len == 3 means that there is one for loop variable
# and thus no tuple unpacking:

View File

@@ -0,0 +1,23 @@
# Regression test for bug #21242
discard """
action: compile
"""
iterator iterSome(): int =
proc inner1() =
let something = 6
proc inner2() =
let othersomething = something
inner2()
for n in 0 .. 10:
inner1()
yield n
proc test() =
proc test1() =
for v in iterSome():
discard
test1()
test()

13
tests/iter/t25704.nim Normal file
View File

@@ -0,0 +1,13 @@
import std/[sugar, strutils]
type Res[T] = tuple[a: int, b: string]
iterator test(): Res[string] =
yield (1, "")
for (i, s) in test():
static:
echo typeof(i)
echo typeof(s)
let
a: int = i
b: string = s