Admin message

Due to a large amount of spam we do not allow new users to create repositories, they are "external" users. If you are a new user and want to create a repository, for example for forking GHC, open a new issue on ghc/ghc using the "get-verified" issue template

Compilation time increases quadratically with the number of statements in a do-block
## Summary `hspec-discover` combines a list of test modules into a single *test driver*, e.g.: ```haskell import qualified FooSpec import qualified Foo.BarSpec import qualified BazSpec main :: IO () main = hspec $ do describe "Foo" FooSpec.spec describe "Foo.Bar" Foo.BarSpec.spec describe "Baz" BazSpec.spec ``` If you have hundreds or even thousands of test modules, compiling the test driver becomes very slow ([corresponding Hspec issue](https://github.com/hspec/hspec/issues/952#issue-3960276745)). Specifically, GHC compilation time increases quadratically with the number of test modules. ## Steps to reproduce The issue can be reproduced with a single test module and a test driver that "includes" the test module multiple times. Given a test module ```haskell -- test/FooSpec.hs module FooSpec where import Test.Hspec {-# OPAQUE spec #-} spec :: Spec spec = do it "should be true" $ do True `shouldBe` True ``` and a test driver ```haskell -- test/Spec.hs module Main (main) where import qualified FooSpec import Test.Hspec main :: IO () main = hspec spec spec :: Spec spec = do FooSpec.spec ... FooSpec.spec ``` that uses the test module `n` times, compilation time grows quadratically with `n`. Reproducer: https://github.com/sol/hspec-discover-performance-issue ## Expected behavior Things I've tried: - Adding `{-# OPTIONS_GHC -O0 #-}` to the test driver decreases compilation time by a constant factor, but it still stays quadratic in regards to `n`. - Adding `{-# OPTIONS_GHC -fignore-interface-pragmas #-}` to the test driver does not have any effect (I assume this is because `-fignore-interface-pragmas` only changes how interface files are read, but at this point the interface file for `FooSpec` has already been read). - Adding `-fignore-interface-pragmas` to the `.cabal` solves the issue, giving logarithmic compilation time. From what I understand: - GHC spends most of the compilation time on "simplifying" things and *code generation*. - If I compile the test drive with `-O0` then the "simplifying" part doesn't change, but code generation goes down to ~0s. - Once I enable `-fignore-interface-pragmas` globally "simplifying" goes down to ~0s. At this point it doesn't matter whether I use `-O0` or `-O1` because (I assume) without the "simplifying" there's no code blow up and hence nothing the optimizer could chew on. Marking definition as `NOINLINE` or `OPAQUE` doesn't seem to help at all. Questions: - If I compile a test drive with `-O0`, for what reason does "simplifying" still take a long time? Is there a way of telling GHC to stop doing that for a single module? - What's the reason that that `NOINLINE` or `OPAQUE` seemingly don't help? - Is there a way to work around this issue somehow without requiring every user to enable `-fignore-interface-pragmas`? Ideally, I would wanna address this in `hspec-discover` by generating code that doesn't blow up. ## Environment * GHC version used: 9.14.1
issue