[GHC] #12875: GHC fails to link all StaticPointers-defining modules of a library in an executable

#12875: GHC fails to link all StaticPointers-defining modules of a library in an executable -------------------------------------+------------------------------------- Reporter: bgamari | Owner: Type: bug | Status: new Priority: normal | Milestone: 8.2.1 Component: Compiler | Version: 8.0.1 Keywords: | Operating System: Unknown/Multiple StaticPointers | Architecture: | Type of failure: None/Unknown Unknown/Multiple | Test Case: | Blocked By: Blocking: | Related Tickets: Differential Rev(s): | Wiki Page: -------------------------------------+------------------------------------- Consider that you have a package called `lib` which exposes these modules, {{{#!hs module ALib.Types where data AThing = AThing String deriving (Show) {-# LANGUAGE StaticPointers #-} module ALib.Things where import GHC.StaticPtr import ALib.Types thing1 :: StaticPtr AThing thing1 = static (AThing "hello") }}} Now consider that you have a server which reads a `StaticKey` of `StaticPtr AThing` and shows it, {{{#!hs import ALib.Types main :: IO () main = do key <- readFingerprint <$> getContents :: IO StaticKey Just thing <- unsafeLookupStaticPtr key :: IO (Maybe (StaticPtr AThing)) print $ deRefStaticPtr thing }}} Naturally this executable will link against `lib`. However, this executable as-written will fail if given the key of `ALib.Things.thing1`. Fixing this requires that the executable explicitly import and use a definition from `ALib.Things`. The problem appears to be that the linker elides the `ALib.Things` object from the final executable unless it refers to a symbol. Note that things also work fine if the server executable is dynamically linked. -- Ticket URL: http://ghc.haskell.org/trac/ghc/ticket/12875 GHC http://www.haskell.org/ghc/ The Glasgow Haskell Compiler

#12875: GHC fails to link all StaticPointers-defining modules of a library in an executable -------------------------------------+------------------------------------- Reporter: bgamari | Owner: Type: bug | Status: new Priority: normal | Milestone: 8.2.1 Component: Compiler | Version: 8.0.1 Resolution: | Keywords: | StaticPointers Operating System: Unknown/Multiple | Architecture: | Unknown/Multiple Type of failure: None/Unknown | Test Case: Blocked By: | Blocking: Related Tickets: | Differential Rev(s): Wiki Page: | -------------------------------------+------------------------------------- @@ -7,0 +7,1 @@ + New description: Consider that you have a package called `lib` which exposes these modules, {{{#!hs module ALib.Types where data AThing = AThing String deriving (Show) {-# LANGUAGE StaticPointers #-} module ALib.Things where import GHC.StaticPtr import ALib.Types thing1 :: StaticPtr AThing thing1 = static (AThing "hello") }}} Now consider that you have a server which reads a `StaticKey` of `StaticPtr AThing` and shows it, {{{#!hs import ALib.Types main :: IO () main = do key <- readFingerprint <$> getContents :: IO StaticKey Just thing <- unsafeLookupStaticPtr key :: IO (Maybe (StaticPtr AThing)) print $ deRefStaticPtr thing }}} Naturally this executable will link against `lib`. However, this executable as-written will fail if given the key of `ALib.Things.thing1`. Fixing this requires that the executable explicitly import and use a definition from `ALib.Things`. The problem appears to be that the linker elides the `ALib.Things` object from the final executable unless it refers to a symbol. Note that things also work fine if the server executable is dynamically linked. -- Comment (by bgamari): See https://github.com/bgamari/T12875-repro for a functional example of this. -- Ticket URL: http://ghc.haskell.org/trac/ghc/ticket/12875#comment:1 GHC http://www.haskell.org/ghc/ The Glasgow Haskell Compiler

#12875: GHC fails to link all StaticPointers-defining modules of a library in an executable -------------------------------------+------------------------------------- Reporter: bgamari | Owner: Type: bug | Status: new Priority: normal | Milestone: 8.2.1 Component: Compiler | Version: 8.0.1 Resolution: | Keywords: | StaticPointers Operating System: Unknown/Multiple | Architecture: | Unknown/Multiple Type of failure: None/Unknown | Test Case: Blocked By: | Blocking: Related Tickets: | Differential Rev(s): Wiki Page: | -------------------------------------+------------------------------------- Changes (by bgamari): * cc: dcoutts (added) -- Ticket URL: http://ghc.haskell.org/trac/ghc/ticket/12875#comment:2 GHC http://www.haskell.org/ghc/ The Glasgow Haskell Compiler

