Honor #[mutants::skip] on const and static items#622
Open
sandersaares wants to merge 1 commit into
Open
Conversation
Previously, #[mutants::skip] (and #[cfg_attr(..., mutants::skip)]) placed on a const or static item was silently ignored: the visitor walked into the initializer expression and generated the usual operator mutants. Add visit_item_const, visit_item_static, visit_impl_item_const, and visit_trait_item_const to DiscoveryVisitor. Each bails out when the item's attrs match attrs_excluded, suppressing all mutants inside the initializer; otherwise it delegates to the default syn::visit recursion so behavior for unskipped items is unchanged. This addresses sourcefrog#508. Generating fresh "replace value" mutants for the constant itself (kpreid's follow-up suggestion) is a separate, larger feature and is not included here. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
e1c096d to
7a2cb01
Compare
Contributor
There was a problem hiding this comment.
Pull request overview
This pull request fixes an attribute-handling gap in the mutation discovery visitor so that #[mutants::skip] (including #[cfg_attr(..., mutants::skip)]) is honored on const and static items, preventing mutants from being generated inside their initializer expressions.
Changes:
- Added
Visitoverrides inDiscoveryVisitorforItemConst,ItemStatic,ImplItemConst, andTraitItemConstto early-return whenattrs_excluded(&i.attrs)matches. - Added targeted tests ensuring skipped const/static initializers don’t produce operator mutants while unskipped siblings still do.
- Updated documentation and changelog to reflect the newly supported skip scope.
Reviewed changes
Copilot reviewed 7 out of 7 changed files in this pull request and generated no comments.
Show a summary per file
| File | Description |
|---|---|
src/visit.rs |
Adds visitor hooks for const/static items (including associated consts) to honor #[mutants::skip] before descending into initializer/default expressions. |
src/visit/test/skip_attr_item_const.rs |
Tests skipping top-level const initializers, including cfg_attr(..., mutants::skip). |
src/visit/test/skip_attr_item_static.rs |
Tests skipping top-level static initializers. |
src/visit/test/skip_attr_impl_item_const.rs |
Tests skipping associated const initializers inside impl blocks. |
src/visit/test/skip_attr_trait_item_const.rs |
Tests skipping associated const defaults inside trait blocks. |
book/src/attrs.md |
Documents that skip applies to const/static initializer expressions (including associated consts). |
NEWS.md |
Adds an Unreleased changelog entry describing the fix and linking to #508. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Fixes #508.
Problem
#[mutants::skip](and#[cfg_attr(..., mutants::skip)]) placed on aconstorstaticitem was silently ignored. TheDiscoveryVisitorinsrc/visit.rshad novisit_item_const/visit_item_static/visit_impl_item_const/visit_trait_item_const, sosyn's default visitor walked straight into the initializer expression and produced the usual operator mutants without consulting the item's attributes.Reproduced before the fix:
Fix
Added four visitor methods to
DiscoveryVisitorthat bail out viaattrs_excluded(&i.attrs)when the item carries a skip attribute, and otherwise delegate to the defaultsyn::visit::visit_*recursion. Behavior for unskipped consts/statics is unchanged.The attribute is now honoured on:
const FOO: T = ...;static FOO: T = ...;constinsideimplblocksconstdefaults insidetraitblocksBoth
#[mutants::skip]and#[cfg_attr(..., mutants::skip)]work, via the existingattrs_excludedhelper.Tests
Five new tests under
src/visit/test/following the existingskip_attr_impl.rspattern:skip_attr_item_const.rs— covers#[mutants::skip]and#[cfg_attr(test, mutants::skip)]on a top-levelconstskip_attr_item_static.rs— coversstaticskip_attr_impl_item_const.rs— covers associatedconstinimplskip_attr_trait_item_const.rs— covers associatedconstdefault intraitEach test puts a distinct operator on the skipped item (
^) and on the unskipped sibling (|), then asserts onMutant::original_text()rather than line numbers, so reformatting the indoc block cannot turn the assertions into silent passes.Documentation
book/src/attrs.md: added a Scope bullet forconst/staticitems.NEWS.md: added an Unreleased entry describing the fix.Out of scope
Generating fresh "replace value" mutants for const initializers (per @kpreid's follow-up on the issue) would need a new mutation genre and is a separate, larger feature.
Validation
cargo fmt --checkpassescargo clippy --all-targets --all-features -- -D warningspassescargo nextest run --all-features --no-fail-fast: 401/402 pass (the one failure,symlink_in_source_tree_is_copied, is a pre-existing Windows symlink-privilege issue unrelated to this change)#[mutants::skip]and#[cfg_attr(..., mutants::skip)]while unskipped items continue to produce mutants as before.