From e39272eaa832589368f5cc2cafd157c732ce48e4 Mon Sep 17 00:00:00 2001 From: ringabout <43030857+ringabout@users.noreply.github.com> Date: Fri, 10 Apr 2026 21:29:20 +0800 Subject: [PATCH] fixes #25637; nim ic with destructors (#25723) fixes #25637 This pull request refactors the way the `sfInjectDestructors` flag is set on symbols during lambda lifting in the Nim compiler. The main change is the introduction of a helper procedure to encapsulate the logic for marking symbols that require destructor injection, improving code clarity and maintainability. Refactoring and code quality improvements: * Introduced the `markInjectDestructors` procedure to encapsulate the logic for marking a symbol with the `sfInjectDestructors` flag, ensuring that `backendEnsureMutable` is always called before modifying the symbol's flags. * Replaced direct flag manipulation (`owner.incl sfInjectDestructors` and `prc.incl sfInjectDestructors`) with calls to the new `markInjectDestructors` procedure in multiple locations, including `makeClosure`, `createTypeBoundOpsLL`, and `rawClosureCreation`. [[1]](diffhunk://#diff-19193904ba011a2bcc1e1a9768a7eb57cac57a274cad73d388149776ec2901e6L231-R235) [[2]](diffhunk://#diff-19193904ba011a2bcc1e1a9768a7eb57cac57a274cad73d388149776ec2901e6L243-R247) [[3]](diffhunk://#diff-19193904ba011a2bcc1e1a9768a7eb57cac57a274cad73d388149776ec2901e6L639-R643) --- compiler/lambdalifting.nim | 10 +++++++--- tests/ic/tmiscs.nim | 12 ++++++++++++ 2 files changed, 19 insertions(+), 3 deletions(-) diff --git a/compiler/lambdalifting.nim b/compiler/lambdalifting.nim index 8f979a16b5..a94db43211 100644 --- a/compiler/lambdalifting.nim +++ b/compiler/lambdalifting.nim @@ -216,6 +216,10 @@ proc newAsgnStmt(le, ri: PNode, info: TLineInfo): PNode = result[0] = le result[1] = ri +proc markInjectDestructors(s: PSym) {.inline.} = + backendEnsureMutable s + s.flagsImpl.incl sfInjectDestructors + proc makeClosure*(g: ModuleGraph; idgen: IdGenerator; prc: PSym; env: PNode; info: TLineInfo): PNode = result = newNodeIT(nkClosure, info, prc.typ) result.add(newSymNode(prc)) @@ -228,7 +232,7 @@ proc makeClosure*(g: ModuleGraph; idgen: IdGenerator; prc: PSym; env: PNode; inf #if isClosureIterator(result.typ): createTypeBoundOps(g, nil, result.typ, info, idgen) if tfHasAsgn in result.typ.flags or optSeqDestructors in g.config.globalOptions: - prc.incl sfInjectDestructors + markInjectDestructors(prc) template liftingHarmful(conf: ConfigRef; owner: PSym): bool = ## lambda lifting can be harmful for JS-like code generators. @@ -240,7 +244,7 @@ proc createTypeBoundOpsLL(g: ModuleGraph; refType: PType; info: TLineInfo; idgen createTypeBoundOps(g, nil, refType.elementType, info, idgen) createTypeBoundOps(g, nil, refType, info, idgen) if tfHasAsgn in refType.flags or optSeqDestructors in g.config.globalOptions: - owner.incl sfInjectDestructors + markInjectDestructors(owner) proc genCreateEnv(env: PNode): PNode = var c = newNodeIT(nkObjConstr, env.info, env.typ) @@ -636,7 +640,7 @@ proc rawClosureCreation(owner: PSym; if owner.kind != skMacro: createTypeBoundOps(d.graph, nil, fieldAccess.typ, env.info, d.idgen) if tfHasAsgn in fieldAccess.typ.flags or optSeqDestructors in d.graph.config.globalOptions: - owner.incl sfInjectDestructors + markInjectDestructors(owner) let upField = lookupInRecord(env.typ.skipTypes({tyOwned, tyRef, tyPtr}).n, getIdent(d.graph.cache, upName)) if upField != nil: diff --git a/tests/ic/tmiscs.nim b/tests/ic/tmiscs.nim index 403faf360b..aabdd92601 100644 --- a/tests/ic/tmiscs.nim +++ b/tests/ic/tmiscs.nim @@ -7,6 +7,7 @@ discard """ 1.0 2.0 55 +@[1, 2] ''' """ @@ -79,3 +80,14 @@ let x = compute: echo x +# Crash: bridge.nim(206, 5) `allowEmpty` unexpected nkEmpty [AssertionDefect] +# Bare closure iterator type alias +type IntIter = iterator(): int {.closure.} +proc run(it: IntIter): seq[int] = + result = @[] + for x in it(): + result.add(x) +let gen: IntIter = iterator(): int {.closure.} = + yield 1 + yield 2 +echo run(gen)