3f1df5f6

By: Tom Sydney Kerckhove <syd@cs-syd.eu>

Fix `ignore` filter leaking through `$` and ExpandedThingTc

Two bugs prevented the plugin's `ignore` config from working in practice:

1. `nix/addManifest.nix` passed the YAML config via `--ghc-options=...`
   (plural).  Cabal treats that as a space-separated multi-flag and the
   value's embedded `=` and `:` confused the parser, so the plugin was
   invoked with no opts and `ignore` always stayed at `[]`.  Switch to
   `--ghc-option=...` (singular) so the whole `-fplugin-opt=...` token
   reaches GHC intact.

2. Once the config is actually loaded, `opOccName` still failed to see
   through GHC 9.6+ expansions: `mark $ unwords [...]` is a
   `XExpr (ExpandedThingTc _ (HsApp (HsApp ($) mark) (unwords [...])))`,
   and `opOccName` returned `Nothing` for it.  The ignore filter then
   fell through to children and mutated the inner list literal.  Walk
   through `ExpandedThingTc`, and treat `($) f x` as having syntactic
   head `f` rather than `$`.

Regression test in `sydtest-mutation-example/src/Example/IgnoreLib.hs`:
`mark` is a two-argument no-op with a polymorphic payload (introduces
typecheck `WrapExpr` wrappers), called both directly and via `$`; the
golden `Example.IgnoreLib.json` asserts no mutations are produced.
`mutationManifestCheck.nix` now passes `./mutation.yaml` so the golden
actually exercises the `ignore` machinery.

Suite timing

Time to Start Worker time Duration Time to finish Idle
Config 0s 2s 2s 2s 0s
Eval 2s 30s 30s 33s 0s
Build 22s 12s 10s 33s 0s
Suite 0s 45s 33s 33s 0s

Timeline

0s10s20s30s