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

feature: Add Replace if let else with Option::map_or_else assist #16031

Closed
wants to merge 2 commits into from

Conversation

Emilgardis
Copy link
Contributor

@Emilgardis Emilgardis commented Dec 5, 2023

Implements the option_if_let_else clippy lint.

Screen.Recording.2023-12-05.at.18.30.03.webm

@rustbot rustbot added the S-waiting-on-review Status: Awaiting review from the assignee but also interested parties. label Dec 5, 2023
Copy link
Contributor Author

@Emilgardis Emilgardis left a comment

Choose a reason for hiding this comment

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

This works fine, however we don't check for control flow like break, return or continue. I think that's fine.

I want to also implement the reverse but I had trouble implementing it.

Comment on lines +74 to +76
if scrutinee_to_be_expr.syntax().text() != expr.syntax().text() {
return None;
}
Copy link
Contributor Author

Choose a reason for hiding this comment

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

I don't know if this is needed, stolen from

// FIXME: If one `let` is wrapped in parentheses and the second is not,
// we'll exit here.
if scrutinee_to_be_expr.syntax().text() != expr.syntax().text() {
// Only if all condition expressions are equal we can merge them into a match
return None;
}
pat_seen = true;

Copy link
Member

Choose a reason for hiding this comment

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

I don't think this applies here

@Emilgardis Emilgardis changed the title Add Replace if let else with Option::map_or_else` assist feature: Add Replace if let else with Option::map_or_else` assist Dec 5, 2023
@Emilgardis
Copy link
Contributor Author

this doesn't seem to handle

if let Some(ref field) = self.field {
    field.eq_ignore_ascii_case(other)
} else $0if let Some(field2) = self.field2 {
    self.something()
} else {
    false
}

well, it becomes

if let Some(ref field) = self.field {
    field.eq_ignore_ascii_case(other)
} else self.field2.map_or_else(|| {
    false
}, |field2| {
    self.something()
})

which is obviously wrong.

@Emilgardis
Copy link
Contributor Author

We also need to prevent

let _ = if $0let Some(ref mut field) = self.field2 {
    *field = "".to_owned();
    field == other
} else {
    true
}

or make it change to

let _ = self.field2.as_mut().map_or_else(|| {
    true
}, |field| {
    *field = "".to_owned();
    field == other
})

however I can't figure out how to get the bindings inside the pattern

@Emilgardis Emilgardis changed the title feature: Add Replace if let else with Option::map_or_else` assist feature: Add Replace if let else with Option::map_or_else assist Dec 8, 2023
}
pat = tuple_pat.fields().next()?;
}
None => return None,
Copy link
Member

Choose a reason for hiding this comment

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

Looks like we can just ? on the result of single_let

Comment on lines +74 to +76
if scrutinee_to_be_expr.syntax().text() != expr.syntax().text() {
return None;
}
Copy link
Member

Choose a reason for hiding this comment

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

I don't think this applies here

@Veykril
Copy link
Member

Veykril commented Jan 2, 2024

this doesn't seem to handle

if let Some(ref field) = self.field {
    field.eq_ignore_ascii_case(other)
} else $0if let Some(field2) = self.field2 {
    self.something()
} else {
    false
}

well, it becomes

if let Some(ref field) = self.field {
    field.eq_ignore_ascii_case(other)
} else self.field2.map_or_else(|| {
    false
}, |field2| {
    self.something()
})

which is obviously wrong.

It's fine if we just don't offer the assist in that case for the time being. better than creating these syntax errors.

@Veykril Veykril added S-waiting-on-author Status: This is awaiting some action (such as code changes or more information) from the author. and removed S-waiting-on-review Status: Awaiting review from the assignee but also interested parties. labels Jan 2, 2024
@Veykril
Copy link
Member

Veykril commented Jan 2, 2024

We also need to prevent

let _ = if $0let Some(ref mut field) = self.field2 {
    *field = "".to_owned();
    field == other
} else {
    true
}

or make it change to

let _ = self.field2.as_mut().map_or_else(|| {
    true
}, |field| {
    *field = "".to_owned();
    field == other
})

however I can't figure out how to get the bindings inside the pattern

You can get the binding for that here https://github.com/rust-lang/rust-analyzer/pull/16031/files#diff-74f54460a4549ebe1f552b2513663b9eac476eef5399254c8895d6177094baa0R70-R72

tuple_pat is your pattern in that case, you just gotta inspect it there (ref mut ident in that case would be an IdentPat with ref and mut keyword being some)

@Veykril
Copy link
Member

Veykril commented Apr 15, 2024

Closing due to inactivity, feel free to come back to this if you find the time

@Veykril Veykril closed this Apr 15, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
S-waiting-on-author Status: This is awaiting some action (such as code changes or more information) from the author.
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants