unwrap_or_else_default -> unwrap_or_default and improve resulting lint#10120
unwrap_or_else_default -> unwrap_or_default and improve resulting lint#10120bors merged 3 commits intorust-lang:masterfrom
unwrap_or_else_default -> unwrap_or_default and improve resulting lint#10120Conversation
|
r? @flip1995 (rustbot has picked a reviewer for you, use r? to override) |
5864200 to
8b1c3e2
Compare
|
☔ The latest upstream changes (presumably #10184) made this pull request unmergeable. Please resolve the merge conflicts. |
|
@flip1995 Would it be helpful if I split this into two PRs: one for the false positive fix (the biggest change), and one for everything else? |
"try this" -> "try" Current help messages contain a mix of "try", "try this", and one "try this instead". In the spirit of #10631, this PR adopts the first, as it is the most concise. It also updates the `lint_message_conventions` test to catch cases of "try this". (Aside: #10120 unfairly contained multiple changes in one PR. I am trying to break that PR up into smaller pieces.) changelog: Make help messages more concise ("try this" -> "try").
Fix `unwrap_or_else_default` false positive
This PR fixes a false positive in the handling of `unwrap_or_else` with a default value when the value is needed for type inference.
An easy example to exhibit the false positive is the following:
```rust
let option = None;
option.unwrap_or_else(Vec::new).push(1);
```
The following code would not compile, because the fact that the value is a `Vec` has been lost:
```rust
let option = None;
option.unwrap_or_default().push(1);
```
The fix is to:
- implement a heuristic to tell whether an expression's type can be determined purely from its subexpressions, and the arguments and locals they use;
- apply the heuristic to `unwrap_or_else`'s receiver.
The heuristic returns false when applied to `option` in the above example, but it returns true when applied to `option` in either of the following examples:
```rust
let option: Option<Vec<u64>> = None;
option.unwrap_or_else(Vec::new).push(1);
```
```rust
let option = None::<Vec<u64>>;
option.unwrap_or_else(Vec::new).push(1);
```
(Aside: #10120 unfairly contained multiple changes in one PR. I am trying to break that PR up into smaller pieces.)
---
changelog: FP: [`unwrap_or_else_default`]: No longer lints if the default value is needed for type inference
|
@flip1995 Is this PR more reasonable now? |
|
Sorry, I don't have time to review currently. It would take be too long, even though the PR size now looks better. r? @blyxyas do you mind taking over? |
|
Failed to set assignee to
|
|
I don't mind taking over. Even better, I will take over. Yeehaw 🤠 |
|
@bors delegate=blyxyas In case you're quicker with the review, than getting your bors rights. Thanks for taking over! :) |
|
Oh, rust-lang/team#1031 just got merged 🎉 |
|
Nice, now you have all the rights and with #11194 you'll be picked as a reviewer automatically in the future. |
|
@bors r? blyxyas |
|
The |
| /// Checks for usage of `_.unwrap_or_else(Default::default)` on `Option` and | ||
| /// `Result` values. | ||
| /// Checks for usages of the following functions with an argument that constructs a default value | ||
| /// (e.g., `Default::default` or `String::new`): |
There was a problem hiding this comment.
| /// (e.g., `Default::default` or `String::new`): | |
| /// (e.g. `Default::default` or `String::new`): |
There was a problem hiding this comment.
Both are correct and used a similar amount of times in rustc (512 without the comma vs 680 with the comma). The preferred spelling differs from place to place though.
There was a problem hiding this comment.
Just a personal preference, but I feel like it's weird to have 2 punctuation signs right next to each other and it kinda worsens readability.
There was a problem hiding this comment.
I personally find it easier to read as it keeps the punctuation mark only being used at the end of a sentence. That's subjective though ^^
There was a problem hiding this comment.
I feel like it's weird to have 2 punctuation signs right next to each other
@blyxyas Personally, I agree with you 100%.
But literally every English writing guide I have consulted says to put a ',' after "e.g.".
So I think the question comes down to: should Clippy comments follow English writing guides?
(And, to state the obvious, this is a total bike shed. 😀)
There was a problem hiding this comment.
I'm fine with either. It's bikeshedding and won't cause confusion anyway.
There was a problem hiding this comment.
In American English, a comma is always placed after “i.e.” or “e.g.” In fact, this is a punctuation rule on which both the AP Style Book and the Chicago Manual of Style agree. However, in British English, a comma is not used after “i.e.” or “e.g.”
Mmmm... Guess it doesn't matter. It just looks weird, I don't know and honestly, it isn't that big of a problem.
We can continue designing the power plant, do what you consider the best 🤠
| if let Some(sugg) = match (name, call_expr.is_some()) { | ||
| ("unwrap_or", true) | ("unwrap_or_else", false) => Some("unwrap_or_default"), | ||
| ("or_insert", true) | ("or_insert_with", false) => Some("or_default"), | ||
| _ => None, | ||
| }; |
There was a problem hiding this comment.
This if statement could be replaced by an early return (the compiler probably optimizes this, but just to be sure)
There was a problem hiding this comment.
Is the change I made the one you had in mind?
| if body.params.is_empty() | ||
| && let hir::Expr{ kind, .. } = &body.value | ||
| && let hir::ExprKind::MethodCall(hir::PathSegment {ident, ..}, self_arg, _, _) = kind | ||
| && ident == &symbol::Ident::from_str("to_string") |
There was a problem hiding this comment.
Unnecessary allocation here 🐄
| && ident == &symbol::Ident::from_str("to_string") | |
| && ident.name == sym::to_string |
|
I think this is pretty much ready. Just a final question, @xFrednet, what do you mean by "Not handles more functions" 😅 |
|
@blyxyas this confused me for a solid minute ^^. It's just the usual amount of typos in my artfully crafted changelog entries. You noticed it and passed the test 😉. Here have a Cookie: 🍪 |
|
Okis ^w^ |
|
☀️ Test successful - checks-action_dev_test, checks-action_remark_test, checks-action_test |
|
Thanks very much for the review, @blyxyas. |
Resolves #10080 (though it doesn't implement exactly what's described there)
This PR does the following:
unwrap_or_else_default.rs's code intoor_fun_call.rsunwrap_or(/* default value */)and similar, and moves it intounwrap_or_else_defaultEntry::or_defaultforEntry::or_insert(Default::default())#9342, e.g.,, to handleor_insert_with(Default::default)unwrap_or_else_defaulttounwrap_or_default(since the "new" lint handles bothunwrap_orandunwrap_or_else, it seemed sensible to use the shortened name)This PR is currently two commits. The first implements 1-3, the second implements 4.
A word about 2: the
or_fun_calllint currently produces warnings like the following:To me, such warnings look like they should come from
unwrap_or_else_default, notor_fun_call, especially sinceor_fun_callis in the nursery.changelog: Move: Renamed
unwrap_or_else_defaultto [unwrap_or_default]#10120
changelog: Enhancement: [
unwrap_or_default]: Now handles more functions, likeor_insert_with#10120