From 5385e4b8a6eb781bc77afef4911931f869a4085b Mon Sep 17 00:00:00 2001 From: metagn Date: Mon, 7 Oct 2024 12:28:23 +0300 Subject: [PATCH] iterate overloads when resolving symchoice based on type fixes #20240 --- compiler/sigmatch.nim | 64 +++++++++++++++++++---------- tests/lookups/topensymchoiceres.nim | 20 +++++++++ 2 files changed, 62 insertions(+), 22 deletions(-) create mode 100644 tests/lookups/topensymchoiceres.nim diff --git a/compiler/sigmatch.nim b/compiler/sigmatch.nim index e50b50331ca8..935541e5bf49 100644 --- a/compiler/sigmatch.nim +++ b/compiler/sigmatch.nim @@ -2618,10 +2618,19 @@ proc paramTypesMatch*(m: var TCandidate, f, a: PType, if arg == nil or arg.kind notin nkSymChoices: result = paramTypesMatchAux(m, f, a, arg, argOrig) else: + # code to resolve symchoices based on type match + # should be moved to own proc but will mess up commit history # symbol kinds that don't participate in symchoice type disambiguation: let matchSet = {low(TSymKind)..high(TSymKind)} - {skModule, skPackage} - var best = -1 + var best: PNode = nil + proc getNode(choice: PNode, i: int, s: PSym): PNode {.inline.} = + # return ith node corresponding to symbol s in symchoice, + # if s is outside the symchoice, create new symbol node + if i < choice.len: + result = choice[i] + else: + result = newSymNode(s, choice.info) result = arg var actingF = f @@ -2632,20 +2641,25 @@ proc paramTypesMatch*(m: var TCandidate, f, a: PType, var bestScope = -1 counts = 0 - for i in 0.. bestScope: - best = i + best = getNode(arg, i, currentSym) bestScope = thisScope counts = 0 elif thisScope == bestScope: inc counts - if best == -1: + currentSym = nextOverloadIter(o, m.c, arg) + inc i + if best == nil: result = nil elif counts > 0: m.genericMatches = 1 - best = -1 + best = nil else: # CAUTION: The order depends on the used hashing scheme. Thus it is # incorrect to simply use the first fitting match. However, to implement @@ -2660,38 +2674,44 @@ proc paramTypesMatch*(m: var TCandidate, f, a: PType, y.calleeSym = m.calleeSym z.calleeSym = m.calleeSym - for i in 0.. -1 and result != nil: + if best != nil and result != nil: # only one valid interpretation found: - markUsed(m.c, arg.info, arg[best].sym) - onUse(arg.info, arg[best].sym) - result = paramTypesMatchAux(m, f, arg[best].typ, arg[best], argOrig) + markUsed(m.c, arg.info, best.sym) + onUse(arg.info, best.sym) + result = paramTypesMatchAux(m, f, best.typ, best, argOrig) when false: if m.calleeSym != nil and m.calleeSym.name.s == "[]": echo m.c.config $ arg.info, " for ", m.calleeSym.name.s, " ", m.c.config $ m.calleeSym.info diff --git a/tests/lookups/topensymchoiceres.nim b/tests/lookups/topensymchoiceres.nim new file mode 100644 index 000000000000..d0ecf938da64 --- /dev/null +++ b/tests/lookups/topensymchoiceres.nim @@ -0,0 +1,20 @@ +discard """ + output: ''' +int: 100 +''' +""" + +# issue #20240 + +type Action[T] = proc (x: T): void {.nimcall.} + +proc doThing(x : float) = echo "float: ", x + +proc getDoThing[T]: Action[T] = + mixin doThing + assert compiles(doThing(default(T))) # still works + result = doThing # but this doesn't -- type mismatch: got 'None' for 'doThing' but expected 'Action[system.int]' + +proc doThing(x : int) = echo "int: ", x +let intDoThing = getDoThing[int]() +intDoThing(100)