#12875: GHC fails to link all StaticPointers-defining modules of a library in an executable -------------------------------------+------------------------------------- Reporter: bgamari | Owner: Type: bug | Status: new Priority: normal | Milestone: 8.2.1 Component: Compiler | Version: 8.0.1 Resolution: | Keywords: | StaticPointers Operating System: Unknown/Multiple | Architecture: | Unknown/Multiple Type of failure: None/Unknown | Test Case: Blocked By: | Blocking: Related Tickets: | Differential Rev(s): Wiki Page: | -------------------------------------+------------------------------------- Comment (by facundo.dominguez): Perhaps it is possible to stop the linker from removing modules from the final executable when they use the `StaticPointers` language extension. That failing, the simplest solution could be to document that the module defining static pointers needs to be imported transitively into the main module of an executable supposed to find them. -- Ticket URL: http://ghc.haskell.org/trac/ghc/ticket/12875#comment:3 GHC http://www.haskell.org/ghc/ The Glasgow Haskell Compiler

#12875: GHC fails to link all StaticPointers-defining modules of a library in an executable -------------------------------------+------------------------------------- Reporter: bgamari | Owner: Type: bug | Status: new Priority: normal | Milestone: 8.2.1 Component: Compiler | Version: 8.0.1 Resolution: | Keywords: | StaticPointers Operating System: Unknown/Multiple | Architecture: | Unknown/Multiple Type of failure: None/Unknown | Test Case: Blocked By: | Blocking: Related Tickets: | Differential Rev(s): Wiki Page: | -------------------------------------+------------------------------------- Comment (by mboes):
That failing, the simplest solution could be to document that the module defining static pointers needs to be imported transitively into the main module of an executable supposed to find them.
That solution would be as anti-modular as non StaticPtr remote tables. Losing modularity would defeat much of the purpose of this language extension. Surely we can let the linker know that downstream modules *might* depend on `ALib.Things`? -- Ticket URL: http://ghc.haskell.org/trac/ghc/ticket/12875#comment:4 GHC http://www.haskell.org/ghc/ The Glasgow Haskell Compiler

#12875: GHC fails to link all StaticPointers-defining modules of a library in an executable -------------------------------------+------------------------------------- Reporter: bgamari | Owner: Type: bug | Status: new Priority: normal | Milestone: 8.2.1 Component: Compiler | Version: 8.0.1 Resolution: | Keywords: | StaticPointers Operating System: Unknown/Multiple | Architecture: | Unknown/Multiple Type of failure: None/Unknown | Test Case: Blocked By: | Blocking: Related Tickets: | Differential Rev(s): Wiki Page: | -------------------------------------+------------------------------------- Comment (by simonpj): Can you explain a bit more what the problem is? In the description what is `things1`? In general if a Haskell process deserialises, say from a network message, the key of a static pointer, there is no guarantee that it'll be in its SPT. Also I don't understand the API. What's unsafe about looking up a static pointer? Surely we shouldn't be exposing low-level details like fingerprints? -- Ticket URL: http://ghc.haskell.org/trac/ghc/ticket/12875#comment:5 GHC http://www.haskell.org/ghc/ The Glasgow Haskell Compiler

Also I don't understand the API. What's unsafe about looking up a static
#12875: GHC fails to link all StaticPointers-defining modules of a library in an executable -------------------------------------+------------------------------------- Reporter: bgamari | Owner: Type: bug | Status: new Priority: normal | Milestone: 8.2.1 Component: Compiler | Version: 8.0.1 Resolution: | Keywords: | StaticPointers Operating System: Unknown/Multiple | Architecture: | Unknown/Multiple Type of failure: None/Unknown | Test Case: Blocked By: | Blocking: Related Tickets: | Differential Rev(s): Wiki Page: | -------------------------------------+------------------------------------- Comment (by mboes): pointer? Surely we shouldn't be exposing low-level details like fingerprints? I think both of these points were already discussed in previous tickets (but I don't have pointers handy right now). The only lookup operation we have right now is one that doesn't check that you're looking up at the right type. That's because we don't yet store in the SPT what the type of the pointer really should be. As for fingerprints: an alternative is to expose {{{ serializeStaticPtr :: ... => StaticPtr a -> ByteString unserializeStaticPtr :: ... => ByteString -> StaticPtr a }}} As discussed, not a viable API, because then `base` depends on `bytestring`. That API would have the compiler make more assumptions than it needs to. With the current API the user has the freedom to serialize/deserialize in whatever way she wants (including e.g. integers created by a perfect hash function). IOW we try to bake into the compiler as little as possible, leaving the rest to implementation choices in "userland" libraries. -- Ticket URL: http://ghc.haskell.org/trac/ghc/ticket/12875#comment:6 GHC http://www.haskell.org/ghc/ The Glasgow Haskell Compiler
participants (1)
-
GHC