Skip to content

GitLab

  • Menu
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 4,866
    • Issues 4,866
    • List
    • Boards
    • Service Desk
    • Milestones
    • Iterations
  • Merge requests 455
    • Merge requests 455
  • 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 Compiler
  • GHCGHC
  • Issues
  • #17442
Closed
Open
Created Nov 06, 2019 by Ryan Scott@RyanGlScottMaintainer

GHC HEAD-only panic (emitPrimOp: handled above in cgOpApp)

I noticed this issue originally as deriving-compat-0.5.7's test suite fails to compile on HEAD. Here is a minimized version of the test suite that compiles successfully with optimizations on GHC 8.8.1 and earlier:

{-# LANGUAGE MagicHash #-}
{-# LANGUAGE TypeFamilies #-}
module Bug where

import Control.Monad
import GHC.Arr (Ix(..))
import GHC.Base (getTag)
import GHC.Exts

data family D
data instance D = MkD
  deriving (Eq, Ord, Show)

instance Ix D where
  range (a, b) =
    let a# = getTag a
        b# = getTag b
    in map (\(I# i#) -> tagToEnum# i# :: D)
           (enumFromTo (I# a#) (I# b#))
  unsafeIndex (a, _) c =
    let a# = getTag a
        c# = getTag c
        d# = c# -# a#
    in I# d#
  inRange (a, b) c =
    let a# = getTag a
        b# = getTag b
        c# = getTag c
    in tagToEnum# (c# >=# a#) && tagToEnum# (c# <=# b#)

shouldBe :: (Eq a, Show a) => a -> a -> IO ()
shouldBe x y =
  unless (x == y) $ fail $ show x ++ " is not equal to " ++ show y

ixLaws :: (Ix a, Show a) => a -> a -> a -> IO ()
ixLaws l u i = do
    inRange (l,u) i                 `shouldBe` elem i (range (l,u))
    range (l,u) !! index (l,u) i    `shouldBe` i
    map (index (l,u)) (range (l,u)) `shouldBe` [0..rangeSize (l,u)-1]
    rangeSize (l,u)                 `shouldBe` length (range (l,u))

dIsLawfulIx :: IO ()
dIsLawfulIx = ixLaws MkD MkD MkD

However, it panics on GHC HEAD:

$ ~/Software/ghc5/inplace/bin/ghc-stage2 Bug.hs -O -fforce-recomp
[1 of 1] Compiling Bug              ( Bug.hs, Bug.o )
ghc-stage2: panic! (the 'impossible' happened)
  (GHC version 8.9.0.20191023:
        emitPrimOp: handled above in cgOpApp

Some notes:

  • The use of optimization -O is critical to triggering the bug.

  • The panic goes away if D is an ordinary data type instead of a data family.

  • The code in the hand-written Ix instance is very similar to the code you would get for a derived Ix instance, but with one key difference: the hand-written code uses getTag instead of a function that does something like this:

    dTag :: D -> Int#
    dTag MkD = 0#

    If you replace all uses of getTag with dTag, then the panic goes away. As a consequence, you won't trigger the panic if you derive the Ix instance.

Edited Nov 06, 2019 by Ryan Scott
To upload designs, you'll need to enable LFS and have an admin enable hashed storage. More information
Assignee
Assign to
Time tracking