Panic in `addCaseBndrDmd`
Summary
Depending on the particular version of GHC used, the compiler will panic when attempting to compile a valid Haskell program containing certain Exception
-related typecasts.
Steps to reproduce
Try to compile the following file with each of GHC versions 8.8.4, 8.10.7, 9.0.2, 9.2.3, 9.2.4 and 9.4.1 and observe that the compiler only avoids a panic when compiling with optimization -O0 or with GHC version 9.0.2 or 8.8.4. It is also worthwhile to note that uncommenting the {-# NOINLINE fromError #-}
pragma or changing the data declaration for UniquenessError
to a newtype
also prevents the panic.
{-# LANGUAGE ExistentialQuantification #-}
module Bug where
import Control.Exception
import Data.Typeable
data Error
= Error Int String
| forall e . Exception e => SomeError Int e
deriving (Typeable)
fromError :: Exception e => Error -> Maybe e
fromError e@(Error _ _) = cast e
fromError (SomeError _ e) = cast e
-- {-# NOINLINE fromError #-}
instance Eq Error where
Error i s == Error i' s' = i == i' && s == s'
SomeError i e == SomeError i' e' = i == i' && show e == show e'
_ == _ = False
instance Show Error where
show _ = ""
instance Exception Error
-- newtype
data
UniquenessError = UniquenessError [((String, String), Int)]
deriving (Show, Eq)
instance Exception UniquenessError
test :: SomeException -> IO ()
test e = case fromError =<< fromException e :: Maybe UniquenessError of
Just err -> print err
_ -> pure ()
The following zsh
script may be convenient to use and modify as a means of quickly reproducing the behavior, where "Bug.hs" is the expected filename of the above source code.
#!/usr/bin/env zsh
GHC_VERSIONS=('8.8.4' '8.10.7' '9.0.2' '9.2.4' '9.4.1')
OPTIMIZATION_LEVELS=('-O0' '-O1' '-O2')
for ghc_version in "${GHC_VERSIONS[@]}"; do
for optimization_level in "${OPTIMIZATION_LEVELS[@]}"; do
GHC=ghc-$ghc_version
printf "%s\n\n" "Compiling with GHC version $ghc_version using optimization level $optimization_level:"
$GHC -c $optimization_level Bug.hs
if [ $? -eq 0 ]; then
printf "SUCCESS\n\n"
rm Bug.hi Bug.o
else
printf "FAIL\n\n"
fi
done
done
Expected behavior
GHC should not panic in any of the above-mentioned scenarios, and it should accept the source as a valid program.
Panic Outputs
GHC 9.4.1:
ghc-9.4.1: panic! (the 'impossible' happened) GHC version 9.4.1: was a call demand !P(ML) [A, A] Call stack: CallStack (from HasCallStack): callStackDoc, called at compiler/GHC/Utils/Panic.hs:182:37 in ghc:GHC.Utils.Panic pprPanic, called at compiler/GHC/Core/Opt/DmdAnal.hs:587:5 in ghc:GHC.Core.Opt.DmdAnal
GHC 9.2.4:
Compiling with GHC version 9.2.4 using optimization level -O2: ghc: panic! (the 'impossible' happened) (GHC version 9.2.4: compiler/GHC/Types/Demand.hs:591:5-43: Non-exhaustive patterns in Just ds
GHC 8.10.7:
ghc: panic! (the 'impossible' happened) (GHC version 8.10.7: setBndrsDemandInfo [ds_d1Yv] Call stack: CallStack (from HasCallStack): callStackDoc, called at compiler/utils/Outputable.hs:1179:37 in ghc:Outputable pprPanic, called at compiler/stranal/DmdAnal.hs:964:28 in ghc:DmdAnal
Environment
- GHC version used: variously 8.10.7, 9.0.2, 9.2.3, 9.2.4 and 9.4.1 as described above
- The compiler panics for GHC versions 8.10.7, 9.2.4, and 9.4.1 and build success for GHC version 9.0.2 were reproduced on an M1 MacBook Air on macOS Monterey as well as on Ubuntu 20.04 running an Intel x86_64 processor.
- The above results were also reproduced for 8.10.7, 9.0.2, 9.2.3 and 9.4.1 using
nix-shell
environments.
Credits
This bug would not have been discovered and documented without the kind efforts of my FP Complete colleagues Neil Mayhew (https://gitlab.haskell.org/neil.mayhew), Phil de Joux (https://gitlab.haskell.org/philderbeast) and Grant Weyburne. Grant did some initial work to suspect that the proprietary code we were working with failed when doing some problematic typecasts, and Neil managed to figure out how to reduce the proprietary code sample that was causing the panic into a completely non-proprietary, reproducible test case using fairly standard Haskell code. Phil did additional testing using GHC 9.2.4 built from source as well as with a GHC 9.4.1 version from GHCup.