packages feed

st2 0.1.0.0 → 0.1.0.1

raw patch · 3 files changed

+66/−6 lines, 3 files

Files

ChangeLog.md view
@@ -1,5 +1,10 @@ # Revision history for st2 -## 0.1.0.0 -- YYYY-mm-dd+## 0.1.0.1 -- 2018-11-02++* Fix internal bug that could cause semantic differences under optimisations,+  related to implementation of runRegion#.++## 0.1.0.0 -- 2018-07-23  * First version. Released on an unsuspecting world.
src/Control/Monad/ST2.hs view
@@ -102,11 +102,12 @@ import           Data.Semigroup (Semigroup((<>))) import           GHC.IO (IO(IO),unsafeDupableInterleaveIO) import           GHC.MVar (readMVar, putMVar, newEmptyMVar)-import           GHC.Prim (State#, realWorld#, unsafeCoerce#, MutVar#, newMutVar#, readMutVar#, writeMutVar#, sameMutVar#, RealWorld, noDuplicate#)+import           GHC.Prim (State#, unsafeCoerce#, MutVar#, newMutVar#, readMutVar#, writeMutVar#, sameMutVar#, RealWorld, noDuplicate#) import           GHC.Show (Show(showsPrec, showList), showString, showList__) import           GHC.Types (RuntimeRep, TYPE, Any, isTrue#) import           Theory.Named (type (~~)) import           Unsafe.Coerce (unsafeCoerce)+import qualified GHC.Magic as GHCMagic  -- | Convert an ST2 to an ST toBaseST :: ST s a -> BaseST.ST s a@@ -119,7 +120,7 @@ fromBaseST = unsafeCoerce  -- The state-transformer monad proper.  By default the monad is strict;--- too many people got bitten by space leaks when it was lazy.+-- too many people got bit by space leaks when it was lazy.  -- | The strict state-transformer monad. -- A computation of type @'ST' s a@ transforms an internal state indexed@@ -390,9 +391,64 @@  runRegion# :: forall (r :: RuntimeRep) (o :: TYPE r) s.            (State# (Any ~~ s) -> o) -> o-runRegion# m = m (rwToAny# realWorld#)+runRegion# m = GHCMagic.runRW# (unsafeCoerce# m) -- m = m (rwToAny# realWorld#) {-# INLINE runRegion# #-} +{- Note [runRegion#]+   ~~~~~~~~~~~~~~~~~+Originally, `runRegion#` was defined quite similarly to runRW#:+  runRegion# :: forall (r :: RuntimeRep) (o :: TYPE r) s.+    (State# (Any ~~ s) -> o) -> o+  runRegion# m = m (rwToAny# realWorld#)++But this definition is extremely brittle under optimisations! You should never+define a function that performs as `runRW#` does without defining it in _terms_+of `runRW#`. You can get semantically undesirable floating - runRW# is treated+specially by Core and inlined only very late in compilation, after floating is+complete. Below, I will inline "Note [runRW magic]" which is written in ghc's+compiler/coreSyn/CorePrep.hs:++Some definitions, for instance @runST@, must have careful control over float out                     +of the bindings in their body. Consider this use of @runST@,                                         +                                                                                                     +    f x = runST ( \ s -> let (a, s')  = newArray# 100 [] s                                           +                             (_, s'') = fill_in_array_or_something a x s'                            +                         in freezeArray# a s'' )                                                     +                                                                                                     +If we inline @runST@, we'll get:                                                                     +                                                                                                     +    f x = let (a, s')  = newArray# 100 [] realWorld#{-NB-}                                           +              (_, s'') = fill_in_array_or_something a x s'                                           +          in freezeArray# a s''                                                                      +                                                                                                     +And now if we allow the @newArray#@ binding to float out to become a CAF,                            +we end up with a result that is totally and utterly wrong:                                           +                                                                                                     +    f = let (a, s')  = newArray# 100 [] realWorld#{-NB-} -- YIKES!!!                                 +        in \ x ->                                                                                    +            let (_, s'') = fill_in_array_or_something a x s'                                         +            in freezeArray# a s''                                                                    +                                                                                                     +All calls to @f@ will share a {\em single} array! Clearly this is nonsense and                       +must be prevented.                                                                                   +                                                                                                     +This is what @runRW#@ gives us: by being inlined extremely late in the                               +optimization (right before lowering to STG, in CorePrep), we can ensure that                         +no further floating will occur. This allows us to safely inline things like                          +@runST@, which are otherwise needlessly expensive (see #10678 and #5916).                            +                                                                                                     +'runRW' is defined (for historical reasons) in GHC.Magic, with a NOINLINE                            +pragma.  It is levity-polymorphic.                                                                   +                                                                                                     +    runRW# :: forall (r1 :: RuntimeRep). (o :: TYPE r)                                               +           => (State# RealWorld -> (# State# RealWorld, o #))                                        +                              -> (# State# RealWorld, o #)                                           +                                                                                                     +It needs no special treatment in GHC except this special inlining+in CorePrep (and in ByteCodeGen). ++-}+ rwToAny# :: forall s s'. State# s' -> State# (Any ~~ s) rwToAny# x# = unsafeCoerce# x# {-# INLINE rwToAny# #-}@@ -415,4 +471,3 @@ repFromAny# :: STRep (Any ~~ s) a -> (State# s -> (# State# s, a #)) repFromAny# = unsafeCoerce# {-# INLINE repFromAny# #-}-
st2.cabal view
@@ -1,5 +1,5 @@ name:                st2-version:             0.1.0.0+version:             0.1.0.1 synopsis:            shared heap regions between local mutable state threads description:   This library implements the ST2 monad, a type using GDP (ghosts of departed proofs)