Do not materialize empty varargs[untyped] arrays (#8715)
When an empty nkArgList `varargs[untyped]` is passed around it is now reused for efficiency sake and to prevent the introduction of a spurious element: before this commit we'd pass the caller a nkArgList[nkHiddenStdConv[nkBracket]] node instead of just an empty nkArgList. Fixes #8706
This commit is contained in:
parent
aa33bcb974
commit
b74faf354e
2 changed files with 38 additions and 6 deletions
|
|
@ -2231,12 +2231,20 @@ proc matchesAux(c: PContext, n, nOrig: PNode,
|
||||||
if a >= formalLen-1 and f < formalLen and m.callee.n[f].typ.isVarargsUntyped:
|
if a >= formalLen-1 and f < formalLen and m.callee.n[f].typ.isVarargsUntyped:
|
||||||
formal = m.callee.n.sons[f].sym
|
formal = m.callee.n.sons[f].sym
|
||||||
incl(marker, formal.position)
|
incl(marker, formal.position)
|
||||||
if container.isNil:
|
|
||||||
container = newNodeIT(nkArgList, n.sons[a].info, arrayConstr(c, n.info))
|
if n.sons[a].kind == nkHiddenStdConv:
|
||||||
setSon(m.call, formal.position + 1, container)
|
doAssert n.sons[a].sons[0].kind == nkEmpty and
|
||||||
|
n.sons[a].sons[1].kind == nkArgList and
|
||||||
|
n.sons[a].sons[1].len == 0
|
||||||
|
# Steal the container and pass it along
|
||||||
|
setSon(m.call, formal.position + 1, n.sons[a].sons[1])
|
||||||
else:
|
else:
|
||||||
incrIndexType(container.typ)
|
if container.isNil:
|
||||||
addSon(container, n.sons[a])
|
container = newNodeIT(nkArgList, n.sons[a].info, arrayConstr(c, n.info))
|
||||||
|
setSon(m.call, formal.position + 1, container)
|
||||||
|
else:
|
||||||
|
incrIndexType(container.typ)
|
||||||
|
addSon(container, n.sons[a])
|
||||||
elif n.sons[a].kind == nkExprEqExpr:
|
elif n.sons[a].kind == nkExprEqExpr:
|
||||||
# named param
|
# named param
|
||||||
# check if m.callee has such a param:
|
# check if m.callee has such a param:
|
||||||
|
|
@ -2400,7 +2408,10 @@ proc matches*(c: PContext, n, nOrig: PNode, m: var TCandidate) =
|
||||||
if not containsOrIncl(marker, formal.position):
|
if not containsOrIncl(marker, formal.position):
|
||||||
if formal.ast == nil:
|
if formal.ast == nil:
|
||||||
if formal.typ.kind == tyVarargs:
|
if formal.typ.kind == tyVarargs:
|
||||||
var container = newNodeIT(nkBracket, n.info, arrayConstr(c, n.info))
|
# For consistency with what happens in `matchesAux` select the
|
||||||
|
# container node kind accordingly
|
||||||
|
let cnKind = if formal.typ.isVarargsUntyped: nkArgList else: nkBracket
|
||||||
|
var container = newNodeIT(cnKind, n.info, arrayConstr(c, n.info))
|
||||||
setSon(m.call, formal.position + 1,
|
setSon(m.call, formal.position + 1,
|
||||||
implicitConv(nkHiddenStdConv, formal.typ, container, m, c))
|
implicitConv(nkHiddenStdConv, formal.typ, container, m, c))
|
||||||
else:
|
else:
|
||||||
|
|
|
||||||
21
tests/macros/t8706.nim
Normal file
21
tests/macros/t8706.nim
Normal file
|
|
@ -0,0 +1,21 @@
|
||||||
|
discard """
|
||||||
|
output: '''0
|
||||||
|
0
|
||||||
|
'''
|
||||||
|
"""
|
||||||
|
|
||||||
|
import macros
|
||||||
|
|
||||||
|
macro varargsLen(args:varargs[untyped]): untyped =
|
||||||
|
doAssert args.kind == nnkArglist
|
||||||
|
doAssert args.len == 0
|
||||||
|
result = newLit(args.len)
|
||||||
|
|
||||||
|
template bar(a0:varargs[untyped]): untyped =
|
||||||
|
varargsLen(a0)
|
||||||
|
|
||||||
|
template foo(x: int, a0:varargs[untyped]): untyped =
|
||||||
|
bar(a0)
|
||||||
|
|
||||||
|
echo foo(42)
|
||||||
|
echo bar()
|
||||||
Loading…
Add table
Add a link
Reference in a new issue