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

asyncmacro: Error: attempting to call undeclared routine: 'callback=', when using forward declaration #7124

Open
skunkiferous opened this issue Jan 22, 2018 · 11 comments
Labels
Async Everything related to Nim's async Error Messages Standard Library

Comments

@skunkiferous
Copy link

skunkiferous commented Jan 22, 2018

I've checked open issues related to "callback", and could not find anthing similar, so I think it's a new issue. It's also been posted in the forum, in case someone knows a work-around.

It seems to be related mixing forward declarations with async code. Here is an example that causes the issue. It has to be defined as two different modules, otherwise I could not produce the error.

# modulea

import asyncdispatch
import asyncnet

type
  QueueID* = uint32
  Msg*[T: not (ref|string|seq)] = object
    content*: T

proc myQueue*(): QueueID =
  QueueID(0)

proc sendMsgInternally[T](q: QueueID, m: ptr[Msg[T]]): void =
  echo("Sending message internally to " & $q)

proc sendMsgExternally[T](q: QueueID, m: ptr[Msg[T]], size: uint32) {.async.}

proc sendMsg*[T](q: QueueID, m: ptr[Msg[T]]): void =
  # fill m with data ...
  if q == myQueue():
    sendMsgInternally(q, m)
  else:
    let size = uint32(sizeof(Msg[T]))
    asyncCheck sendMsgExternally(q, m, size)

proc sendMsgExternally[T](q: QueueID, m: ptr[Msg[T]], size: uint32) {.async.} =
  echo("Sending message across the cluster to " & $q)
  var sock = newAsyncSocket()
  await sock.send(pointer(m), int(size))
# moduleb

import modulea

type
  TstMsg = Msg[int]

proc testIt() =
  var m: TstMsg
  m.content = 42
  var dst = QueueID(99)
  sendMsg(dst, addr m)

testIt()
@dom96
Copy link
Contributor

dom96 commented Jan 22, 2018

so the problem is that you're not specifying the generic type to sendMsgExternally. To get this to work just change to sendMsgExternally[T](q, m, size).

That error message is horrible though.

@dom96
Copy link
Contributor

dom96 commented Jan 22, 2018

For reference: https://forum.nim-lang.org/t/3493

@dom96
Copy link
Contributor

dom96 commented Jan 22, 2018

As a side note, why is ptr[...] allowed and why are you using it? The convention is to write ptr T, not ptr[T]. IMO this should be removed from the language.

@andreaferretti
Copy link
Collaborator

Uh? I always assumed ptr T is a shortcut for ptr[T]. It is more consistent: pointer is just a generic type in fact. If anything, I would remove ptr T

@dom96
Copy link
Contributor

dom96 commented Jan 22, 2018

If anything, I would remove ptr T

99% of code uses this syntax. Why should it be removed?

I never thought of ptr as a generic. It's a special language construct, pretty sure it's represented uniquely in the compiler too.

@andreaferretti
Copy link
Collaborator

I guess it probably is. But speaking from a user point of view it is just a type that is parametrized on another type, like every generic is. It seems arbitrary and inconsistent to use a special syntax just because it is a pointer

@skunkiferous
Copy link
Author

skunkiferous commented Jan 22, 2018

@dom96 Could you paste the version of modulea that you got to work? I tried adding [T] to the call to sendMsgExternally(), and it still fails for me:

# modulea

import asyncdispatch
import asyncnet

type
  QueueID* = uint32
  Msg*[T: not (ref|string|seq)] = object
    content*: T

proc myQueue*(): QueueID =
  QueueID(0)

proc sendMsgInternally[T](q: QueueID, m: ptr[Msg[T]]): void =
  echo("Sending message internally to " & $q)

proc sendMsgExternally[T](q: QueueID, m: ptr[Msg[T]], size: uint32) {.async.}

proc sendMsg*[T](q: QueueID, m: ptr[Msg[T]]): void =
  # fill m with data ...
  if q == myQueue():
    sendMsgInternally[T](q, m)
  else:
    let size = uint32(sizeof(Msg[T]))
    asyncCheck sendMsgExternally[T](q, m, size)

proc sendMsgExternally[T](q: QueueID, m: ptr[Msg[T]], size: uint32) {.async.} =
  echo("Sending message across the cluster to " & $q)
  var sock = newAsyncSocket()
  await sock.send(pointer(m), int(size))

FYI, I'm using thios version of Nim:

Nim Compiler Version 0.17.2 (2017-09-07) [Windows: amd64]
Copyright (c) 2006-2017 by Andreas Rumpf

EDIT: And regarding ptr, I don't expect any syntax to be "removed", and I'll use whatever I have to, but I have to agree with @andreaferretti on this one; "ptr T" might be more "popular" (I wouldn't know), but "ptr[T]" is more "consistent", IMO.

@dom96
Copy link
Contributor

dom96 commented Jan 22, 2018

@skunkiferous apologies. That wasn't the proper fix. The real reason this fails is that the second module isn't importing asyncdispatch, you should be able to work around this by just importing that module.

And regarding ptr, I don't expect any syntax to be "removed", and I'll use whatever I have to, but I have to agree with @andreaferretti on this one; "ptr T" might be more "popular" (I wouldn't know), but "ptr[T]" is more "consistent", IMO.

The ultimate goal is to remove the syntax, but we would have a deprecation path (as usual). I do really dislike that there are two syntaxes for this case, so I would like to discourage its use and eventually remove it from the language.

@dom96 dom96 added Standard Library Async Everything related to Nim's async labels Jan 22, 2018
@dom96
Copy link
Contributor

dom96 commented Jan 22, 2018

As far as fixing this issue, I have a hunch that the async macro needs to "bind" the callback= procedure.

It would be nice to improve the error message as well. It took me far too long to work out the problem.

@skunkiferous
Copy link
Author

@dom96 The import fixed that issue. Now I have so much more "other" errors to fix. :D But at least, I understand them.

Regarding ptr, I'll rewrite my code accordingly; no point in using something that's deprecated (or soon going to be).

@andreaferretti
Copy link
Collaborator

Please, do leave ptr[T] in. People will be able to just ignore ptr T and use a consistent language where ptr is just another generic instead of a special language construct

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Async Everything related to Nim's async Error Messages Standard Library
Projects
None yet
Development

No branches or pull requests

3 participants