Closed yglukhov closed 1 year ago
I haven't found some useful clues, but there are some observations:
registerCmd
declaration makes it workregisterCmd
, but nextIdentIter
cannot find the other overloadI suspect there is something wrong with hash, but I had no luck to find the root cause.
The fact that the foo*
symbols are proc
's doesn't seem to make a difference, I can reproduce the issue using any combination of let
and var
as well:
var p1 = 0
let p2 = 0
let p3 = 0
let p4 = 0
let p5 = 0
let p6 = 0
let p7 = 0
let p8 = 0
let p9 = 0
let p10 = 0
let p11 = 0
let p12 = 0
let p13 = 0
let p14 = 0
let p15 = 0
let p16 = 0
let p17 = 0
let p18 = 0
let p19 = 0
let p20 = 0
let p22 = 0
let p23 = 0
let p24 = 0
let p25 = 0
let p26 = 0
let p27 = 0
let p28 = 0
let p29 = 0
let p30 = 0
let p31 = 0
let p32 = 0
let p33 = 0
let p34 = 0
let p35 = 0
let p36 = 0
let p37 = 0
let p38 = 0
let p39 = 0
let p40 = 0
let p41 = 0
let p42 = 0
proc call(i: int) =
discard
proc call(p: proc()) =
p1 = 1
call(proc () = discard)
echo p1
doAssert p1 == 1
This also only seems to trigger when passing a proc
as an argument, if the second proc call ...
is changed to:
proc call (s: string) =
p1 = 1
and the invocation is changed to call("hello world")
it works.
Wrapping the call(proc () = discard)
in an anonymous proc also seems to work: (proc () = call(proc () = discard))()
but that probably doesn't mean anything since an anonymous proc introduces a top level symbol.
I also tried unsuccessfully to force call
into scope by adding a mixin call
before the invocation.
Putting the invocation in a block
also seems to work:
block:
call(proc() = discard)
The AST for call(proc () = discard)
never reaches the code generator. The bug must be earlier in the compilation pipeline.
Already wrong during sem checking, semExpr spits out nkEmpty after semDirectOp
Funnily enough it does work if you put r = resolveOverloads(c, n, nOrig, filter, flags, errors, efExplain in flags)
after https://github.com/nim-lang/Nim/blob/devel/compiler/semcall.nim#L606 (so running it twice)
Going deeper than this, matches
in pickBestCandidate
finds new symbols and moving it above the counter check also makes it work because then recalc triggers for it
A related issue is that nextOverloadIter
does not find the proc call(p: proc())
overload in the cache. There maybe some issue with the way identifier chains are getting built up in the TStrTable
symbol table.
Took another peek. Issue seems to be caused by mergeShadowScope
in some way as it works with closeShadowScope
in noMatch
, matchesAux
mustRehash makes it work with * 2
for both length
and counter
, but not knowledgeable enough on this to know if that would cause other issues/move this issue to another magic number.
Logic error on my side, would make it always use second case because of assert, but interesting that that does make it work (edit from future: magic numbers from below apply, just other numbers)
Ok yeah this is interesting, quick python script tells us the other magic numbers where it breaks, make variables up until b-2 (so for b=22 you put p1-p20) and the lambda you pass will break it because regrow is triggered
a = 1
b = 0
for _ in range(2000):
if (a * 2 < b * 3) or (a - b < 4):
print(f"Grow at {a=} {b=}")
a *= 2
b += 1
Why does it rehash to begin with? Because of mergeShallowScope
?
Yeah merging it makes it put the lambda :anonymous
into parent scope so it grows and reaches the rehash threshold (magic numbers), seemingly messing with overload resolution, that's why it worked with closeShadowScope
instead of mergeShadowScope
in match. Also explains why overload order mattered, tries to match and then merges when noMatch is hit, so if it matches on first attempt it would work
Not sure how to fix this, so best I can do is give you what I figured out, but point of all this is that rehash breaks the iterator.
Idea of moving the call to match
up by one line might work though, because then recalc triggers like expected instead of sym being nil prematurely (or just don't merge scopes)
Description
Nim Version
Nim Compiler Version 1.9.1 [Linux: amd64] Compiled at 2023-01-17 Copyright (c) 2006-2023 by Andreas Rumpf
git hash: 30da566d9dc81feab9ba3015d293d93b5c6785af active boot switches: -d:release
Current Output
Expected Output
None
Possible Solution
No response
Additional Information
The generated C sources do not mention
registerCmd
at all, but they should.