Simplifier wrongly discards erroring function call
Steps to reproduce
Compile with optimisations and run the following module:
{-# LANGUAGE GHC2021, UnboxedTuples #-}
module Main (main) where
newtype Tricky = TrickyCon { unTrickyCon :: (# #) -> Tricky }
main :: IO ()
main = do
let
tricky :: Tricky
{-# OPAQUE tricky #-}
tricky = TrickyCon $ \(# #) -> TrickyCon $ \(# #) ->
error "tricky called with at least two args"
applyToN :: Int -> Tricky -> Tricky
{-# OPAQUE applyToN #-}
applyToN n a | n == 0 = a
| otherwise = applyToN (n - 1) a `unTrickyCon` (# #)
case applyToN 12345 tricky of
!_ -> putStrLn "unreachable"
The function tricky
is applied to far more than two args, so the error call in its body should be reached. But when run, the program prints "unreachable" and exits successfully instead of failing with "tricky called with at least two args". (This wrong behavior persists even with -O -fpedantic-bottoms -fno-state-hack
.)
Inspecting the -ddump-simpl
and -dverbose-core2core
output suggests the simplifier is eliminating the applyToN
stuff entirely.
Environment
- GHC version used: 9.8.1