Skip to content

Reduce Boolean Blindness

Motivation

There are many places in GHC's code base that are prone to boolean blindness. Here's BasicTypes.OccInfo, for example (this situation has been fixed in !2210 (closed), but I bet there are many other instances):


-- | identifier Occurrence Information
data OccInfo
  = ManyOccs        { occ_tail    :: !TailCallInfo }
  | IAmDead
  | OneOcc          { occ_in_lam  :: !InsideLam
                    , occ_one_br  :: !OneBranch
                    , occ_int_cxt :: !InterestingCxt
                    , occ_tail    :: !TailCallInfo }
                        -- ^ Occurs exactly once (per branch), not inside a rule

  -- | This identifier breaks a loop of mutually recursive functions. The field
  -- marks whether it is only a loop breaker due to a reference in a rule
  | IAmALoopBreaker { occ_rules_only :: !RulesOnly
                    , occ_tail       :: !TailCallInfo }

type RulesOnly = Bool

-- | Interesting Context
type InterestingCxt = Bool      -- True <=> Function: is applied
                                --          Data value: scrutinised by a case with
                                --                      at least one non-DEFAULT branch

-- | Inside Lambda
type InsideLam = Bool   -- True <=> Occurs inside a non-linear lambda
                        -- Substituting a redex for this occurrence is
                        -- dangerous because it might duplicate work.
insideLam, notInsideLam :: InsideLam
insideLam    = True
notInsideLam = False

type OneBranch = Bool   -- True <=> Occurs in only one case branch
                        --      so no code-duplication issue to worry about
oneBranch, notOneBranch :: OneBranch
oneBranch    = True
notOneBranch = False

data TailCallInfo = AlwaysTailCalled JoinArity -- See Note [TailCallInfo]
                  | NoTailCallInfo

Not only do booleans force us to repeat the same documentation all over the place, also we define bindings like oneBranch/notOneBranch anyway to make our lives easier.

Proposal

Simply define the proper ADTs, like we do for TailCallInfo (which notably gets by without any dead documentation) or TopLevelFlag. Provide a conversion function to Bool in cases where we want that.

Edited by Sebastian Graf
To upload designs, you'll need to enable LFS and have an admin enable hashed storage. More information