[GHC] #9390: Inlining prevents evaluation of ignored parts of unboxed tuples

GHC ghc-devs at haskell.org
Wed Aug 6 09:49:49 UTC 2014


#9390: Inlining prevents evaluation of ignored parts of unboxed tuples
-------------------------------------+-------------------------------------
              Reporter:  snoyberg    |            Owner:
                  Type:  bug         |           Status:  new
              Priority:  normal      |        Milestone:  7.8.4
             Component:  Compiler    |          Version:  7.8.3
            Resolution:              |         Keywords:
      Operating System:  Linux       |     Architecture:  x86_64 (amd64)
       Type of failure:  Incorrect   |       Difficulty:  Unknown
  result at runtime                  |       Blocked By:
             Test Case:              |  Related Tickets:
              Blocking:              |
Differential Revisions:              |
-------------------------------------+-------------------------------------

Comment (by simonpj):

 The example in comment:2 is different in kind to the main one.  Considre
 {{{
   (unsafePerformIO (do { write arr 0 'A'; return 3 })
   +
   (unsafePerformIO (do { write arr 0 'B'; return 4 })
 }}}
 After you evaluate this, does `arr[0]` contain `'A'` or `'B'`?  Obviously
 it depends on the evaluation order of `(+)`.  GHC is, quite specifically,
 at liberty to change evaluation order -- notably the strictness analyser
 makes quite radical changes in evaluation order -- so you absolutely
 cannot rely on it.  Even if you say
 {{{
    a `seq` b `seq` d
 }}}
 you cannot rely on `a` being evaluated before `b`.

 In short:
  * GHC is tries never to ''discard'' exceptions, divergence, or write
 effects
  * but it is free to ''re-order'' them
 (See our paper "A semantics for imprecise exceptions" for lots of detail
 on this.)

 The only way to enforce sequencing of write effects is to us the data
 dependency of the state token.  By using `unsafePerformIO` you are
 specifically saying "I don't mind in what order these effects are
 performed relative to everything else.

 `unsafeInterleaveIO` lets you ensure that it occurs after the effects thus
 far in the do-block have occurred.  So this:
 {{{
 main = do
     vm <- VM.new 1
     VM.write vm 0 'A'
     !b<- return $! 'B'
     x <- unsafeInterleaveIO $! VM.write vm 0 b
     x `seq` (V.freeze vm >>= print)
 }}}
 always prints "B".

 These things are not obvious.  We have a good place for "collaborative
 documentation" of GHC, [http://www.haskell.org/haskellwiki/GHC here].
 Would any of you like to write an explanatory page there?

 Simon

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


More information about the ghc-tickets mailing list