Nim icon indicating copy to clipboard operation
Nim copied to clipboard

Invoking generic procedure that uses varargs implicit conversion acts incorrectly

Open SolitudeSF opened this issue 6 years ago • 3 comments

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

SolitudeSF avatar May 01 '19 17:05 SolitudeSF

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

disruptek avatar May 01 '19 18:05 disruptek

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)

krux02 avatar May 01 '19 19:05 krux02

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 ). I import this module and call this generic proc with my own generic proc:

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

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

export dbValue

maxtidev avatar May 07 '24 12:05 maxtidev