Skip to content

Simplifier ticks exhausted on mapM/traverse

Summary

GHC 8.8 and 8.10 runs into Simplifier ticks exhausted on a simple function running mapM over a bunch of instances of Gen from QuickCheck.

Steps to reproduce

  1. Compile the following code. It can cloned from here.

    module Test.Bonanza.Arbitrary where
    
    import Test.QuickCheck (Gen)
    
    genFields :: Gen [(String, Int)]
    genFields =
      mapM
        (\(f, g) -> (f,) <$> g)
        [ ("status", genIntField),
          ("body_bytes_sent", genIntField),
          ("http_referer", genIntField),
          ("http_user_agent", genIntField),
          ("http_x_forwarded_for", genIntField),
          ("separator", genIntField),
          ("connection", genIntField),
          ("request_time", genIntField),
          ("upstream_response_time", genIntField),
          ("upstream_cache_status", genIntField),
          ("user", genIntField),
          ("zconn", genIntField),
          ("request", genIntField),
          ("proxy_protocol_addr", genIntField)
        ]
    
    genIntField :: Gen Int
    genIntField = pure 0
  2. See this error:

    Simplifier ticks exhausted
      When trying UnfoldingDone w1_s1v5
      To increase the limit, use -fsimpl-tick-factor=N (default 100).
    
      If you need to increase the limit substantially, please file a
      bug report and indicate the factor you needed.
    
      If GHC was unable to complete compilation even with a very large factor
      (a thousand or more), please consult the "Known bugs or infelicities"
      section in the Users Guide before filing a report. There are a
      few situations unlikely to occur in practical programs for which
      simplifier non-termination has been judged acceptable.
    
      To see detailed counts use -ddump-simpl-stats
      Total ticks: 17534

Expected behavior

It should compile.

Other observations

As I know nothing of the GHC internals, I will drop a few things I observed:

  • If I replace the mapM with sequence $ map, the problem goes away. Replacing it with traverse does not fix the problem.
  • GHC 8.6.5 is able to compile this without any problems.
  • I copied code for Gen from QuickCheck into the module, the problem went away. However, the problem comes back If I put the code in a separate module and import it.
  • If I write a dummy implementation of Gen, the problem goes away.
  • If I replace Gen with IO, the problem goes away.

Environment

  • GHC version used: 8.8.4 and 8.10.2

Optional:

  • Operating System: Linux/Debian-unstable
  • System Architecture: amd64
To upload designs, you'll need to enable LFS and have an admin enable hashed storage. More information