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

Lint: comparing two expressions of unit type #4481

Closed
timotree3 opened this issue Sep 1, 2019 · 6 comments · Fixed by #4613
Closed

Lint: comparing two expressions of unit type #4481

timotree3 opened this issue Sep 1, 2019 · 6 comments · Fixed by #4613
Labels
C-enhancement Category: Enhancement of lints, like adding more cases or adding help messages good-first-issue These issues are a good way to get started with Clippy

Comments

@timotree3
Copy link
Contributor

I recently wrote a test like this

assert_eq!(&my_complicated_function().sort(), &[4, 3, 7, 1].sort()) // works!

but much to my surprise, the test kept passing even if I changed the literal

assert_eq!(&my_complicated_function().sort(), &[4, 3].sort()) // works!

at this point I realized that what I wrote was as good as this useless comparison

assert_eq!((), ())

In order to catch people who try to do things like this, I suggest that we lint comparing two expressions of unit type, since the result will always be true and it would be more straightforward just to write two lines for each expression e.g.

my_complicated_function();
[4, 3, 7, 1];

In addition to the canonical Unit Type (), I suggest that we lint for expressions of any user-created unit type such as:

struct UnitStruct;
enum UnitEnum {
    OnlyVariant,
}
// and maybe
enum TechnichallyUnitStruct {
    unit_field: (),
}
enum TechnichallyUnitEnum {
    UnitVariant(UnitStruct, ()),
    NeverVariant(!),
}
// etc...

Thoughts?

@ghost
Copy link

ghost commented Sep 2, 2019

unit_cmp already checks for comparisons. It can be extended to work with assert_eq.

I wonder if we could lint any expression that contains a call to function that returns (). The return value is meaningless so the code either contains a bug or is misleading.

@flip1995
Copy link
Member

flip1995 commented Sep 2, 2019

We explicitly exclude expanded code from that lint:

if expr.span.from_expansion() {
return;
}

I'm not sure if that is necessary, since even when () is compared in an external macro, it most likely isn't something you wanted to do. I think removing this check would solve this issue without causing false positives because of macros. The macro check was added because of this FP: #307. So a test for this has to be added, whether this still happens today (without the macro check).

@flip1995 flip1995 added good-first-issue These issues are a good way to get started with Clippy C-enhancement Category: Enhancement of lints, like adding more cases or adding help messages labels Sep 2, 2019
@timotree3
Copy link
Contributor Author

I could imagine a more complicated macro that is general to a lot of types and does a comparison somewhere without being incorrect. Is there any precedent for doing some sort of heuristic as to how complex the macro is and therefore how likely it is that its sole purpose is the comparison?

@flip1995
Copy link
Member

flip1995 commented Sep 3, 2019

We can't look into the macro, we only can check the expanded code, so there is no way to know the complexity of a macro. I would change this lint, to not trigger on external_macros, but exclude assert_eq! from this.

@jakubadamw
Copy link
Contributor

jakubadamw commented Sep 3, 2019

@flip1995, and perhaps the whole family: (debug_)?assert(_eq|_ne)?!?

@Lythenas
Copy link
Contributor

Lythenas commented Oct 2, 2019

@flip1995 Commenting out

if expr.span.from_expansion() {
return;
}

will still generate warnings when deriving e.g. PartialEq. And according to the comment in the unit_cmp test it should not generate warnings for this:

#[derive(PartialEq)]
pub struct ContainsUnit(()); // should be fine

So I think that check is still needed.

But I was digging around and I think I found a way to implement special exceptions for asserts using expr.span.source_callee() and checking the kind and symbol of the macro expansion.

I would like to work on this issue if there isn't already someone working on it.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
C-enhancement Category: Enhancement of lints, like adding more cases or adding help messages good-first-issue These issues are a good way to get started with Clippy
Projects
None yet
Development

Successfully merging a pull request may close this issue.

4 participants