408b473d

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

Make a mutation-disable annotation that disables nothing an error

A disable annotation could keep claiming to suppress a mutation long after the
code stopped producing one. Only a DisableMutationsFor whose target named no
local binding was caught; every other way for a disable to go stale was silent.

The rule is that removing the annotation would not change the manifest, and it
is decided by measuring: the annotated scope is walked a second time with only
that annotation's disables lifted, and the operators that fire in that walk are
exactly the ones it suppresses. Reading the verdict off the same walk that
fills the manifest is what stops it drifting as the ignore list, per-operator
skip-calls-to keys, splice filtering and the dropping of non-desugaring mutants
change, since any of those can be why an operator produces nothing.

This covers a module, a binding, and a binding's local bindings. An annotation
naming something that is not an operator says so and lists the operators; one
naming Control says that a control is only inserted where an operator fires, so
naming it among operators takes nothing away; and a DisableMutation-prefixed
string that parses as none of the recognised forms is an error rather than
being ignored. A string that does not begin with DisableMutation is still left
alone, because ANN payloads are a shared mechanism and dekking marks functions
with "nocover" through the same one.

Measuring costs a second walk of the annotated scope, paid only where an
annotation is. For a module-level disable that means walking the module and
throwing the result away, so a module whose instrumentation misbehaves belongs
in the exceptions config key, which is answered before any walk happens.

Run against nix-ci's 617 annotations this found 52 that disabled nothing, each
either superseded by a config key added later, obsoleted by a plugin
improvement, or redundant with a broader annotation on the same binding.

Also fixes the debug setting, which was read into the instrumentation
environment and never consulted, so every instrumented build printed a line per
mutation whether or not it asked to. The measuring walk needs that print
silenced, and the field it had to consult was dead.

Total

5m19s

Created Started Finished

Time to Start Worker time Duration Time to finish Idle
Config 5s 0s 0s 6s 5s
Eval 1m46s 18s 18s 2m05s 1m39s
Build 2m04s 0s 3m20s 5m25s 3m20s
Suite 5s 19s 5m19s 5m25s 5m05s

Timeline

Config Eval Build Compressed gap
0s1m50s2m