Document and test all scopes where #[mutants::skip] applies#617
Merged
sourcefrog merged 1 commit intoMay 27, 2026
Merged
Conversation
`#[mutants::skip]` is honoured at every scope where the visitor checks
attributes — not just on `fn` declarations. The book's "Skipping
functions with an attribute" section, and the surrounding explanatory
text, implied otherwise; the only explicit test coverage of the attribute
was on top-level functions, impl methods, trait default methods, and
modules (via testdata trees), leaving every other supported scope
unexercised.
This commit clarifies the docs and locks in the behaviour with unit
tests for every previously-uncovered scope:
- file inner attribute `#![mutants::skip]`
- `#[mutants::skip] impl Foo { ... }` on the impl block itself
- `#[mutants::skip] trait Foo { ... }` on the trait declaration itself
- expression-level skip on call, method-call, match, struct literal,
and unary expressions
- `#[cfg_attr(test, mutants::skip)]` at non-fn scopes (impl, mod)
Skip on a binary expression is intentionally not tested: syn absorbs
a leading attribute into the leftmost operand, so `ExprBinary.attrs`
is unreachable from any current Rust syntax (same constraint that
applies to `mutants::exclude_re`).
The book's Skip section is rewritten to drop the fn-only framing and
adds a Scope subsection listing every supported placement.
No behaviour change.
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
38b77f7 to
5ee6053
Compare
Contributor
There was a problem hiding this comment.
Pull request overview
Documentation and test-only PR that pins down the existing behavior of #[mutants::skip]: the attribute is honoured by the visitor at every scope where attributes are inspected, not only on fn items. The book chapter is rewritten to reflect this, and per-scope unit tests are added under src/visit/test/ for previously-uncovered scopes.
Changes:
- Rewrite
book/src/attrs.mdto talk about "items" instead of "functions", clarify the two recognised forms (direct and nested incfg_attr), correct the note aboutcfg_attr(condition is not evaluated), and add a "Scope" subsection enumerating supported placements. - Add nine new unit-test files (file inner attr, impl block, trait block, call/method-call/match/struct/unary expression attrs, and
cfg_attr(...)on impl block and module) wired into the existingmod testinsrc/visit.rs. - Add a NEWS entry noting that only docs and tests changed.
Reviewed changes
Copilot reviewed 12 out of 12 changed files in this pull request and generated no comments.
Show a summary per file
| File | Description |
|---|---|
book/src/attrs.md |
Rewrites title/wording from functions to items, fixes inaccurate note about cfg_attr evaluation, adds Scope section listing all supported placements. |
NEWS.md |
Adds an unreleased entry describing the doc clarification. |
src/visit.rs |
Declares nine new submodules under the existing mod test to host the new unit tests. |
src/visit/test/skip_attr_file.rs |
Asserts #![mutants::skip] as file inner attribute suppresses all mutants. |
src/visit/test/skip_attr_impl.rs |
Asserts #[mutants::skip] on an impl block suppresses every method. |
src/visit/test/skip_attr_trait.rs |
Asserts #[mutants::skip] on a trait declaration suppresses default-method mutants. |
src/visit/test/skip_attr_expr_call.rs |
Asserts the attribute on a call expression suppresses nested arg mutants, sibling call unaffected. |
src/visit/test/skip_attr_expr_method_call.rs |
Same as above for method-call expressions. |
src/visit/test/skip_attr_expr_match.rs |
Asserts the attribute on a match suppresses both arm-deletion and guard-replacement mutants. |
src/visit/test/skip_attr_expr_struct.rs |
Asserts the attribute on a struct literal suppresses field-deletion mutants. |
src/visit/test/skip_attr_expr_unary.rs |
Asserts the attribute on a unary expression suppresses only that specific delete ! mutant. |
src/visit/test/skip_attr_cfg_attr.rs |
Asserts #[cfg_attr(test, mutants::skip)] is honoured at non-fn scopes (impl block and mod). |
💡 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.
#[mutants::skip]is honoured at every scope where the visitor checks attributes — not just onfndeclarations. The book's Skipping functions with an attribute section implied otherwise, and explicit test coverage of the attribute only exercised top-level functions, impl methods, trait default methods, and modules (via testdata trees), leaving every other supported scope unexercised.This PR locks in the current behaviour and clarifies the docs. No production code changes — only documentation and added tests.
Tests added
New unit tests under
src/visit/test/for every previously-uncovered scope:#![mutants::skip]— file inner attribute#[mutants::skip] impl Foo { ... }— on the impl block itself#[mutants::skip] trait Foo { ... }— on the trait declaration itself#[cfg_attr(test, mutants::skip)]at non-fn scopes (impl, mod)Skip on a binary expression is intentionally not tested: syn absorbs a leading attribute into the leftmost operand, so
ExprBinary.attrsis unreachable from any current Rust syntax.Docs
book/src/attrs.md:functions→items.#[mutants::skip]or nested insidecfg_attr); drop the misleading avoid the dependency sentence (thecfg_attr(test, ...)form still needs the crate as a dev-dependency, since the attr expands undercfg(test)).Noteto accurately describe the cfg-condition-not-evaluated behaviour rather than the previous looks for the sequence framing.