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 3s 3s 3s 0s
Eval 3s 32s 32s 36s 0s
Build 9s 35s 22s 31s 0s
Suite 0s 1m11s 36s 36s 0s

Timeline

0s10s20s30s