diff options
Diffstat (limited to 'libraries/ghc-prim/GHC/Prim/Panic.hs')
-rw-r--r-- | libraries/ghc-prim/GHC/Prim/Panic.hs | 58 |
1 files changed, 58 insertions, 0 deletions
diff --git a/libraries/ghc-prim/GHC/Prim/Panic.hs b/libraries/ghc-prim/GHC/Prim/Panic.hs index 21ebc56a88..0aa07813c1 100644 --- a/libraries/ghc-prim/GHC/Prim/Panic.hs +++ b/libraries/ghc-prim/GHC/Prim/Panic.hs @@ -9,6 +9,7 @@ module GHC.Prim.Panic ( absentSumFieldError , panicError + , absentError ) where @@ -17,10 +18,56 @@ import GHC.Magic default () -- Double and Integer aren't available yet +{- +Note [Compiler error functions] +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +Most error functions (such as pattern match failure) are defined +in base:Control.Exception.Base. But absentError# and absentSumFieldError# +are defined here in the ghc-prim package for two reasons: + +* GHC itself generates calls to these functions as a result of + strictness analysis, over which the programmer has no control. So + it is hard to ensure that no such calls exist in the modules + compiled "before" Control.Base.Exception. (E.g. when compiling + with -fdicts-strict.) + +* A consequence of defining them in ghc-prim is that the libraries + defining exceptions have not yet been built, so we can't make them + into proper Haskell exceptions. + + However, if these functions are ever called, it's a /compiler/ error, + not a user error, so it seems acceptable that they cannot be caught. + +One might wonder why absentError doesn't just call panic#. +For absent error we want to combine two parts, one static, one call site +dependent into one error message. While for absentSumFieldError it's a +static string. + +The easiest way to combine the two parts for absentError is to use a +format string with `barf` in the RTS passing the *dynamic* part of the +error as argument. There is no need to do any of this for +absentSumFieldError as it's a static string there. + +The alternatives would be to: +* Drop the call site specific information from absentError. + The call site specific information is at times very helpful for debugging + so I don't consider this an option. +* Remove the common prefix. We would then need to include the prefix + in the call site specific string we pass to absentError. Increasing + code size for no good reason. + +Both of which seem worse than having an stg_absentError function specific to +absentError to me. +-} + -- `stg_panic#` never returns but it can't just return `State# RealWorld` so we -- indicate that it returns `(# #)` too to make the compiler happy. +-- See Note [Compiler error functions] foreign import prim "stg_paniczh" panic# :: Addr# -> State# RealWorld -> (# State# RealWorld, (# #) #) +-- See Note [Compiler error functions] +foreign import prim "stg_absentErrorzh" stg_absentError# :: Addr# -> State# RealWorld -> (# State# RealWorld, (# #) #) + -- | Display the CString whose address is given as an argument and exit. panicError :: Addr# -> a panicError errmsg = @@ -43,3 +90,14 @@ absentSumFieldError = panicError "entered absent sum field!"# -- introduced in Stg.Unarise, long after inlining has stopped, but it seems -- more direct simply to give it a NOINLINE pragma {-# NOINLINE absentSumFieldError #-} + +-- | Displays "Oops! Entered absent arg" ++ errormsg and exits the program. +{-# NOINLINE absentError #-} +absentError :: Addr# -> a +absentError errmsg = + runRW# (\s -> + case stg_absentError# errmsg s of + (# _, _ #) -> -- This bottom is unreachable but we can't + -- use an empty case lest the pattern match + -- checker squawks. + let x = x in x) |