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 if comparison chain that could be a tuple comparison instead #1111

Open
MBons opened this issue Jul 20, 2016 · 9 comments
Open

detect if comparison chain that could be a tuple comparison instead #1111

MBons opened this issue Jul 20, 2016 · 9 comments
Labels
A-lint Area: New lints E-medium Call for participation: Medium difficulty level problem and requires some initial experience. L-style Lint: Belongs in the style lint group

Comments

@MBons
Copy link

MBons commented Jul 20, 2016

The if_same_then_else lint triggered on the following code I use to sort some stuff:

positions.sort_by(|&(x1, y1, z1), &(x2, y2, z2)| {
    use std::cmp::Ordering::*;
    if z1 < z2 {
        Less
    } else if z1 > z2 {
        Greater
    } else if x1 > x2 {
        Less
    } else if x1 < x2 {
        Greater
    } else if y1 < y2 {
        Less
    } else {
        Greater
    }
});

I'm not sure if Clippy could reason about this or if it's even worth the trouble thinking about that but perhaps this is worthy of a footnote in the wiki?

@mcarton
Copy link
Member

mcarton commented Jul 20, 2016

Isn't that (z1, x2, y1) < (z2, x1, y2) or something?

@MBons
Copy link
Author

MBons commented Jul 21, 2016

I wasn't aware comparing tuples worked like that, thanks.

@MBons MBons closed this as completed Jul 21, 2016
@oli-obk
Copy link
Contributor

oli-obk commented Jul 21, 2016

We should be detecting this pattern and suggesting the tuple comparison

@oli-obk oli-obk reopened this Jul 21, 2016
@oli-obk oli-obk changed the title possible if_same_then_else problem? detect if comparison chain that could be a tuple comparison instead Jul 21, 2016
@oli-obk oli-obk added E-medium Call for participation: Medium difficulty level problem and requires some initial experience. A-lint Area: New lints L-style Lint: Belongs in the style lint group labels Jul 21, 2016
@marhoily
Copy link

marhoily commented Oct 5, 2016

Also when chain if ... else if ... blocks the "if_same_then_else" is inapplicable, because "else if" has one more condition, that means that if and else branches are not the same. My particular sample is here. Should I create another issue to detect "else if"?

@mcarton
Copy link
Member

mcarton commented Oct 5, 2016

My view on that is that the lint catches what is most of the time a copy-and-paste error and reports it as wanted. For the few cases where that behavior is actually wanted, explicitly #[allow]ing the lint is acceptable.
This is similar to how unsafe works: most of the time unsafe stuffs are bad, so it's forbidden by default. For the few cases where you know what you are doing, you can explicitly add unsafe.

@marhoily
Copy link

marhoily commented Oct 5, 2016

I'm sorry, but I just don't understand.

When I say if something { OK } else { OK } then I understand why it looks suspicious. Why does it look suspicious when I say if something { OK } else if something_else { OK } else ... ?

I'm not asking why false positives are possible. I'm asking for an example when ...else if... looks suspicious. Can you come up with any counter example?

@mcarton
Copy link
Member

mcarton commented Oct 5, 2016

if something { OK } else if something_else { OK } else ... can be written if something || something_else { OK } else .... In you case it couldn't be rewritten that easily though.
The point of the lint is catching people copy-pasting code in potentially long chains of ifs, make a small variation somewhere, and forget to update one case. Viva64 has published a list of real gotchas found by a similar lint (look at MySQL or Trans-Proteomic Pipeline).

@marhoily
Copy link

marhoily commented Oct 5, 2016

I understand you position now, though it is not correct about something || something_else because I've a bit more convoluted case.

Would you at least consider making it 2 different lints so that we could keep disagreeing? one that says "if and else branches are the same" and the other one "there are 2 identical branches in a chain of else-ifs"?

@mathstuf
Copy link
Contributor

mathstuf commented Nov 8, 2017

I think that the lint should be silent for:

if a {
    X
} else if b {
    Y
} else {
    X
}

The use case is that a checks that some kind of filtering is even applicable, b checks whether the filtering can be done and does it, and then if we reach the end, there's nothing to do, so we do what would have been done without any filtering.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
A-lint Area: New lints E-medium Call for participation: Medium difficulty level problem and requires some initial experience. L-style Lint: Belongs in the style lint group
Projects
None yet
Development

No branches or pull requests

5 participants