[GHC] #8926: GHC makes unsound references in object code

GHC ghc-devs at haskell.org
Mon Mar 24 23:12:50 UTC 2014


#8926: GHC makes unsound references in object code
----------------------------+----------------------------------------------
       Reporter:            |             Owner:
  anton.dubovik             |            Status:  new
           Type:  bug       |         Milestone:
       Priority:  normal    |           Version:  7.6.3
      Component:  Compiler  |  Operating System:  Unknown/Multiple
       Keywords:            |   Type of failure:  GHC rejects valid program
   Architecture:            |         Test Case:
  Unknown/Multiple          |          Blocking:
     Difficulty:  Unknown   |
     Blocked By:            |
Related Tickets:            |
----------------------------+----------------------------------------------
 To reproduce the bug run script `run.sh` from the attached archive.

 It will:

 1. install `FooPackage`

   {{{
   Resolving dependencies...
   Configuring FooPackage-0.1...
   Building FooPackage-0.1...
   Preprocessing library FooPackage-0.1...
   [1 of 1] Compiling FooPackage       ( src\FooPackage.hs,
 dist\build\FooPackage.o )
   In-place registering FooPackage-0.1...
   Installing library in
   C:\Users\Anton\AppData\Roaming\cabal\i386-windows-
 ghc-7.6.3\FooPackage-0.1
   Registering FooPackage-0.1...
   Installed FooPackage-0.1
   }}}

 2. compile executable `Client1` which depends on `FooPackage`

   {{{
   [1 of 3] Compiling QuxClient        ( QuxClient.hs, obj\QuxClient.o )
   [2 of 3] Compiling BarClient        ( BarClient.hs, obj\BarClient.o )
   [3 of 3] Compiling Client1          ( Client1.hs, obj\Client1.o )
   Linking exes/Client1.exe ...
   }}}

 3. compile executable `Client2` which doesn't depend on `FooPackage`

   At the third step GHC will fall with linker error:

   {{{
   [2 of 2] Compiling Client2          ( Client2.hs, obj\Client2.o )
   Linking exes/Client2.exe ...
   obj\BarClient.o:fake:(.text+0x83): undefined reference to
 `FooPackagezm0zi1_FooPackage_zdsinsertzuzdsgo5_info'
   obj\BarClient.o:fake:(.data+0x10): undefined reference to
 `FooPackagezm0zi1_FooPackage_zdsinsertzuzdsgo5_closure'
   collect2: ld returned 1 exit status
   }}}

 Both `Client1` and `Client2` import `BarClient` module that doesn't
 depends on `FooPackage`.
 `Client1` imports `QuxClient` that imports `FooPackage`:

 {{{
 module QuxClient where

 import FooPackage(foo)

 import Data.Set

 qux :: Set String -> Set String
 qux = foo
 }}}

 {{{
 module BarClient where

 import Data.Set

 bar :: Set String -> Set String
 bar s = insert "bar" s
 }}}

 `FooPackage` uses function `Data.Set.insert` which is marked at `Data.Set`
 as `INLINABLE`:

 {{{
 module FooPackage where

 import Data.Set

 foo :: Set String -> Set String
 foo s = insert "foo" s
 }}}

 GHC emphasizes in interface file, that `FooPackage.o` contains specialized
 version of `Data.Set.insert`:

 {{{
 > ghc --show-iface FooPackage.hi
 ...
 "SPEC Data.Set.Base.insert [GHC.Base.String]" [ALWAYS] forall $dOrd ::
 GHC.Classes.Ord
 GHC.Base.String
   Data.Set.Base.insert @ [GHC.Types.Char] $dOrd = FooPackage.$sinsert
 ...
 }}}

 Later GHC see again the use of `Data.Set.insert at String` at `BarClient` and
 decides to apply this specialise rule, so that `BarClient` now has
 reference to `FooPackage`:

 {{{
 >  ghc --show-iface BarClient.hi
 ...
   bar :: Data.Set.Base.Set GHC.Base.String
          -> Data.Set.Base.Set GHC.Base.String
     {- Arity: 1, Strictness: S,
        Unfolding: (\ s :: Data.Set.Base.Set GHC.Base.String ->
                    FooPackage.$sinsert_$sgo5 BarClient.bar1 s) -}
 ...
 }}}

 `Client2` doesn't depend on `FooPackage`, thus linker throws an error.

 There are plenty of workarounds here, but all of them are ad hoc (1,2,3)
 or could affect performance (4):
 1. Change the order of `BarClient` and `QuxClient` imports in `Client1`
 module.
 2. Compile `Client1` and `Client2` in opposite order.
 3. Add fake import at `Client2` module:
    {{{
    import FooPackage()
    }}}
 4. Build `FooPackage` with ghc-option `-fomit-interface-pragmas`. That
 will eraise from `FooPackage.hi` all specialisation rules as well as
 information about strictness and inlining.

 Some information about the environment:
 {{{
 > ghc-pkg list
 ...
   containers-0.5.0.0
   base-4.6.0.1
 ...
 > ghc --version
 The Glorious Glasgow Haskell Compilation System, version 7.6.3
 > cabal --version
 cabal-install version 1.18.0.3
 using version 1.18.1.3 of the Cabal library
 }}}

--
Ticket URL: <http://ghc.haskell.org/trac/ghc/ticket/8926>
GHC <http://www.haskell.org/ghc/>
The Glasgow Haskell Compiler


More information about the ghc-tickets mailing list