Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Error: type mismatch: got <typedesc[A]>, but expected one of: A = proc (){.closure.} #23587

Closed
haoyu234 opened this issue May 9, 2024 · 4 comments · Fixed by #24265
Closed

Comments

@haoyu234
Copy link
Contributor

haoyu234 commented May 9, 2024

Description

https://play.nim-lang.org/#pasty=cVWRkhXTOfpv

Compiles normally on 'play.nim-lang.org' without uncommenting.
Compiling locally will report an error, just like the title says.

import std/tables

# After uncommenting and compiling on 'play.nim-lang.org', an error will be reported (killed by system)
# import std/asyncnet
# import std/asyncdispatch

type
  A = proc ()

proc main =
  let repo = initTable[uint32, A]()

  let c1 = repo.getOrDefault(uint32(1), nil)
  echo "c1.isNil: ", c1.isNil

  let c2 = repo.getOrDefault(uint32(1), A(nil))
  echo "c2.isNil: ", c2.isNil

main()

Nim Version

Nim Compiler Version 2.1.1 [Linux: amd64]
Compiled at 2024-05-05
Copyright (c) 2006-2024 by Andreas Rumpf

git hash: 1ef4d04
active boot switches: -d:release

Current Output

/root/repos/spaces2/a.nim(13, 16) template/generic instantiation of `getOrDefault` from here
/root/.choosenim/toolchains/nim-#devel/lib/pure/collections/tables.nim(437, 19) Error: type mismatch: got <typedesc[A]>
but expected one of:
A = proc (){.closure.}

Expected Output

no error

Possible Solution

No response

Additional Information

No response

@haoyu234 haoyu234 changed the title Error: type mismatch: got <typedesc[A]>, but expected one of: A = proc (b: B){.closure.} Error: type mismatch: got <typedesc[A]>, but expected one of: A = proc (){.closure.} May 9, 2024
@drkameleon
Copy link
Contributor

Also spotted: https://forum.nim-lang.org/t/12547

@haoyu234 Have you found any workaround to this?

@metagn
Copy link
Collaborator

metagn commented Oct 8, 2024

Took me a second to figure it out, the issue is this call:

result = default(B)

It tries to call the parameter default with B rather than the magic default, which gets overriden because default has a proc type in this case. A minimization is:

proc foo(default: proc ()) =
  echo default(int)

foo(123)

which seems to fail in all versions, likely it also started consistently happening for generic procs at some point nevermind, the call was just added in #22365. Doesn't happen if default doesn't have a proc type.

Very easily worked around by just removing this call from tables but it is an interesting issue and the error message isn't good.

metagn added a commit to metagn/Nim that referenced this issue Oct 8, 2024
Araq pushed a commit that referenced this issue Oct 9, 2024
fixes #23587

As explained in the issue, `getOrDefault` has a parameter named
`default` that can be a proc after generic instantiation. But the
parameter having a proc type [overrides all other
overloads](https://github.com/nim-lang/Nim/blob/f73e03b1323cf3ed65d6996f43c8e6891c40f924/compiler/semexprs.nim#L1203)
including the magic `system.default` overload and causes a compile error
if the proc doesn't match the normal use of `default`. To fix this, the
`result = default(B)` initializer call is removed because it's not
needed, `result` is always set in `getOrDefaultImpl` when a default
value is provided.

This is still a suspicious behavior of the compiler but `tables` working
has a higher priority.
@c-blake
Copy link
Contributor

c-blake commented Oct 10, 2024

This workaround seems ok, but for non-proc value types it worked before when called with a keyword parameter. E.g., this worked fine but with this fix it obviously will not:

import std/tables
var t: Table[int, int]
echo t.getOrDefault(0, default=2)

A preliminary search of Nimble packages makes that seems very rare. As a (probably already known) simple meta-rule, if you must change call sites in / uses by the compiler, you should likely put in a changelog. Some dark/non-nimble-published code might like the self-documenting/more explicit kw param calls => changelog, even if the compile error in that case might be clear.

@c-blake
Copy link
Contributor

c-blake commented Oct 10, 2024

(and I know both @Araq & @metagn noticed my above point (sans changelog idea) already from the code review discussion on the PR - but maybe more people read Issue threads?? ¯\(ツ)/¯ )

narimiran pushed a commit that referenced this issue Jan 14, 2025
fixes #23587

As explained in the issue, `getOrDefault` has a parameter named
`default` that can be a proc after generic instantiation. But the
parameter having a proc type [overrides all other
overloads](https://github.com/nim-lang/Nim/blob/f73e03b1323cf3ed65d6996f43c8e6891c40f924/compiler/semexprs.nim#L1203)
including the magic `system.default` overload and causes a compile error
if the proc doesn't match the normal use of `default`. To fix this, the
`result = default(B)` initializer call is removed because it's not
needed, `result` is always set in `getOrDefaultImpl` when a default
value is provided.

This is still a suspicious behavior of the compiler but `tables` working
has a higher priority.

(cherry picked from commit 67ea754)
narimiran pushed a commit that referenced this issue Jan 14, 2025
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging a pull request may close this issue.

4 participants