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:
LemonBoy
2018-08-31 12:16:46 +02:00
committed by Andreas Rumpf
parent aa33bcb974
commit b74faf354e
2 changed files with 38 additions and 6 deletions

View File

@@ -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:
formal = m.callee.n.sons[f].sym
incl(marker, formal.position)
if container.isNil:
container = newNodeIT(nkArgList, n.sons[a].info, arrayConstr(c, n.info))
setSon(m.call, formal.position + 1, container)
if n.sons[a].kind == nkHiddenStdConv:
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:
incrIndexType(container.typ)
addSon(container, n.sons[a])
if container.isNil:
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:
# named 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 formal.ast == nil:
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,
implicitConv(nkHiddenStdConv, formal.typ, container, m, c))
else:

21
tests/macros/t8706.nim Normal file
View 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()