summaryrefslogtreecommitdiff
path: root/libraries/ghc-prim/GHC/Prim/Panic.hs
diff options
context:
space:
mode:
Diffstat (limited to 'libraries/ghc-prim/GHC/Prim/Panic.hs')
-rw-r--r--libraries/ghc-prim/GHC/Prim/Panic.hs58
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)