flyx / NimYAML

YAML implementation for Nim
https://nimyaml.org
Other
191 stars 36 forks source link

Field name causes `Error: ambiguous identifier` for no relevant Reason #136

Closed theAkito closed 1 year ago

theAkito commented 1 year ago

https://github.com/theAkito/zoominvitr/actions/runs/5957435803/job/16160211615#step:7:638

Module A

.....
const
  debug* {.booldefine.} = false
.....

Module B

.....
  ConfigSettings* {.sparse.} = object
    debug*: Option[ConfigDebug]
    zoomApiPullInterval*: Option[ConfigPushSchedule]
    hostRedis*: Option[string]
    portRedis*: Option[int]
.....

Module A has no relationship whatsoever to Module B. They do not import each other, nothing. The only way, they are in some way connected is that Module C is importing both at the same time. Module B also imports yaml, while Module A does not.

So, how does serialization.nim know and, most importantly, care about a constant from a foreign module? How does this even collide?

Do the fields need to be unique across the project?

This is the related code snippet from serialization.nim.

.....
      let
        name = $child
        childAccessor = newDotExpr(value, newIdentNode(name))
      result.add(quote do:
        template serializeImpl {.used.} =
          when bool(`isVO`): c.put(startMapEvent())
          c.put(scalarEvent(`name`, if `childTagStyle` == tsNone:
              yTagQuestionMark else: yTagNimField, yAnchorNone))
          representChild(`childAccessor`, `childTagStyle`, c)
          when bool(`isVO`): c.put(endMapEvent())
        when not `childAccessor`.hasCustomPragma(transient):
          when hasSparse(`tDecl`) and `child` is Option:
            if `childAccessor`.isSome: serializeImpl()
          else:
            serializeImpl()
      )
.....

When re-defining ConfigSettings.debug as ConfigSettings.sDebug, compilation succeeds, because the names are different.

flyx commented 1 year ago

I assume Module C is the module that calls NimYAML functionality (load / dump / etc)? Then both A and B are visible in C and therefore visible when binding symbols in NimYAML's macros, because name binding in macros happens at the calling site.

That being said, the const in Module A you show does not seem to be the issue at all. The error says

[snip]/yaml/serialization.nim(1051, 55) Error: ambiguous identifier: 'debug' -- use one of the following:
  meta.debug: bool
  logging.debug: template (args: varargs[string])

The second debug is a template, most probably this one. The problem seems to be that debug(arg) can be written as arg.debug which in this case is what NimYAML generates. I cannot reproduce the error with simpler code though.

My advice would be to call NimYAML somewhere where std/logging is not directly visible. There should be a way to force Nim to bind the symbol as field but I don't know how.

theAkito commented 1 year ago

@flyx

Fixed it like this.

import std/logging except debug

Thank you very much! 🙂