REMOVE AND LIFT: Removes a sub-term from a term and attaches orphaned children to the parent
(such that types match). This only works if there is only a single child.
REPLACE-REUSE: Replaces a sub-term with a different sub-term which is part of the trace
(such that types match). The new sub-term could come from another step which has a different
recipe term.
Apply new_term in place of the term at to_mutate_path, generalising the replacement to
structurally equal terms according to a randomly drawn MutationScope.
Replace the term at each of targets (each currently structurally equal to representative) by
new_term, enforcing the result-size caps (constraints.max_result_{term,trace}_size) and,
when with_bit is set, the per-term payload budget
(constraints.threshold_max_payloads_per_term). If applying to all targets would exceed a cap,
the mutation is rejected wholesale (returns [MutationResult::Skipped]) so the “replace all
equal occurrences” atomicity is preserved. See replacement_within_caps and
payloads_within_caps.
Returns true iff replacing a term carrying representative_payloads payloads by one carrying
new_payloads, at every path in targets, keeps each affected step recipe within
constraints.threshold_max_payloads_per_term.
Returns true iff replacing a term of size representative_size by one of size new_size at
every path in targets keeps each affected single step recipe within
constraints.max_result_term_size.
Draw a MutationScope and return all the occurrences to replace, see
apply_scoped_mutation. The search is unbounded (finds every structurally-equal occurrence);
runaway is prevented at application time by the result-size caps in apply_to_targets, not
by cutting the search short.