Skip to content

chs: fix GHC 9.2+ prim ambiguity in c2hs-processed source files#86

Open
mgajda wants to merge 1 commit into
tmcdonell:masterfrom
mgajda:fix-ghc94-prim-guards
Open

chs: fix GHC 9.2+ prim ambiguity in c2hs-processed source files#86
mgajda wants to merge 1 commit into
tmcdonell:masterfrom
mgajda:fix-ghc94-prim-guards

Conversation

@mgajda
Copy link
Copy Markdown

@mgajda mgajda commented Apr 14, 2026

Branch: fix/ghc94-prim-guards
Commit: chs: fix GHC 9.2+ prim ambiguity in c2hs-processed source files


Building with GHC 9.2 or later fails with ambiguous occurrence errors:

src/Foreign/CUDA/Driver/Stream.chs:516:18: error:
    Ambiguous occurrence `wordToWord64#'
    It could refer to
       either `GHC.Base.wordToWord64#'
           or `Foreign.CUDA.Driver.Stream.wordToWord64#'

The .chs files guard local bridge definitions with #if __GLASGOW_HASKELL__ < N. c2hs processes .chs files with its own C preprocessor, in which __GLASGOW_HASKELL__ is undefined (evaluates to 0). The guard is therefore always TRUE, and the local definitions of wordToWord64#, word64ToWord#, and wordToWord8# are emitted unconditionally into the generated .hs output. GHC 9.2+ exports these same operations from GHC.Base/GHC.Exts, so the compiler sees a duplicate and correctly rejects it.

The fix changes bare guards of the form #if __GLASGOW_HASKELL__ < N to #if defined(__GLASGOW_HASKELL__) && __GLASGOW_HASKELL__ < N. Under c2hs, defined(__GLASGOW_HASKELL__) is FALSE so the local definition is stripped. GHC's own CPP pass sees a defined macro and evaluates the version check normally.

Affected: Driver/Stream.chs, Driver/Marshal.chs, Driver/Module/Query.chs.

Tested: c2hs 0.28.8, GHC 9.4.7, CUDA 12.0, Ubuntu 24.04.

c2hs processes .chs files with its own C preprocessor, in which
`__GLASGOW_HASKELL__` is not defined. Bare guards of the form

    #if __GLASGOW_HASKELL__ < N

therefore evaluate to `0 < N` (TRUE), so local bridge definitions of
`wordToWord64#`, `word64ToWord#`, and `wordToWord8#` are emitted
unconditionally into the generated .hs output.

GHC 9.2 added these operations to `GHC.Prim` / `GHC.Base` / `GHC.Exts`,
so on GHC 9.2+ the generated code contains a duplicate definition that
the compiler correctly rejects as ambiguous:

    Ambiguous occurrence `wordToWord64#'
    It could refer to either `GHC.Base.wordToWord64#'
                           or `Foreign.CUDA.Driver.Stream.wordToWord64#'

Fix: rewrite bare guards as

    #if defined(__GLASGOW_HASKELL__) && __GLASGOW_HASKELL__ < N

`defined(__GLASGOW_HASKELL__)` evaluates to FALSE under c2hs, suppressing
the local definition there. GHC's own CPP pass sees a defined macro and
evaluates the version comparison normally.

Affected files: Driver/Stream.chs, Driver/Marshal.chs, Driver/Module/Query.chs

Tested: c2hs 0.28.8, GHC 9.4.7 and 9.6.x, CUDA 12.0, Ubuntu 24.04.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant