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,255
    • Issues 5,255
    • List
    • Boards
    • Service Desk
    • Milestones
    • Iterations
  • Merge requests 562
    • Merge requests 562
  • 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
  • #19413
Closed
Open
Issue created Feb 21, 2021 by Neil Mitchell@ndmitchellReporter

unsafePerformIO/NOINLINE tricks no longer work

Summary

Starting with GHC 9.0.1, the following program:

{-# OPTIONS_GHC -O1 #-}

import System.IO.Unsafe
import Data.IORef

{-# NOINLINE resourceId #-}
resourceId :: IO Int
resourceId = unsafePerformIO counter

counter :: IO (IO Int)
counter = do
    ref <- newIORef 0
    pure $ atomicModifyIORef' ref $ \i -> let j = i + 1 in (j, j)

main = do
    print =<< resourceId
    print =<< resourceId

Has gone from printing 1 then 2, to printing 1 then 1.

Whether it's a bug or GHC just getting better at optimisation is debatable. It definitely breaks code that works with 8.10, but I appreciate that with unsafePerformIO that isn't evidence of anything. I'm raising a bug after looking at the core, which seems like it might be broken.

Steps to reproduce

Using GHC 9.0:

$ ghc --make Test.hs
$ ./Test
1
1

Expected behaviour

1
2

Environment

GHC 9.0.1. Reproduced on Windows, but happens on Linux/Mac CI machines too.

Core output

The reason I raised this as a bug is after looking at the output of -ddump-simpl, available at https://gist.github.com/ndmitchell/a45d1db2eea8f8b2ee207e5d29475fce#file-core-hs-L67. Approximately, I think it has done the equivalent of:

resourceId = runRW $ \rw1 rw2 -> <all the work>

Namely, it pushed the creation of the IORef inside the inner IO, which I don't believe is allowed.

To upload designs, you'll need to enable LFS and have an admin enable hashed storage. More information
Assignee
Assign to
Time tracking