diff options
-rw-r--r-- | compiler/semtempl.nim | 39 | ||||
-rw-r--r-- | tests/template/tnested.nim | 38 |
2 files changed, 63 insertions, 14 deletions
diff --git a/compiler/semtempl.nim b/compiler/semtempl.nim index e572efdc0..10440614d 100644 --- a/compiler/semtempl.nim +++ b/compiler/semtempl.nim @@ -507,14 +507,21 @@ proc semTemplBody(c: var TemplCtx, n: PNode): PNode = if x.kind == nkExprColonExpr: x[1] = semTemplBody(c, x[1]) of nkBracketExpr: - result = newNodeI(nkCall, n.info) - result.add newIdentNode(getIdent(c.c.cache, "[]"), n.info) - for i in 0..<n.len: result.add(n[i]) + if n.typ == nil: + # if a[b] is nested inside a typed expression, don't convert it + # back to `[]`(a, b), prepareOperand will not typecheck it again + # and so `[]` will not be resolved + # checking if a[b] is typed should be enough to cover this case + result = newNodeI(nkCall, n.info) + result.add newIdentNode(getIdent(c.c.cache, "[]"), n.info) + for i in 0..<n.len: result.add(n[i]) result = semTemplBodySons(c, result) of nkCurlyExpr: - result = newNodeI(nkCall, n.info) - result.add newIdentNode(getIdent(c.c.cache, "{}"), n.info) - for i in 0..<n.len: result.add(n[i]) + if n.typ == nil: + # see nkBracketExpr case for explanation + result = newNodeI(nkCall, n.info) + result.add newIdentNode(getIdent(c.c.cache, "{}"), n.info) + for i in 0..<n.len: result.add(n[i]) result = semTemplBodySons(c, result) of nkAsgn, nkFastAsgn, nkSinkAsgn: checkSonsLen(n, 2, c.c.config) @@ -524,17 +531,21 @@ proc semTemplBody(c: var TemplCtx, n: PNode): PNode = let k = a.kind case k of nkBracketExpr: - result = newNodeI(nkCall, n.info) - result.add newIdentNode(getIdent(c.c.cache, "[]="), n.info) - for i in 0..<a.len: result.add(a[i]) - result.add(b) + if a.typ == nil: + # see nkBracketExpr case above for explanation + result = newNodeI(nkCall, n.info) + result.add newIdentNode(getIdent(c.c.cache, "[]="), n.info) + for i in 0..<a.len: result.add(a[i]) + result.add(b) let a0 = semTemplBody(c, a[0]) result = semTemplBodySons(c, result) of nkCurlyExpr: - result = newNodeI(nkCall, n.info) - result.add newIdentNode(getIdent(c.c.cache, "{}="), n.info) - for i in 0..<a.len: result.add(a[i]) - result.add(b) + if a.typ == nil: + # see nkBracketExpr case above for explanation + result = newNodeI(nkCall, n.info) + result.add newIdentNode(getIdent(c.c.cache, "{}="), n.info) + for i in 0..<a.len: result.add(a[i]) + result.add(b) result = semTemplBodySons(c, result) else: result = semTemplBodySons(c, n) diff --git a/tests/template/tnested.nim b/tests/template/tnested.nim new file mode 100644 index 000000000..81e416a76 --- /dev/null +++ b/tests/template/tnested.nim @@ -0,0 +1,38 @@ +block: # issue #22775 + proc h(c: int) = discard + template k(v: int) = + template p() = v.h() + p() + let a = @[0] + k(0 and not a[0]) + +block: # issue #22775 case 2 + proc h(c: int, q: int) = discard + template k(v: int) = + template p() = h(v, v) + p() + let a = [0] + k(0 and not a[0]) + +block: # issue #22775 minimal cases + proc h(c: int) = discard + template k(v: int) = + template p() = h(v) + p() + let a = [0] + k(not a[0]) + block: + k(-a[0]) + block: + proc f(x: int): int = x + k(f a[0]) + +block: # bracket assignment case of above tests + proc h(c: int) = discard + template k(v: int) = + template p() = h(v) + p() + var a = [0] + k(not (block: + a[0] = 1 + 1)) |