f97a1209

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

Mutation: skip-calls-to for ConstConstructor

A function whose result is always the same constructor makes every call to it
an equivalent mutant: replacing the call with that constructor cannot change
anything, so no test can kill it.  A delegating

  instance PersistFieldSql RepoType where
    sqlType Proxy = sqlType (Proxy :: Proxy Text)

is the shape that keeps coming up, sqlType answering with a constant of its
type by definition.

Deciding that from the compiler is out of reach here in a way the Map.empty
case was not.  The head of that expression is the class-method selector, not
the instance's method, so there is no unfolding to read: it would take walking
the typechecker's evidence to the PersistFieldSql Text dictionary, pulling its
DFunUnfolding, indexing out the method and beta-reducing the selector against
it -- a Core evaluator inside a typechecker plugin, silently doing nothing
whenever any link in that chain is missing.

So this is config, as it already is for the other two operators whose
equivalent mutants come from a semantic property: symmetry for
SwitchFunctionArguments, identity for ElideCall.  Same key, same name matching
(bare or qualified, by defining module or by import module).  A surviving
mutation on a call now carries a mitigation naming the key, so the report
points at it.

The key skips calls, not definitions: the body of a listed function stays
under mutation testing, which the example pins.

Total

1m49s

Created Started Finished

Time to Start Worker time Duration Time to finish Idle
Config 0s 1s 1s 1s 0s
Eval 1s 35s 35s 37s 0s
Build 36s 24s 20s 56s 0s
Deploy 1m37s 11s 11s 1m49s 40s
Suite 0s 1m14s 1m49s 1m49s 41s

Timeline

Config Eval Build Deploy Compressed gap
0s10s20s30s40s50s1m40s