Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Detect redundant always successful assert_eq! #8567

Open
repi opened this issue Mar 18, 2022 · 9 comments
Open

Detect redundant always successful assert_eq! #8567

repi opened this issue Mar 18, 2022 · 9 comments
Labels
A-lint Area: New lints

Comments

@repi
Copy link

repi commented Mar 18, 2022

What it does

Detect if assert_eq! always returns succeeds because the same expression is on the left and right side, such as with assert_eq!(a,a).

These type of cases can happen when refactoring and search'n'replacing code, for example we've recently saw a case of this recently:

   assert_eq!(mem::size_of::<usize>(), mem::size_of::<usize>());

It would however be important that it only lints on the expressions being exactly identical, so if using a type alias in the above example that should not trigger this lint, example:

   type MyType = usize;
   assert_eq!(mem::size_of::<usize>(), mem::size_of::<MyType>());

Lint Name

redundant_assert

Category

pedantic

Advantage

Keeping an assert that has no effect is a code smell and negative value as can leave a false sense of safety in tests / coverage and is additional cognitive overhead without any positive effects.

Drawbacks

Likely none.

Probably not that common occurrence, but does happen.

Example

assert_eq!(mem::size_of::<usize>(), mem::size_of::<usize>());

Assert should simply be removed as it has no effect.

@matthiaskrgr
Copy link
Member

Mh, sounds kinda hard, because when there is any kind of mutability or randomness involved, we can still end up with identical expressions that evaluate to completely different things :/

    assert_eq!(
        rand::thread_rng().gen::<u8>(),
        rand::thread_rng().gen::<u8>()
    )

@repi
Copy link
Author

repi commented Mar 19, 2022

For sure if the expression use global mutable state it doesn't work, I was thinking of it primarily for const functions (though I should have added that in the lint description).

std::mem::size_of for example is a const fn. And that could be easier to detect and cover?

@lucarlig
Copy link
Contributor

lucarlig commented Jan 15, 2024

Mh, sounds kinda hard, because when there is any kind of mutability or randomness involved, we can still end up with identical expressions that evaluate to completely different things :/

    assert_eq!(
        rand::thread_rng().gen::<u8>(),
        rand::thread_rng().gen::<u8>()
    )

when assert_eq between random elements wouldn't that be wrong regardless?
the lint should warn about identical literal in assert_eq! regardless of randomness? In case of const or randomness for opposite reasons still wouldn't make sense, although the lint would work only for assert_eq! and not for assert_ne!

@jplatte
Copy link
Contributor

jplatte commented Jan 20, 2024

@lucarlig In more complex cases of non-deterministic functions it might be useful to run the same function twice and assert that the result is the same. For example, testing that a function that internally memoizes some intermediate result gives the same output before and after memoization has kicked in.

@mhnap
Copy link

mhnap commented Jan 24, 2024

I think this could be a useful lint cause Rust allows shadowing variables, and it's too easy to forget the right name (especially after refactoring). This is a bug I found in tests that led me to this issue:

            let non_optional = NonOptional { vec: vec![1, 2, 3] };
            let non_optional: NonOptional =
                serde_json::from_str(&serde_json::to_string(&non_optional).unwrap()).unwrap();
            assert_eq!(non_optional, non_optional);

Not sure why not make this lint work simply for all cases, when the left and right sides are the same, and leave other corner cases to be enabled/disabled as usual per line/file.

@lucarlig
Copy link
Contributor

Makes sense @rustbot claim

@lucarlig
Copy link
Contributor

i think some parts of this lints overlap with eq_op lint, does it make sense to implement it as separate lint or expand that?

@lucarlig lucarlig removed their assignment Aug 27, 2024
@Rudxain Rudxain mentioned this issue Dec 3, 2024
@Rudxain
Copy link
Contributor

Rudxain commented Dec 3, 2024

Related: #13725

@klensy
Copy link
Contributor

klensy commented Dec 15, 2024

This should be partially covered by #13828, see the tests results in https://github.com/rust-lang/rust-clippy/actions/runs/12331203231/job/34417532284?pr=13828

Only that lint explicitly ignores #[test] fn.

2024-12-14T15:58:31.9748781Z +error: identical args used in this `debug_assert_ne!` macro call
2024-12-14T15:58:31.9749117Z +  --> tests/ui/missing_assert_message.rs:97:26
2024-12-14T15:58:31.9749340Z +   |
2024-12-14T15:58:31.9749503Z +LL |         debug_assert_ne!(foo(), foo());

2024-12-14T15:58:31.9739237Z +error: identical args used in this `assert_eq!` macro call
2024-12-14T15:58:31.9739646Z +  --> tests/ui/missing_assert_message.rs:65:16
2024-12-14T15:58:31.9739879Z +   |
2024-12-14T15:58:31.9740034Z +LL |     assert_eq!(foo(), foo(), "msg");

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
A-lint Area: New lints
Projects
None yet
Development

No branches or pull requests

7 participants