39dc5032

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

Mutation: keep source text out of the MutationId so swap mutants activate

A MutationId renders and parses as '/'-separated parts (Test.Syd.Mutation.Runtime),
and its parts must contain no '/'. But recordMutationAt embedded the replacement
string (raw source text) as a part. A SwitchFunctionArguments swap of e.g.
'stripPrefix "/nix/store/" t' has replacement text 't "/nix/store/"', which
contains '/'. The compiled ifMutation carried that id intact, but the driver
renders the id into MUTATION_ACTIVE and the runtime parses it back by splitting
on '/': the '/' inside the replacement split into extra parts, so the parsed id
never equalled the compiled one and the mutation was never activated. The mutant
survived even though a test killed it, while same-site operators with a
'/'-free replacement (ConstNothing -> 'Nothing') were killed normally. The
coverage phase still recorded the (intact) id, so it showed up as 'survived',
not 'uncovered'.

Drop the replacement string from the id. The id is now the structural key
[module, operator, line, colStart, colEnd, altIndex]; none of those can contain
'/', and the index already disambiguates alternatives at one span (the
replacement text remains in the manifest's mutRecReplacement field for humans).
Update the two positional consumers of the id's arity (the instrumentation
debug line and Manifest.Render's '#n' variant suffix), regenerate the example
manifest goldens, and add Example.SwitchArgsLib.stripStorePrefix as a regression
test (a swap whose replacement contains '/').

Bump sydtest-mutation-plugin to 0.4.1.0 with a changelog entry.