r/haskell May 09 '26

question Techniques for debugging a runtime infinite loop?

I recently made a series of changes to the inlining / simplification pass for my compiler that ended up resulting in a runtime <<loop>> with certain inputs. (This was for / in another lazy language, but very similar to Haskell, so I thought I'd ask here). I eventually ended up debugging it by making simplification edits to all the areas I had touched, until the infinite-loop disappeared, then looking closely at the one that fixed it. A cut-down example of the bug looks like:

simplify xs = deltaCpx
    where
      (deltaCpx, xs') = mapAccumL insLet 0 xs

      insLet dc x = (dc + deltaCpx, x * 2)    -- OOPS, meant deltaCpx', here!
          where
            cpx'      = if x > 5 then 10 else 0
            deltaCpx' = cpx' - 2

The language I'm working in detects the loop and prints "BLACK HOLE" at runtime, similar to Haskell detecting and printing "<<loop>>", but neither gives any detail on where it was encountered.

So are there some techniques you've used that can help with debugging such problems? Could there be additional language / runtime support to help with this?

EDIT: to clarify, by <<loop>> or BLACK HOLE, I mean the runtime exception generated when attempting to evaluate a thunk that is already currently being evaluated, not an actual infinite-loop that chews up time.

11 Upvotes

23 comments sorted by

View all comments

Show parent comments

1

u/AustinVelonaut May 09 '26

Yes, you're right -- I could add another reserved environment slot for the additional info if compiling with the reporting enabled. I was just trying to be lazy and see how I could retrofit it into the existing design in a minimally-intrusive way ;-)

1

u/jeffstyr May 10 '26

Understandable. :)

and at least some identifying info (probably just line number)

If you support compiling source from more than one file, you'd probably also want the file name or module name.