diff options
author | Andreas Klebinger <klebinger.andreas@gmx.at> | 2021-02-21 16:04:20 +0100 |
---|---|---|
committer | Marge Bot <ben+marge-bot@smart-cactus.org> | 2021-02-26 16:27:26 -0500 |
commit | a9f23793126251844944e00bca8e84370c759aa7 (patch) | |
tree | 29122c4a7ce6aafcc41d3b070f70697289e2db97 /libraries/ghc-prim | |
parent | 24777bb334a49f6bd6c0df2d5ddb371f98436888 (diff) | |
download | haskell-a9f23793126251844944e00bca8e84370c759aa7.tar.gz |
Move absentError into ghc-prim.
When using -fdicts-strict we generate references to absentError while
compiling ghc-prim. However we always load ghc-prim before base so this
caused linker errors.
We simply solve this by moving absentError into ghc-prim. This does mean
it's now a panic instead of an exception which can no longer be caught.
But given that it should only be thrown if there is a compiler error
that seems acceptable, and in fact we already do this for
absentSumFieldError which has similar constraints.
Diffstat (limited to 'libraries/ghc-prim')
-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) |