diff options
Diffstat (limited to 'compiler/prelude/primops.txt.pp')
-rw-r--r-- | compiler/prelude/primops.txt.pp | 45 |
1 files changed, 25 insertions, 20 deletions
diff --git a/compiler/prelude/primops.txt.pp b/compiler/prelude/primops.txt.pp index 7361c4bea8..685a867b0d 100644 --- a/compiler/prelude/primops.txt.pp +++ b/compiler/prelude/primops.txt.pp @@ -2595,20 +2595,23 @@ primop RaiseOp "raise#" GenPrimOp with strictness = { \ _arity -> mkClosedStrictSig [topDmd] botDiv } out_of_line = True - has_side_effects = True - -- raise# certainly throws a Haskell exception and hence has_side_effects - -- It doesn't actually make much difference because the fact that it - -- returns bottom independently ensures that we are careful not to discard - -- it. But still, it's better to say the Right Thing. + can_fail = True + -- In contrast to 'raiseIO#', which throws a *precise* exception, + -- exceptions thrown by 'raise#' are considered *imprecise*. + -- Hence 'raise#' is marked as "can_fail" (which 'raiseIO#' is not), but + -- not as "has_side_effects" (which 'raiseIO#' is). + -- See Note [PrimOp can_fail and has_side_effects] in PrimOp.hs. + -- For the same reasons, it has 'botDiv', not 'exnDiv'. -- Note [Arithmetic exception primops] -- ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -- --- The RTS provides several primops to raise specific exceptions (raiseDivZero#, --- raiseUnderflow#, raiseOverflow#). These primops are meant to be used by the --- package implementing arbitrary precision numbers (Natural,Integer). It can't --- depend on `base` package to raise exceptions in a normal way because it would --- create a package dependency circle (base <-> bignum package). +-- The RTS provides several primops to raise specific imprecise exceptions +-- (raiseDivZero#, raiseUnderflow#, raiseOverflow#). These primops are meant to +-- be used by the package implementing arbitrary precision numbers +-- (Natural,Integer). It can't depend on `base` package to raise exceptions in a +-- normal way because it would create a package dependency circle +-- (base <-> bignum package). -- -- See #14664 @@ -2646,25 +2649,27 @@ primop RaiseOverflowOp "raiseOverflow#" GenPrimOp -- raiseIO# needs to be a primop, because exceptions in the IO monad -- must be *precise* - we don't want the strictness analyser turning --- one kind of bottom into another, as it is allowed to do in pure code. +-- one kind of bottom into another, as it is allowed to do with imprecise +-- exceptions. For the same reason it doesn't return botRes, either. +-- +-- Take the following function as an example. It should *not* be strict in @y@, +-- because that would turn a precise into an imprecise exception for the call +-- site @f 1 (error "boom")@ (see #13380): -- --- But we *do* want to know that it returns bottom after --- being applied to two arguments, so that this function is strict in y -- f x y | x>0 = raiseIO blah -- | y>0 = return 1 -- | otherwise = return 2 -- --- TODO Check that the above notes on @f@ are valid. The function successfully --- produces an IO exception when compiled without optimization. If we analyze --- it as strict in @y@, won't we change that behavior under optimization? --- I thought the rule was that it was okay to replace one valid imprecise --- exception with another, but not to replace a precise exception with --- an imprecise one (dfeuer, 2017-03-05). +-- This is scenario 2 in Note [Precise exceptions and strictness analysis] in +-- Demand. For this reason, 'raiseIO#' should have @topDiv@, but that would +-- entail not being able to eliminate a lot of dead code. Hence it is the only +-- primitive to introduce @exnDiv@, which differs from @botDiv@ only in its +-- 'defaultDmd'. primop RaiseIOOp "raiseIO#" GenPrimOp a -> State# RealWorld -> (# State# RealWorld, b #) with - strictness = { \ _arity -> mkClosedStrictSig [topDmd, topDmd] botDiv } + strictness = { \ _arity -> mkClosedStrictSig [topDmd, topDmd] exnDiv } out_of_line = True has_side_effects = True |