summary refs log tree commit diff stats
diff options
context:
space:
mode:
-rw-r--r--compiler/semtempl.nim39
-rw-r--r--tests/template/tnested.nim38
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))