nim-lang / Nim

Nim is a statically typed compiled systems programming language. It combines successful concepts from mature languages like Python, Ada and Modula. Its design focuses on efficiency, expressiveness, and elegance (in that order of priority).
https://nim-lang.org
Other
16.55k stars 1.47k forks source link

Invoking generic procedure that uses varargs implicit conversion acts incorrectly #11154

Open SolitudeSF opened 5 years ago

SolitudeSF commented 5 years ago

Invoking generic procedure that uses varargs implicit conversion breaks.

Example

a.nim

proc convert(arg: HSlice): string = discard

proc implicitConvert(args: varargs[string, convert]) = discard

proc test*(range: HSlice) = implicitConvert range

b.nim

import a

test 0..1

Current Output

a.nim(1, 6) Hint: 'convert' is declared but not used [XDeclaredButNotUsed]
b.nim(3, 6) template/generic instantiation of `test` from here
a.nim(3, 44) Error: undeclared identifier: 'convert'

Expected Output

Should compile.

Additional Information

Adding explicit generic parameters to HSlice in test proc makes program compile.

Nim Compiler Version 0.19.9 [Linux: amd64]
Compiled at 2019-05-01
disruptek commented 5 years ago

Adding a call to test() inside a.nim causes it to compile and run correctly.

krux02 commented 5 years ago

At first sight I thought this would be the same thing as https://github.com/nim-lang/Nim/issues/11155, but it isn't. The convert symbol is resolved in test, which is defined in a.nim, a totally valid context to use the unexported convert function.

Btw a non generic version of test will make this example compile.

proc convert(arg: HSlice): string = discard

proc implicitConvert(args: varargs[string, convert]) = discard

# non generic version of ``test``
proc test*(arg: HSlice[int,int]) =
  implicitConvert(arg)
maxtidev commented 5 months ago

Any leads on how to address this? I seem to be suffering from the same or a similar issue.

My error ``` Expression: select(dbConn, relatedEntries, sqlCondition, oneEntry.id) [1] dbConn: DbConn [2] relatedEntries: seq[Player] [3] sqlCondition: string [4] oneEntry.id: int64 Expected one of (first mismatch at [position]): [1] proc select[T: Model](dbHandler; colName: string; value: string): Option[T] [2] proc select[T: Model](dbConn; obj: var T; cond: string; params: varargs[DbValue, dbValue]) [4] proc select[T: Model](dbConn; objs: var seq[T]; cond: string; params: varargs[DbValue, dbValue]) ``` `dbValue` should convert `int64` to `DbValue` but the compiler doesn't agree. `select` is being called in a generic proc inside a module ([norm/postgres.nim#L527](https://github.com/moigagoo/norm/blob/develop/src/norm/postgres.nim#L527) ). I import this module and call this generic proc with my own generic proc: ```nim proc selectOneToMany*[O: Model, T: Model](dbHandler; oneEntry: O): Option[seq[T]] = var objs = @[ when T is Lobby: newLobby() elif T is Player: newPlayer() elif T is Game: newGame() elif T is Participation: newParticipation()] try: dbHandler.dbConn.selectOneToMany[:O, T](oneEntry, objs) except NotFoundError: return none(seq[T]) result = some(objs) ```

Edit: Adding an unused non-generic call to the generic proc makes it compile correctly. Exporting the conversion proc also does.

My work-around either ```nim proc selectOneToManyShunt(dbHandler) = ## this proc is never used and exists solely to please the compiler var arg = @[newPlayer()] dbHandler.dbConn.selectOneToMany(newLobby(), arg) ``` or right after imports ```nim export dbValue ```