From ca77423ffc09e92ca17e430bf79c10ae3c1adb63 Mon Sep 17 00:00:00 2001 From: Ryan McConnell Date: Tue, 20 Feb 2024 02:08:16 -0500 Subject: [PATCH] `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. --- compiler/sigmatch.nim | 23 +++++++++++++++++++++-- tests/types/tissues_types.nim | 10 ++++++++++ 2 files changed, 31 insertions(+), 2 deletions(-) diff --git a/compiler/sigmatch.nim b/compiler/sigmatch.nim index a0de33ed50..e831a28562 100644 --- a/compiler/sigmatch.nim +++ b/compiler/sigmatch.nim @@ -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: diff --git a/tests/types/tissues_types.nim b/tests/types/tissues_types.nim index 49c6d85eea..6bb1258f4d 100644 --- a/tests/types/tissues_types.nim +++ b/tests/types/tissues_types.nim @@ -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)