What should and should not be marked has_side_effects?

David Feuer david at well-typed.com
Fri Mar 10 22:17:47 UTC 2017


Note [PrimOp can_fail and has_side_effects] in prelude/PrimOp.hs says

> A primop "has_side_effects" if it has some *write* effect, visible
> elsewhere
> 
>     - writing to the world (I/O)
>     - writing to a mutable data structure (writeIORef)
>     - throwing a synchronous Haskell exception
>
> [...]
>
>  * NB3: *Read* effects (like reading an IORef) don't count here,
>  
>    because it doesn't matter if we don't do them, or do them more than
>    once.  *Sequencing* is maintained by the data dependency of the state
>    token.

But this does not actually seem to match what goes on in primops.txt.pp. The 
following, among many other seemingly read-only operations, have  
has_side_effects = True:

readMutVar# (the very example cited!), readArray#, unsafeFreezeArray#, 
unsafeThawArray#, tryReadMVar#, deRefWeak#

So what's the correct story? Do we want to change the note, or change the 
reality? The reason I happen to be looking at this is that I think the current 
arrangement allows us to define unsafeInterleaveIO in a particularly simple 
fashion:

unsafeInterleaveIO = pure . unsafePerformIO

but that's only safe as long as the interleaved IO won't float out and get 
performed before it's forced by normal IO.

But the unsafeInterleaveIO story seems much less important, in the grand 
scheme of things, than making everything else run fast. If indeed it's 
otherwise safe to mark these read-only ops has_side_effects=False, then I 
imagine we probably should do that.

David Feuer


More information about the ghc-devs mailing list