From d7353ba6faee6510474541bc95f07bec940c5def Mon Sep 17 00:00:00 2001 From: zerbina <100542850+zerbina@users.noreply.github.com> Date: Sat, 29 Jun 2024 02:51:25 +0200 Subject: [PATCH] sem: correctly type empty containers in macro calls (#1361) ## Summary Internal-only issue. Empty container values passed to `static` macro/ template parameters used empty container types. Now they're converted to the formal parameter's type. ## Details * wrap the arguments to `static` macro/template parameters in implicit conversions, if needed for the match * use post-match argument fitting for macro calls * for a smaller impact, template calls still don't use post-match argument fitting * remove the `vmserialize` workaround for empty set types (which no longer reach there now) --- compiler/sem/semexprs.nim | 8 ++++++-- compiler/sem/sigmatch.nim | 24 ++++++++++++++++++++---- compiler/vm/vmserialize.nim | 6 +----- 3 files changed, 27 insertions(+), 11 deletions(-) diff --git a/compiler/sem/semexprs.nim b/compiler/sem/semexprs.nim index a810fd6033d..e9ae4293edd 100644 --- a/compiler/sem/semexprs.nim +++ b/compiler/sem/semexprs.nim @@ -1182,8 +1182,12 @@ proc afterCallActions(c: PContext; n: PNode, flags: TExprFlags): PNode = result = n let callee = result[0].sym case callee.kind - of skMacro: result = semMacroExpr(c, result, callee, flags) - of skTemplate: result = semTemplateExpr(c, result, callee, flags) + of skMacro: + result = fitArgTypesPostMatch(c, result) + if result.kind != nkError: + result = semMacroExpr(c, result, callee, flags) + of skTemplate: + result = semTemplateExpr(c, result, callee, flags) else: semFinishOperands(c, result) activate(c, result) diff --git a/compiler/sem/sigmatch.nim b/compiler/sem/sigmatch.nim index faf78bb9d6d..e14d99681bf 100644 --- a/compiler/sem/sigmatch.nim +++ b/compiler/sem/sigmatch.nim @@ -2311,10 +2311,26 @@ proc paramTypesMatchAux(m: var TCandidate, f, a: PType, of tyTyped, tyTypeDesc: arg of tyStatic: - if arg.typ.n.isNil: # no value on the type - argSemantized - else: # value on the type - arg.typ.n + let n = + if arg.typ.n.isNil: # no value on the type + argSemantized + else: # value on the type + arg.typ.n + + # XXX: the implicit conversion handling is duplicated from the non- + # template/non-macro path. Template and macro arguments shouldn't + # be special-cased like this + case r + of isEqual: n + of isGeneric: + if n.typ.isEmptyContainer: + implicitConv(nkHiddenStdConv, f[0], n, m, c) + else: + n + of isSubtype: + implicitConv(nkHiddenSubConv, f[0], n, m, c) + else: + implicitConv(nkHiddenStdConv, f[0], n, m, c) else: argSemantized return diff --git a/compiler/vm/vmserialize.nim b/compiler/vm/vmserialize.nim index 88f59328e39..ae4b29a558f 100644 --- a/compiler/vm/vmserialize.nim +++ b/compiler/vm/vmserialize.nim @@ -94,11 +94,7 @@ proc initFromExpr(dest: LocHandle, tree: MirTree, n: var int, env: MirEnv, # subtract the first element's value to make all values zero-based toInt(val - first) - let first = - if tree[n].len > 0: firstOrd(c.config, env[tree[n].typ]) - else: Zero - # XXX: ^^ ``set[empty]``-typed literals reach here, but they shouldn't. The - # len guard works around the issue + let first = firstOrd(c.config, env[tree[n].typ]) iterTree(j): let node = next() if node.kind == mnkRange: