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.
This commit is contained in:
Ryan McConnell
2025-03-11 05:01:32 -04:00
committed by GitHub
parent 38ad336c69
commit 850f327713
2 changed files with 11 additions and 3 deletions

View File

@@ -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 =

View File

@@ -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