From 05beb32d0726d8f73dd9821de6b00ab2cdd8835a Mon Sep 17 00:00:00 2001 From: Ryan McConnell Date: Tue, 11 Mar 2025 05:01:32 -0400 Subject: [PATCH] folding const expressions with branching logic (#24689) motivating example: ```nim iterator p(a: openArray[char]): int = if a.len != 0: if a[0] != '/': discard for t in p(""): discard ``` The compiler wants to evaluate `a[0]` at compile time even though it is protected by the if statement above it. Similarly expressions like `a.len != 0 and a[0] == '/'` have problems. It seems like the logic in semfold needs to be more aware of branches to positively identify when it is okay to fail compilation in these scenarios. It's a bit tough though because it may be the case that non-constant expressions in branching logic can properly protect some constant expressions. (cherry picked from commit 850f32771339efc8ae0a1f070f231e0167ac946c) --- compiler/semfold.nim | 7 ++++--- tests/controlflow/tcontrolflow.nim | 7 +++++++ 2 files changed, 11 insertions(+), 3 deletions(-) diff --git a/compiler/semfold.nim b/compiler/semfold.nim index 00b40f5727..451d675188 100644 --- a/compiler/semfold.nim +++ b/compiler/semfold.nim @@ -471,19 +471,20 @@ proc foldArrayAccess(m: PSym, n: PNode; idgen: IdGenerator; g: ModuleGraph): PNo if result.kind == nkExprColonExpr: result = result[1] else: result = nil - localError(g.config, n.info, formatErrorIndexBound(idx, x.len-1) & $n) + #localError(g.config, n.info, formatErrorIndexBound(idx, x.len-1) & $n) of nkBracket: idx -= toInt64(firstOrd(g.config, x.typ)) if idx >= 0 and idx < x.len: result = x[int(idx)] else: result = nil - localError(g.config, n.info, formatErrorIndexBound(idx, x.len-1) & $n) + #localError(g.config, n.info, formatErrorIndexBound(idx, x.len-1) & $n) of nkStrLit..nkTripleStrLit: result = newNodeIT(nkCharLit, x.info, n.typ) if idx >= 0 and idx < x.strVal.len: result.intVal = ord(x.strVal[int(idx)]) else: - localError(g.config, n.info, formatErrorIndexBound(idx, x.strVal.len-1) & $n) + result = nil + #localError(g.config, n.info, formatErrorIndexBound(idx, x.strVal.len-1) & $n) else: result = nil proc foldFieldAccess(m: PSym, n: PNode; idgen: IdGenerator; g: ModuleGraph): PNode = diff --git a/tests/controlflow/tcontrolflow.nim b/tests/controlflow/tcontrolflow.nim index dd21a2bb67..c2f34ce0e2 100644 --- a/tests/controlflow/tcontrolflow.nim +++ b/tests/controlflow/tcontrolflow.nim @@ -114,3 +114,10 @@ block named: # works if true: break named doAssert false, "not reached" + +block: + iterator p(a: openArray[char]): int = + if a.len != 0: + if a[0] != '/': + discard + for t in p(""): discard