mirror of
https://github.com/nim-lang/Nim.git
synced 2025-12-28 08:54:53 +00:00
varargs[typed] should behave more like typed (#23303)
This fixes an oversight with a change that I made a while ago. Basically, these two snippets should both compile. Currently the `varargs` version will fail. ```nim template s(d: typed)=discard proc something()=discard proc something(x:int)=discard s(something) ``` ```nim template s(d: varargs[typed])=discard proc something()=discard proc something(x:int)=discard s(something) ``` Potentially unrelated, but this works currently for some reason: ```nim template s(a: varargs[typed])=discard proc something()=discard proc something(x:int)=discard s: something ``` also, this works: ```nim template s(b:untyped, a: varargs[typed])=discard proc something()=discard proc something(x:int)=discard s (g: int): something ``` but this doesn't, and the error message is not what I would expect: ```nim template s(b:untyped, a: varargs[typed])=discard proc something()=discard proc something(x:int)=discard s (g: int), something ``` So far as I can tell, none of these issues persist for me after the code changes in this PR.
This commit is contained in:
@@ -2311,6 +2311,9 @@ proc paramTypesMatchAux(m: var TCandidate, f, a: PType,
|
||||
if f.n != nil:
|
||||
# Forward to the varargs converter
|
||||
result = localConvMatch(c, m, f, a, arg)
|
||||
elif f[0].kind == tyTyped:
|
||||
inc m.genericMatches
|
||||
result = arg
|
||||
else:
|
||||
r = typeRel(m, base(f), a)
|
||||
case r
|
||||
@@ -2360,7 +2363,11 @@ proc paramTypesMatch*(m: var TCandidate, f, a: PType,
|
||||
var best = -1
|
||||
result = arg
|
||||
|
||||
if f.kind in {tyTyped, tyUntyped}:
|
||||
var actingF = f
|
||||
if f.kind == tyVarargs:
|
||||
if m.calleeSym.kind in {skTemplate, skMacro}:
|
||||
actingF = f[0]
|
||||
if actingF.kind in {tyTyped, tyUntyped}:
|
||||
var
|
||||
bestScope = -1
|
||||
counts = 0
|
||||
@@ -2376,6 +2383,7 @@ proc paramTypesMatch*(m: var TCandidate, f, a: PType,
|
||||
if best == -1:
|
||||
result = nil
|
||||
elif counts > 0:
|
||||
m.genericMatches = 1
|
||||
best = -1
|
||||
else:
|
||||
# CAUTION: The order depends on the used hashing scheme. Thus it is
|
||||
@@ -2497,6 +2505,9 @@ proc incrIndexType(t: PType) =
|
||||
template isVarargsUntyped(x): untyped =
|
||||
x.kind == tyVarargs and x[0].kind == tyUntyped
|
||||
|
||||
template isVarargsTyped(x): untyped =
|
||||
x.kind == tyVarargs and x[0].kind == tyTyped
|
||||
|
||||
proc findFirstArgBlock(m: var TCandidate, n: PNode): int =
|
||||
# see https://github.com/nim-lang/RFCs/issues/405
|
||||
result = int.high
|
||||
@@ -2671,7 +2682,15 @@ proc matchesAux(c: PContext, n, nOrig: PNode, m: var TCandidate, marker: var Int
|
||||
n[a], nOrig[a])
|
||||
if arg == nil:
|
||||
noMatch()
|
||||
if m.baseTypeMatch:
|
||||
if formal.typ.isVarargsTyped and m.calleeSym.kind in {skTemplate, skMacro}:
|
||||
if container.isNil:
|
||||
container = newNodeIT(nkBracket, n[a].info, arrayConstr(c, n.info))
|
||||
setSon(m.call, formal.position + 1, implicitConv(nkHiddenStdConv, formal.typ, container, m, c))
|
||||
else:
|
||||
incrIndexType(container.typ)
|
||||
container.add n[a]
|
||||
f = max(f, formalLen - n.len + a + 1)
|
||||
elif m.baseTypeMatch:
|
||||
assert formal.typ.kind == tyVarargs
|
||||
#assert(container == nil)
|
||||
if container.isNil:
|
||||
|
||||
@@ -106,3 +106,13 @@ block:
|
||||
let t = Foo[float](x1: 1)
|
||||
doAssert t.x1 == 1
|
||||
|
||||
block:
|
||||
template s(d: varargs[typed])=discard
|
||||
|
||||
proc something(x:float)=discard
|
||||
proc something(x:int)=discard
|
||||
proc otherthing()=discard
|
||||
|
||||
s(something)
|
||||
s(otherthing, something)
|
||||
s(something, otherthing)
|
||||
|
||||
Reference in New Issue
Block a user