Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions NEWS.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@

- New: mutate `NonZero<T>` into `1`, and also `-1` when `T` is or may be signed.

- New: `#[mutants::exclude_re("pattern")]` attribute to exclude specific mutations by regex, without disabling all mutations on the function. The attribute can be placed on functions, `impl` blocks, `trait` blocks, modules, and files. Multiple patterns can be applied. Also supported within `cfg_attr`.
- Fixed: Set the mtime on files copied using reflinks to the scratch directory, so that they're not deleted prematurely by tools that delete old files from `/tmp`.

## 27.0.0
Expand Down
56 changes: 56 additions & 0 deletions book/src/attrs.md
Original file line number Diff line number Diff line change
Expand Up @@ -49,3 +49,59 @@ mod test {
}
}
```

## Excluding specific mutations with an attribute

If `#[mutants::skip]` is too broad (it disables _all_ mutations on a function)
you can use `#[mutants::exclude_re("pattern")]` to exclude only mutations
whose name matches a regex, while keeping the rest.

The regex is matched against the full mutant name (the same string shown by
`cargo mutants --list`), using the same syntax as `--exclude-re` on the command
line.

For example, to keep all mutations on an `i32`-returning function except the
"replace ... -> i32 with 0" return-value mutation:

```rust
#[mutants::exclude_re("with 0")]
fn do_something(x: i32) -> i32 {
x + 1
}
```

Multiple attributes can be applied to exclude several patterns:

```rust
#[mutants::exclude_re("with 0")]
#[mutants::exclude_re("with 1")]
fn compute(a: i32, b: i32) -> i32 {
a + b
}
```

As with `mutants::skip`, cargo-mutants also looks for `mutants::exclude_re`
within other attributes such as `cfg_attr`, without evaluating the outer
attribute:

```rust
#[cfg_attr(test, mutants::exclude_re("replace .* -> bool"))]
fn is_valid(&self) -> bool {
// ...
true
}
```

### Scope

`#[mutants::exclude_re]` can be placed on:

- **Functions** — applies to all mutations within that function.
- **`impl` blocks** — applies to all methods within the block.
- **`trait` blocks** — applies to all default method implementations.
- **`mod` blocks** — applies to all items within the module.
- **Files** (as an inner attribute `#![mutants::exclude_re("...")]`) — applies to the entire file.

Patterns from outer scopes are inherited: if an `impl` block excludes a pattern,
all methods inside also exclude that pattern, in addition to any patterns on the
methods themselves.
2 changes: 1 addition & 1 deletion mutants_attrs/Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[package]
name = "mutants"
version = "0.0.4"
version = "0.0.5"
edition = "2018"
license = "MIT"
description = "Decorator attributes to be used with cargo-mutants"
Expand Down
22 changes: 22 additions & 0 deletions mutants_attrs/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -24,3 +24,25 @@ use proc_macro::TokenStream;
pub fn skip(_attr: TokenStream, item: TokenStream) -> TokenStream {
item
}

Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We ought to also bump the version of mutants_attrs/Cargo.toml.

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done in d0314a9 — bumped to 0.0.5. Happy to make it 0.1.0 instead if you'd prefer a more notable bump for the new public attribute.

/// Exclude specific mutations matching a regex pattern.
///
/// Unlike [macro@skip], which skips all mutations on a function, this attribute allows
/// you to exclude only mutations whose name matches the given regex, while keeping
/// other mutations active.
///
/// This can be applied to functions, impl blocks, trait blocks, modules, etc.
///
/// ```
/// #[mutants::exclude_re("delete match arm")]
/// pub fn some_function() -> i32 {
/// // ...
/// # 0
/// }
/// ```
///
/// This is a no-op during compilation, but is seen by cargo-mutants as it processes the source.
#[proc_macro_attribute]
pub fn exclude_re(_attr: TokenStream, item: TokenStream) -> TokenStream {
item
}
Loading