`needless_late_init`: ignore `if let`, `let mut` and significant drops
No longer lints `if let`, personal taste on this one is pretty split, so it probably shouldn't be warning by default. Fixes#8613
```rust
let x = if let Some(n) = y {
n
} else {
1
}
```
No longer lints `let mut`, things like the following are not uncommon and look fine as they are
b169c16d86/src/sixty_four.rs (L88-L93)
Avoids changing the drop order in an observable way, where the type of `x` has a drop with side effects and something between `x` and the first use also does, e.g.
48cc6cb791/tests/test_api.rs (L159-L167)
The implementation of `type_needs_ordered_drop_inner` was changed a bit, it now uses `Ty::has_significant_drop` and reordered the ifs to check diagnostic name before checking the implicit drop impl
changelog: [`needless_late_init`]: No longer lints `if let` statements, `let mut` bindings and no longer significantly changes drop order
mistyped_literal_suffix: improve integer suggestions, avoid wrong float suggestions
This PR fixes 2 things:
- The known problem that integer types are always suggested as signed, by suggesting an unsigned suffix for literals that wouldnt fit in the signed type, and ignores any literals too big for the corresponding unsigned type too.
- The lint would only look at the integer part of any floating point literals without an exponent, this causing #6129. This just ignores those literals.
Examples:
```rust
let _ = 2_32; // still 2_i32
let _ = 234_8; // would now suggest 234_u8
// these are now ignored
let _ = 500_8;
let _ = 123_32.123;
```
changelog: suggest correct integer types in [`mistyped_literal_suffix`], ignore float literals without an exponent
fixes#6129
Previously this lint would only look at the integer part of floating
point literals without an exponent, giving wrong suggestions like:
```
|
8 | let _ = 123_32.123;
| ^^^^^^^^^^ help: did you mean to write: `123.123_f32`
|
```
Instead, it now ignores these literals.
Fixes#6129
Instead of just always suggesting signed suffixes regardless of size
of the value, it now suggests an unsigned suffix when the value wouldn't
fit into the corresponding signed type, and ignores the literal entirely
if it is too big for the unsigned type as well.
wrong_self_convention allows `is_*` to take `&mut self`
fix#8480 and #8513
Allowing `is_*` to take `&self` or none is too restrictive.
changelog: FPs: [`wrong_self_convention`] now allows `&mut self` and no self as arguments for `is_*` methods
`manual_split_once`: lint manual iteration of `SplitN`
changelog: `manual_split_once`: lint manual iteration of `SplitN`
Now lints:
```rust
let mut iter = "a.b.c".splitn(2, '.');
let first = iter.next().unwrap();
let second = iter.next().unwrap();
let mut iter = "a.b.c".splitn(2, '.');
let first = iter.next()?;
let second = iter.next()?;
let mut iter = "a.b.c".rsplitn(2, '.');
let first = iter.next().unwrap();
let second = iter.next().unwrap();
let mut iter = "a.b.c".rsplitn(2, '.');
let first = iter.next()?;
let second = iter.next()?;
```
It suggests (minus leftover whitespace):
```rust
let (first, second) = "a.b.c".split_once('.').unwrap();
let (first, second) = "a.b.c".split_once('.')?;
let (second, first) = "a.b.c".rsplit_once('.').unwrap();
let (second, first) = "a.b.c".rsplit_once('.')?;
```
Currently only lints if the statements are next to each other, as detecting the various kinds of shadowing was tricky, so the following won't lint
```rust
let mut iter = "a.b.c".splitn(2, '.');
let something_else = 1;
let first = iter.next()?;
let second = iter.next()?;
```
Less authoritative stable_sort_primitive message
fixes#8241
Hey all - first contribution here so I'm deciding to start with something small.
Updated the linked message to be less authoritative as well as moved the lint grouping from `perf` to `pedantic` as suggested by `@camsteffen` under the issue.
changelog: [`stable_sort_primitive`]: emit less authoritative message and move to `pedantic`
Fix needless_match false positive for if-let when the else block doesn't match to given expr
<!--
Thank you for making Clippy better!
We're collecting our changelog from pull request descriptions.
If your PR only includes internal changes, you can just write
`changelog: none`. Otherwise, please write a short comment
explaining your change. Also, it's helpful for us that
the lint name is put into brackets `[]` and backticks `` ` ` ``,
e.g. ``[`lint_name`]``.
If your PR fixes an issue, you can add "fixes #issue_number" into this
PR description. This way the issue will be automatically closed when
your PR is merged.
If you added a new lint, here's a checklist for things that will be
checked during review or continuous integration.
- \[ ] Followed [lint naming conventions][lint_naming]
- \[ ] Added passing UI tests (including committed `.stderr` file)
- \[x] `cargo test` passes locally
- \[x] Executed `cargo dev update_lints`
- \[ ] Added lint documentation
- \[x] Run `cargo dev fmt`
[lint_naming]: https://rust-lang.github.io/rfcs/0344-conventions-galore.html#lints
Note that you can skip the above if you are just opening a WIP PR in
order to get feedback.
Delete this line and everything above before opening your PR.
--->
fix#8695
*Please write a short comment explaining your change (or "none" for internal only changes)*
changelog: Fixed ``[`needless_match`]`` false positive when else block expression differs.
Take over: New lint bytes count to len
take over #8375close#8083
This PR adds new lint about considering replacing `.bytes().count()` with `.len()`.
Thank you in advance.
---
r! `@Manishearth`
changelog: adds new lint [`bytes_count_to_len`] to consider replacing `.bytes().count()` with `.len()`
adding test patterns
cargo dev bless
fix comment
add ;
delete :
fix suggestion code
and update stderr in tests.
use match_def_path when checking method name
Add `await_holding_invalid_type` lint
changelog: [`await_holding_invalid_type`]
This lint allows users to create a denylist of types which are not allowed to be
held across await points. This is essentially a re-implementation of the
language-level [`must_not_suspend`
lint](https://github.com/rust-lang/rust/issues/83310). That lint has a lot of
work still to be done before it will reach Rust stable, and in the meantime
there are a lot of types which can trip up developers if they are used
improperly.
I originally implemented this specifically for `tracing::span::Entered`, until I discovered #8434 and read the commentary on that PR. Given this implementation is fully user configurable, doesn't tie clippy to any one particular crate, and introduces no additional dependencies, it seems more appropriate.
Report undeclared lifetimes during late resolution.
First step in https://github.com/rust-lang/rust/pull/91557
We reuse the rib design of the current resolution framework. Specific `LifetimeRib` and `LifetimeRibKind` types are introduced. The most important variant is `LifetimeRibKind::Generics`, which happens each time we encounter something which may introduce generic lifetime parameters. It can be an item or a `for<...>` binder. The `LifetimeBinderKind` specifies how this rib behaves with respect to in-band lifetimes.
r? `@petrochenkov`
Refactor HIR item-like traversal (part 1)
Issue #95004
- Create hir_crate_items query which traverses tcx.hir_crate(()).owners to return a hir::ModuleItems
- use tcx.hir_crate_items in tcx.hir().items() to return an iterator of hir::ItemId
- use tcx.hir_crate_items to introduce a tcx.hir().par_items(impl Fn(hir::ItemId)) to traverse all items in parallel;
Signed-off-by: Miguel Guarniz <mi9uel9@gmail.com>
cc `@cjgillot`
changelog: [`await_holding_invalid_type`]
This lint allows users to create a denylist of types which are not allowed to be
held across await points. This is essentially a re-implementation of the
language-level [`must_not_suspend`
lint](https://github.com/rust-lang/rust/issues/83310). That lint has a lot of
work still to be done before it will reach Rust stable, and in the meantime
there are a lot of types which can trip up developers if they are used
improperly.
New lint `format_add_strings`
Closes#6261
changelog: Added [`format_add_string`]: recommend using `write!` instead of appending the result of `format!`
Add `usize` cast to `clippy::manual_bits` suggestion
A fix for the suggestion from https://github.com/rust-lang/rust-clippy/pull/8213
changelog: [`manual_bits`]: The suggestion now includes a cast for proper type conversion
This adds test to make sure correct behavior of lint
- The first test's option variable is not a temporary variable
- The second test does not make usage of `take()`
- The third test makes usage of `take()` and uses a temporary variable
This lint checks if Option::take() is used on a temporary value (a value
that is not of type &mut Option and that is not a Place expression) to
suggest omitting take()
Check for loops/closures in `local_used_after_expr`
Follow up to #8646, catches when a local is used multiple times because it's in a loop or a closure
changelog: none
fix unnecessary_to_owned about msrv
This PR fixes ``[`unnecessary_owned`]``.
## What
```rust
# sample code
fn _msrv_1_35() {
#![clippy::msrv = "1.35"]
let _ = &["x"][..].to_vec().into_iter();
}
fn _msrv_1_36() {
#![clippy::msrv = "1.36"]
let _ = &["x"][..].to_vec().into_iter();
}
```
If we will check this code using clippy, ``[`unnecessary_owned`]`` will modify the code as follows.
```rust
error: unnecessary use of `to_vec`
--> $DIR/unnecessary_to_owned.rs:219:14
|
LL | let _ = &["x"][..].to_vec().into_iter();
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use: `["x"][..].iter().copied()`
error: unnecessary use of `to_vec`
--> $DIR/unnecessary_to_owned.rs:224:14
|
LL | let _ = &["x"][..].to_vec().into_iter();
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use: `["x"][..].iter().copied()`
```
This is incorrect. Because `Iterator::copied` was estabilished in 1.36.
## Why
This bug was caused by not separating "copied" and "clone" by reference to msrv.
89ee6aa6e3/clippy_lints/src/methods/unnecessary_to_owned.rs (L195)
So, I added a conditional branch and described the corresponding test.
Thank you in advance.
changelog: fix wrong suggestions about msrv in [`unnecessary_to_owned`]
r! `@giraffate`
Don't lint `manual_non_exhaustive` when the enum variant is used
fixes#5714
changelog: Don't lint `manual_non_exhaustive` when the enum variant is used
Do not trigger ``[`rest_pat_in_fully_bound_structs`]`` on `#[non_exhaustive]` structs
fixes#8029
Just adds an additional check to ensure that the`ty::VariantDef` is not marked as `#[non_exhaustive]`.
changelog: Do not apply ``[`rest_pat_in_fully_bound_structs`]`` on structs marked as non exhaustive.
adding condition for map_clone message
This PR fixes the message about `map_clone`.
if msrv >= 1.36, the message is correct.
```bash
$ cat main.rs
fn main() {
let x: Vec<&i32> = vec![&1, &2];
let y: Vec<_> = x.iter().map(|i| *i).collect();
println!("{:?}", y);
}
$ cargo clippy
warning: you are using an explicit closure for copying elements
--> main.rs:3:20
|
3 | let y: Vec<_> = x.iter().map(|i| *i).collect();
| ^^^^^^^^^^^^^^^^^^^^ help: consider calling the dedicated `copied` method: `x.iter().copied()`
|
= note: `#[warn(clippy::map_clone)]` on by default
= help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#map_clone
warning: `test` (build script) generated 1 warning
warning: `test` (bin "test") generated 1 warning (1 duplicate)
Finished dev [unoptimized + debuginfo] target(s) in 0.00s
```
but, if msrv < 1.36, the suggestion is `cloned`, but the message is `copying`.
```bash
$ cat clippy.toml
msrv = "1.35"
$ cargo clippy
warning: you are using an explicit closure for copying elements
--> main.rs:3:20
|
3 | let y: Vec<_> = x.iter().map(|i| *i).collect();
| ^^^^^^^^^^^^^^^^^^^^ help: consider calling the dedicated `cloned` method: `x.iter().cloned()`
```
I think the separation of messages will make it more user-friendly.
thank you in advance.
changelog: Fixed a message in map_clone.
New lint `is_digit_ascii_radix`
Closes#6399
changelog: Added [`is_digit_ascii_radix`]: recommend `is_ascii_digit()` or `is_ascii_hexdigit()` in place of `is_digit(10)` and `is_digit(16)`
Fix subtraction overflow in `cast_possible_truncation`
changelog: Fix false negative due to subtraction overflow in `cast_possible_truncation`
I *think* a false negative is the worst that can happen from this
Don't lint various match lints when expanded by a proc-macro
fixes#4952
As always for proc-macro output this is a hack-job of a fix. It would be really nice if more proc-macro authors would set spans correctly.
changelog: Don't lint various lints on proc-macro output.
Fix `same_functions_in_if_condition` FP
fixes#8139
changelog: Don't consider `Foo<{ SomeConstant }>` and `Foo<{ SomeOtherConstant }>` to be the same, even if the constants have the same value.
Remove overlap between `manual_split_once` and `needless_splitn`
changelog: Remove overlap between [`manual_split_once`] and [`needless_splitn`]. Fixes some incorrect `rsplitn` suggestions for [`manual_split_once`]
Things that can trigger `needless_splitn` no longer trigger `manual_split_once`, e.g.
```rust
s.[r]splitn(2, '=').next();
s.[r]splitn(2, '=').nth(0);
s.[r]splitn(3, '=').next_tuple();
```
Fixes some suggestions:
```rust
let s = "should not match";
s.rsplitn(2, '.').nth(1);
// old -> Some("should not match")
Some(s.rsplit_once('.').map_or(s, |x| x.0));
// new -> None
s.rsplit_once('.').map(|x| x.0);
s.rsplitn(2, '.').nth(1)?;
// old -> "should not match"
s.rsplit_once('.').map_or(s, |x| x.0);
// new -> early returns
s.rsplit_once('.')?.0;
```
- Create hir_crate_items query which traverses tcx.hir_crate(()).owners to return a hir::ModuleItems
- use tcx.hir_crate_items in tcx.hir().items() to return an iterator of hir::ItemId
- add par_items(impl Fn(hir::ItemId)) to traverse all items in parallel
Signed-off-by: Miguel Guarniz <mi9uel9@gmail.com>
ignore `&x | &y` in unnested_or_patterns
replacing it with `&(x | y)` is actually more characters
Fixes#6973
changelog: [`unnested_or_patterns`] ignore `&x | &y`, nesting would result in more characters
Add a lint to detect cast to unsigned for abs() and suggest unsigned_…
…abs()
changelog: Add a [`cast_abs_to_unsigned`] that checks for uses of `abs()` that are cast to the corresponding unsigned integer type and suggest to replace them with `unsigned_abs()`.
Fix `as_deref_mut` false positives in `needless_option_as_deref`
Also moves it into `methods/`
Fixes#7846Fixes#8047
changelog: [`needless_option_as_deref`]: No longer lints for `as_deref_mut` on Options that cannot be moved
supersedes #8064
fix FP in lint `[needless_match]`
fixes: #8542fixes: #8551fixes: #8595fixes: #8599
---
changelog: check for more complex custom type, and ignore type coercion in [`needless_match`]
Suggest from_utf8_unchecked in const contexts
Unfortunately I couldn't figure out how to check whether a given expression is in an `unsafe` context or not, so I just unconditionally emit the wrapping `unsafe {}` block in the suggestion. If there is an easy way to get it to work better then I would love to hear it.
changelog: Suggest `from_utf8_unchecked` instead of `from_utf8` in const contexts for ``[`transmute_bytes_to_str`]``
refs: #8379
Fix unnecessary_cast suggestion for type aliasses
Fix#6923. The [`unnecessary_cast`] lint now will skip casting to non-primitive type.
changelog: fix lint [`unnecessary_cast `]
`indexing_slicing` should not fire if a valid array index comes from a constant function that is evaluated at compile-time
fix#8348
changelog: [`indexing_slicing`] fewer false positives in `const` contexts and with `const` indices
fix misspelling in diagnostic message of `bytes_nth`
*Please write a short comment explaining your change (or "none" for internal only changes)*
changelog: fix misspelling in diagnostic message in ``[`bytes_nth`]``
Run fmt test before compile-test/dogfood
I seem to always forget to run `cargo dev fmt` before doing a test. This lets it fail fast rather than going through the much longer compile-test/dogfood tests first
changelog: none
Rework `undocumented_unsafe_blocks`
fixes: #8264fixes: #8449
One thing came up while working on this. Currently comments on the same line are supported like so:
```rust
/* SAFETY: reason */ unsafe {}
```
Is this worth supporting at all? Anything other than a couple of words doesn't really fit well.
edit: [zulip topic](https://rust-lang.zulipchat.com/#narrow/stream/257328-clippy/topic/.60undocumented_unsafe_blocks.60.20same.20line.20comment)
changelog: Don't lint `undocumented_unsafe_blocks` when the unsafe block comes from a proc-macro.
changelog: Don't lint `undocumented_unsafe_blocks` when the preceding line has a safety comment and the unsafe block is a sub-expression.
add `empty_structs_with_brackets`
<!-- Thank you for making Clippy better!
We're collecting our changelog from pull request descriptions.
If your PR only includes internal changes, you can just write
`changelog: none`. Otherwise, please write a short comment
explaining your change. Also, it's helpful for us that
the lint name is put into brackets `[]` and backticks `` ` ` ``,
e.g. ``[`lint_name`]``.
If your PR fixes an issue, you can add "fixes #issue_number" into this
PR description. This way the issue will be automatically closed when
your PR is merged.
If you added a new lint, here's a checklist for things that will be
checked during review or continuous integration.
- \[ ] Followed [lint naming conventions][lint_naming]
- \[ ] Added passing UI tests (including committed `.stderr` file)
- \[ ] `cargo test` passes locally
- \[ ] Executed `cargo dev update_lints`
- \[ ] Added lint documentation
- \[ ] Run `cargo dev fmt`
[lint_naming]: https://rust-lang.github.io/rfcs/0344-conventions-galore.html#lints
Note that you can skip the above if you are just opening a WIP PR in
order to get feedback.
Delete this line and everything above before opening your PR.
--
*Please write a short comment explaining your change (or "none" for internal only changes)*
-->
Closes#8591
I'm already sorry for the massive diff 😅
changelog: New lint [`empty_structs_with_brackets`]
Remove deps
This remove both `regex` and `cargo_metadata` as dependencies making `clippy_dev` compile ~3x faster (~46s -> ~16s locally). `cargo_metadata` was used to extract the `version` field from `Cargo.toml`, which is done trivially without that. `regex` was used to parse `define_clippy_lint` in `update_lints` which is now done using `rustc_lexer`. This isn't any simpler, but it compiles ~15s faster and runs ~3x faster (~2.1s -> ~0.7s locally).
The next biggest offenders to compile times are `clap` and `winapi` on windows. `clap` could be removed, but re-implementing enough is probably more work than it's worth. `winapi` is used by `opener` and `walkdir` so it's stuck there.
changelog: none
Handle relative paths in module_files lints
The problem being that when clippy is run in the project's directory `lp` would be a relative path, this wasn't caught by the tests as there `lp` is an absolute path. Being a relative path it did not start with `trim_src_path` and so was ignored
Also allowed the removal of some `.to_os_string`/`.to_owned`s
changelog: Fixes [`self_named_module_files`] and [`mod_module_files`] not linting
Fixes#8123, cc `@DevinR528`
single_element_loop: handle arrays for Edition2021
changelog: [`single_element_loop`] handle arrays in Edition 2021, handle `.iter_mut()` and `.into_iter()`, and wrap in parens if necessary
Add `crate_in_macro_def` lint
This PR adds a lint to check for `crate` as opposed to `$crate` used in a macro definition.
I think this can close#4798. That issue focused on the case where the macro author "imports something into said macro."
But I think use of `crate` is likely to be a bug whether it appears in a `use` statement or not. There could be some use case I am failing to see, though. (cc: `@nilscript` `@flip1995)`
changelog: `crate_in_macro_def`
new lint: `only_used_in_recursion`
changed:
- added `only_used_in_recursion`.
- fixed code that variables are only used in recursion.
- this would not lint when `unused_variable`
This fixes: #8390
-----
changelog: add lint [`only_used_in_recursion`]
Llint for casting between raw slice pointers with different element sizes
This lint disallows using `as` to convert from a raw pointer to a slice (e.g. `*const [i32]`, `*mut [Foo]`) to any other raw pointer to a slice if the element types have different sizes. When a raw slice pointer is cast, the data pointer and count metadata are preserved. This means that when the size of the inner slice's element type changes, the total number of bytes pointed to by the count changes. For example a `*const [i32]` with length 4 (four `i32` elements) is cast `as *const [u8]` the resulting pointer points to four `u8` elements at the same address, losing most of the data. When the size *increases* the resulting pointer will point to *more* data, and accessing that data will be UB.
On its own, *producing* the pointer isn't actually a problem, but because any use of the pointer as a slice will either produce surprising behavior or cause UB I believe this is a correctness lint. If the pointer is not intended to be used as a slice, the user should instead use any of a number of methods to produce just a data pointer including an `as` cast to a thin pointer (e.g. `p as *const i32`) or if the pointer is being created from a slice, the `as_ptr` method on slices. Detecting the intended use of the pointer is outside the scope of this lint, but I believe this lint will also lead users to realize that a slice pointer is only for slices.
There is an exception to this lint when either of the slice element types are zero sized (e.g `*mut [()]`). The total number of bytes pointed to by the slice with a zero sized element is zero. In that case preserving the length metadata is likely intended as a workaround to get the length metadata of a slice pointer though a zero sized slice.
The lint does not forbid casting pointers to slices with the *same* element size as the cast was likely intended to reinterpret the data in the slice as some equivalently sized data and the resulting pointer will behave as intended.
---
changelog: Added ``[`cast_slice_different_sizes`]``, a lint that disallows using `as`-casts to convert between raw pointers to slices when the elements have different sizes.
Only point at the end of the crate. We could try making it point at the
beginning of the crate, but that is confused with `DUMMY_SP`, causing
the output to be *worse*.
This change will make it so that VSCode will *not* underline the whole
file when `main` is missing, so other errors will be visible.
Add lint to detect `allow` attributes without reason
I was considering putting this lint into the pedantic group. However, that would result in countless warnings for existing projects. Having it in restriction also seems good to me 🙃 (And now I need sleep 💤 )
---
changelog: New lint [`allow_lint_without_reason`] (Requires the `lint_reasons` feature)
Closes: rust-lang/rust-clippy#8502
Add `unnecessary_find_map` lint
This PR adds an `unnecessary_find_map` lint. It is essentially just a minor enhancement of `unnecessary_filter_map`.
Closes#8467
changelog: New lint `unnecessary_find_map`
new lint: `missing-spin-loop`
This fixes#7809. I went with the shorter name because the function is called `std::hint::spin_loop`. It doesn't yet detect `while let` loops. I left that for a follow-up PR.
---
changelog: new lint: [`missing_spin_loop`]
This internal lint checks if the `extract_msrv_attrs!` macro is used if
a lint has a MSRV. If not, it suggests to add this attribute to the lint
pass implementation.
fix false positives of large_enum_variant
fixes: #8321
The size of enums containing generic type was calculated to be 0.
I changed [large_enum_variant] so that such enums are not linted.
changelog: none
tests: default to more threads for ui-tests
Benchmarks (tested on i5-7200U, 2 cores, 4 threads)
```
master branch:
cargo test // prime caches
cargo --color=always test 70,39s user 21,91s system 180% cpu 51,035 total
cargo --color=always test 70,77s user 22,13s system 180% cpu 51,579 total
cargo --color=always test 70,97s user 22,12s system 180% cpu 51,673 total
cargo --color=always nextest run 78,74s user 22,27s system 220% cpu 45,829 total
cargo --color=always nextest run 78,46s user 21,92s system 224% cpu 44,674 total
cargo --color=always nextest run 78,31s user 22,21s system 228% cpu 43,909 total
Patched (ui_speedup branch):
cargo test // prime cache
cargo --color=always test 97,51s user 32,02s system 288% cpu 44,905 total
cargo --color=always test 99,19s user 31,91s system 276% cpu 47,436 total
cargo --color=always test 98,47s user 31,84s system 284% cpu 45,744 total
cargo --color=always nextest run 102,18s user 30,80s system 350% cpu 37,902 total
cargo --color=always nextest run 99,75s user 29,86s system 350% cpu 36,935 total
cargo --color=always nextest run 100,36s user 29,93s system 351% cpu 37,061 total
```
changelog: use more threads for running clippys ui-tests for ~10% walltime speedup
Don't lint `match` expressions with `cfg`ed arms
Somehow there are no open issues related to this for any of the affected lints. At least none that I could fine from a quick search.
changelog: Don't lint `match` expressions with `cfg`ed arms in many cases
Benchmarks (tested on i5-7200U, 2 core 4 threads)
```
master branch:
cargo test // prime caches
cargo --color=always test 70,39s user 21,91s system 180% cpu 51,035 total
cargo --color=always test 70,77s user 22,13s system 180% cpu 51,579 total
cargo --color=always test 70,97s user 22,12s system 180% cpu 51,673 total
cargo --color=always nextest run 78,74s user 22,27s system 220% cpu 45,829 total
cargo --color=always nextest run 78,46s user 21,92s system 224% cpu 44,674 total
cargo --color=always nextest run 78,31s user 22,21s system 228% cpu 43,909 total
Patched (ui_speedup branch)
cargo test // prime cache
cargo --color=always test 97,51s user 32,02s system 288% cpu 44,905 total
cargo --color=always test 99,19s user 31,91s system 276% cpu 47,436 total
cargo --color=always test 98,47s user 31,84s system 284% cpu 45,744 total
cargo --color=always nextest run 102,18s user 30,80s system 350% cpu 37,902 total
cargo --color=always nextest run 99,75s user 29,86s system 350% cpu 36,935 total
cargo --color=always nextest run 100,36s user 29,93s system 351% cpu 37,061 total
```