Skip to content

varargs[untyped] doesn't work with 0 arguments, creating an extraneous nnkHiddenStdConv varargs[untyped] node #8706

Closed
@timotheecour

Description

@timotheecour

see all mentions of BUG below:

see also workaround in case6 to create a macro varargsToTuple

this is a serious bug as it affects generic code (eg I had to work around it for #8679)

import macros

macro varargsToTuple(args:varargs[untyped]):untyped=
  result = newTree(nnkTupleConstr)
  for a in args:
    result.add a

macro varargsLen(args:varargs[untyped]):untyped=
  # BUG: should be 0 for case2, not 1
  result = newLit(args.len)

template foo(args:varargs[untyped]): untyped =
  varargsLen(args)

when defined(case1):
  doAssert foo(10) == 1
  doAssert foo(10, 20) == 2

when defined(case2):
  # fail
  # doAssert foo() == 0
  echo foo() # BUG: got 1


when defined(case3):
  macro varargsFirst(args:varargs[untyped]):untyped=
    echo args[0].kind # BUG: nnkHiddenStdConv ??

    result = args[0]

  template foo2(args:varargs[untyped]): untyped =
    varargsFirst(args)

  doAssert foo2(10) == 10
  # BUG: Error: invalid type: 'varargs[untyped]' for let
  let a = foo2()

when defined(case4):
  template foo2(args:varargs[untyped]): untyped =
    varargsToTuple(args)

  doAssert foo2(10) == (10,)
  doAssert foo2(10, 20) == (10, 20)
  when defined(case4a):
    # BUG: Error: invalid type: 'varargs[untyped]' in this context: 'tuple of (varargs[untyped])' for let
    let a = foo2()
  when defined(case4b):
     # BUG: Error: invalid type: 'untyped' in this context: 'iterator (x: tuple of (varargs[untyped])): RootObj{.inline, noSideEffect.}' for proc
    echo foo2()

when defined(case5):
  macro bar(arg:typed):untyped=
    result = newLit arg.repr

  template foo2(args:varargs[untyped]): untyped =
    bar(varargsToTuple(args))

  echo foo2(1) #(1,)
  echo foo2(1, 2) #(1, 2)
  echo foo2() # BUG: ([],)


when defined(case6):
  # workaround
  macro varargsToTuple2(args:varargs[untyped]):untyped=
    result = newTree(nnkTupleConstr)
    if args.len != 1:
      for a in args:
        result.add a
    else:
      # workaround for BUG with empty args `()`
      if args[0].kind != nnkHiddenStdConv:
          result.add args[0]

  template foo2(args:varargs[untyped]): untyped =
    varargsToTuple2(args)

  doAssert foo2(10) == (10,)
  doAssert foo2(10, 20) == (10, 20)
  echo foo2()

Metadata

Metadata

Assignees

No one assigned

    Labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions