Skip to content

Commit

Permalink
std/dynlib: fix loadLibPatterns having unknown effects (nim-lang#1237)
Browse files Browse the repository at this point in the history
## Summary

The `loadLibPatterns` procedure was erroneously inferred to have
unknown effects (`RootEffect`), making it unusable in `.tags: []`
procedures. This is now fixed.

## Details

`loadLibPatterns` calls the at-that-point forwarded procedure
`loadLib`, so effect inference falls back to assume that
`loadLibPatterns` can have effects.

Since `loadLib`, as well as the other forward-declared procedures,
don't have effects in practice, this is now explicitly specified
on the forward declarations.
  • Loading branch information
zerbina authored Mar 13, 2024
1 parent a4a32d5 commit 5fd1189
Show file tree
Hide file tree
Showing 2 changed files with 27 additions and 4 deletions.
10 changes: 6 additions & 4 deletions lib/pure/dynlib.nim
Original file line number Diff line number Diff line change
Expand Up @@ -48,22 +48,24 @@ import std/strutils
type
LibHandle* = pointer ## A handle to a dynamically loaded library.

proc loadLib*(path: string, globalSymbols = false): LibHandle {.gcsafe.}
{.pragma: noeffects, gcsafe, raises: [], tags: [].}

proc loadLib*(path: string, globalSymbols = false): LibHandle {.noeffects.}
## Loads a library from `path`. Returns nil if the library could not
## be loaded.

proc loadLib*(): LibHandle {.gcsafe.}
proc loadLib*(): LibHandle {.noeffects.}
## Gets the handle from the current executable. Returns nil if the
## library could not be loaded.

proc unloadLib*(lib: LibHandle) {.gcsafe.}
proc unloadLib*(lib: LibHandle) {.noeffects.}
## Unloads the library `lib`.

proc raiseInvalidLibrary*(name: cstring) {.noinline, noreturn.} =
## Raises a `LibraryError` exception.
raise newException(LibraryError, "could not find symbol: " & $name)

proc symAddr*(lib: LibHandle, name: cstring): pointer {.gcsafe.}
proc symAddr*(lib: LibHandle, name: cstring): pointer {.noeffects.}
## Retrieves the address of a procedure/variable from `lib`. Returns nil
## if the symbol could not be found.

Expand Down
21 changes: 21 additions & 0 deletions tests/stdlib/tdynlib.nim
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
discard """
targets: c
action: compile
"""

import std/dynlib

# ensure that the dynlib procedures are GC safe and don't have effects
proc dynlibProcsHaveNoEffects1() {.gcsafe, raises: [], tags: [].} =
discard loadLib("")
discard loadLib()
unloadLib(nil)
discard symAddr(nil, nil)

var candidates: seq[string]
libCandidates("", candidates)

discard loadLibPattern("")

proc dynlibProcsHaveNoEffects2() {.gcsafe, tags: [].} =
discard checkedSymAddr(nil, nil)

0 comments on commit 5fd1189

Please sign in to comment.