Skip to content
GitLab
Projects Groups Snippets
  • /
  • Help
    • Help
    • Support
    • Community forum
    • Submit feedback
  • Sign in / Register
  • GHC GHC
  • Project information
    • Project information
    • Activity
    • Labels
    • Members
  • Repository
    • Repository
    • Files
    • Commits
    • Branches
    • Tags
    • Contributors
    • Graph
    • Compare
    • Locked Files
  • Issues 5,241
    • Issues 5,241
    • List
    • Boards
    • Service Desk
    • Milestones
    • Iterations
  • Merge requests 563
    • Merge requests 563
  • CI/CD
    • CI/CD
    • Pipelines
    • Jobs
    • Schedules
    • Test Cases
  • Deployments
    • Deployments
    • Releases
  • Analytics
    • Analytics
    • Value stream
    • CI/CD
    • Code review
    • Insights
    • Issue
    • Repository
  • Wiki
    • Wiki
  • Snippets
    • Snippets
  • Activity
  • Graph
  • Create a new issue
  • Jobs
  • Commits
  • Issue Boards
Collapse sidebar
  • Glasgow Haskell CompilerGlasgow Haskell Compiler
  • GHCGHC
  • Issues
  • #17676
Closed
Open
Issue created Jan 13, 2020 by Sebastian Graf@sgraf812Developer

IO hack in demand analysis should apply in more situations

Consider

{-# LANGUAGE ScopedTypeVariables #-}
import Data.IORef
import Control.Exception
import Control.Monad

data Exc = Exc deriving Show

instance Exception Exc

-- Recursive instead of NOINLINE because of #17673
f :: Int -> Int -> IO ()
f 0 x = do
  let true = sum [0..4] == 10
  when true $ throwIO Exc
  x `seq` return ()
f n x = f (n-1) (x+1)

main = f 1 (error "expensive computation") `catch` \(_ :: Exc) -> return ()

GHC will change its semantics from exiting normally to crashing when compiled with optimisations:

$ ghc -O0 io.hs
<compilation output>
$ ./io
$ ghc -O2 io.hs
<compilation output>
$ ./io
io: expensive computation
CallStack (from HasCallStack):
  error, called at io.hs:18:13 in main:Main

This is because we are turning a precise exception (throwing Exc) into an imprecise one (forcing the bottom in x), the very thing we aim to avoid by applying the IO hack.

So, clearly not (isPrimOpId f) is unsound. Checking for exprOkForSideEffects would be sound, but is too imprecise (#17653 (closed)) because we also use it to make sure state threads are used linearly by read-only operations (#3207 (closed)).

Edit: While implementing !2525 (closed) I realised that it's not really a problem that not (isPrimOpId f) is unsound, because raiseIO# will never occur in a case scrutinee after simplification. There's !2956 (closed) which fixes this ticket.

Edited Mar 26, 2020 by Sebastian Graf
To upload designs, you'll need to enable LFS and have an admin enable hashed storage. More information
Assignee
Assign to
Time tracking