summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorViktor Dukhovni <ietf-dane@dukhovni.org>2021-08-17 17:16:39 -0400
committerMarge Bot <ben+marge-bot@smart-cactus.org>2021-08-19 01:19:29 -0400
commitcad5a14122cae276a4964e17acd4d2cceb19f01e (patch)
treeea90090d4be9fd00af122b876eeb9bc069703ee9
parent4a10f0ff487c6effee125bedca095a80f68045b7 (diff)
downloadhaskell-cad5a14122cae276a4964e17acd4d2cceb19f01e.tar.gz
Fix missing can_fail annotation on two CAS primops
Also note why has_side_effects is needed with reads of mutable data, using text provided by Simon Peyton-Jones.
-rw-r--r--compiler/GHC/Builtin/PrimOps.hs32
-rw-r--r--compiler/GHC/Builtin/primops.txt.pp2
2 files changed, 24 insertions, 10 deletions
diff --git a/compiler/GHC/Builtin/PrimOps.hs b/compiler/GHC/Builtin/PrimOps.hs
index 1fa8b02bb7..9bfed53382 100644
--- a/compiler/GHC/Builtin/PrimOps.hs
+++ b/compiler/GHC/Builtin/PrimOps.hs
@@ -331,16 +331,18 @@ Both can_fail and has_side_effects mean that the primop has
some effect that is not captured entirely by its result value.
---------- has_side_effects ---------------------
-A primop "has_side_effects" if it has some *write* effect, visible
-elsewhere
- - writing to the world (I/O)
- - writing to a mutable data structure (writeIORef)
+A primop "has_side_effects" if it has some side effect, visible
+elsewhere, apart from the result it returns
+ - reading or writing to the world (I/O)
+ - reading or writing to a mutable data structure (writeIORef)
- throwing a synchronous Haskell exception
Often such primops have a type like
State -> input -> (State, output)
-so the state token guarantees ordering. In general we rely *only* on
-data dependencies of the state token to enforce write-effect ordering
+so the state token guarantees ordering. In general we rely on
+data dependencies of the state token to enforce write-effect ordering,
+but as the notes below make clear, the matter is a bit more complicated
+than that.
* NB1: if you inline unsafePerformIO, you may end up with
side-effecting ops whose 'state' output is discarded.
@@ -353,10 +355,20 @@ data dependencies of the state token to enforce write-effect ordering
"can_fail". We must be careful about not discarding such things;
see the paper "A semantics for imprecise exceptions".
- * NB3: *Read* effects (like reading an IORef) don't count here,
- because it doesn't matter if we don't do them, or do them more than
- once. *Sequencing* is maintained by the data dependency of the state
- token.
+ * NB3: *Read* effects on *mutable* cells (like reading an IORef or a
+ MutableArray#) /are/ included. You may find this surprising because it
+ doesn't matter if we don't do them, or do them more than once. *Sequencing*
+ is maintained by the data dependency of the state token. But see
+ "Duplication" below under
+ Note [Transformations affected by can_fail and has_side_effects]
+
+ Note that read operations on *immutable* values (like indexArray#) do not
+ have has_side_effects. (They might be marked can_fail, however, because
+ you might index out of bounds.)
+
+ Using has_side_effects in this way is a bit of a blunt instrument. We could
+ be more refined by splitting read and write effects (see comments with #3207
+ and #20195)
---------- can_fail ----------------------------
A primop "can_fail" if it can fail with an *unchecked* exception on
diff --git a/compiler/GHC/Builtin/primops.txt.pp b/compiler/GHC/Builtin/primops.txt.pp
index b07c344e18..ec729ac450 100644
--- a/compiler/GHC/Builtin/primops.txt.pp
+++ b/compiler/GHC/Builtin/primops.txt.pp
@@ -1532,6 +1532,7 @@ primop CasArrayOp "casArray#" GenPrimOp
with
out_of_line = True
has_side_effects = True
+ can_fail = True -- Might index out of bounds
------------------------------------------------------------------------
@@ -1710,6 +1711,7 @@ primop CasSmallArrayOp "casSmallArray#" GenPrimOp
with
out_of_line = True
has_side_effects = True
+ can_fail = True -- Might index out of bounds
------------------------------------------------------------------------
section "Byte Arrays"