Skip to content

WIP: Clear up PrimOp effect semantics

Sebastian Graf requested to merge wip/primop-traits into master

Previously we classified PrimOps with two boolean flags, can_fail and has_side_effects. Although there is quite a slew of documentation surrounding them, see Note [PrimOp can_fail and has_side_effects] and Note [Transformations affected by can_fail and has_side_effects], I found it quite hard to understand and also was confused of conservative misclassifications for some read-only primops like readMutVar# (which is marked as has_side_effect, although it actually shouldn't per semantics of has_side_effect, see #3207 (closed)), but not for others (indexIntArr#, which is just can_fail).

This patch defines a total order of 5 different PrimOpEffects:

  • NoEffect: A pure primop
  • ThrowsImprecise: Possibly throws an imprecise exception (and may perform read effects)
  • WriteEffect: May write to a mutable ref cell, array or the world (or read from them or throw an imprecise exception)
  • ThrowsPrecise: May throw a precise exception, or do any of the aforementioned effects.

Each effect is strictly "stronger" than its predecessor in this list wrt. to program transformation that are sound to apply to it. For example, we may speculatively execute read effects (as long as their data dependencies such as the state token are satisfied), but we may not speculate division (for fear of imprecise division-by-zero errors).

Which PrimOpEffect inhibits which transformation, including examples, is spelled out in the rewritten Note [Transformations affected by PrimOpEffect].

Fixes #17900 (closed).

Edited by Sebastian Graf

Merge request reports