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

add lint manual_unwrap_or #6123

Merged
merged 6 commits into from
Oct 16, 2020
Merged

add lint manual_unwrap_or #6123

merged 6 commits into from
Oct 16, 2020

Conversation

tnielens
Copy link
Contributor

@tnielens tnielens commented Oct 6, 2020

Implements partially #5923.

changelog: add lint manual_unwrap_or

@rust-highfive
Copy link

r? @matthiaskrgr

(rust_highfive has picked a reviewer for you, use r? to override)

@rust-highfive rust-highfive added the S-waiting-on-review Status: Awaiting review from the assignee but also interested parties label Oct 6, 2020
@ebroto ebroto assigned ebroto and unassigned matthiaskrgr Oct 8, 2020
Copy link
Member

@ebroto ebroto left a comment

Choose a reason for hiding this comment

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

Left some thoughts

CHANGELOG.md Outdated Show resolved Hide resolved
clippy_lints/src/less_concise_than.rs Outdated Show resolved Hide resolved
tests/ui/less_concise_than.stderr Outdated Show resolved Hide resolved
tests/ui/less_concise_than.fixed Outdated Show resolved Hide resolved
clippy_lints/src/less_concise_than.rs Outdated Show resolved Hide resolved
clippy_lints/src/less_concise_than.rs Outdated Show resolved Hide resolved
clippy_lints/src/less_concise_than.rs Outdated Show resolved Hide resolved
clippy_lints/src/less_concise_than.rs Outdated Show resolved Hide resolved
clippy_lints/src/less_concise_than.rs Outdated Show resolved Hide resolved
clippy_lints/src/less_concise_than.rs Outdated Show resolved Hide resolved
@ebroto ebroto added S-waiting-on-author Status: This is awaiting some action from the author. (Use `@rustbot ready` to update this status) and removed S-waiting-on-review Status: Awaiting review from the assignee but also interested parties labels Oct 11, 2020
@tnielens tnielens changed the title add lint less_concise_than_option_unwrap_or add lint manual_unwrap_or Oct 11, 2020
@tnielens
Copy link
Contributor Author

@ebroto all your remarks should be addressed.

@tnielens tnielens force-pushed the less_concise_than branch 3 times, most recently from 795e34a to 7b3074f Compare October 12, 2020 07:38
Copy link
Member

@ebroto ebroto left a comment

Choose a reason for hiding this comment

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

Just some very minor nits. Also we should rebase to get rid of the merge commits.

clippy_lints/src/manual_unwrap_or.rs Outdated Show resolved Hide resolved
clippy_lints/src/manual_unwrap_or.rs Outdated Show resolved Hide resolved
@tnielens
Copy link
Contributor Author

Last comments were addressed.

Copy link
Member

@ebroto ebroto left a comment

Choose a reason for hiding this comment

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

So, I've been playing with the lint a bit and I think I found a problematic case.

The unwrap_or/else methods take self by value, while match does not need to move the scrutinee. If the scrutinee is mutable and is modified in the None arm, after applying the lint we get a use-after-move error:

struct NonCopyable;

fn main() {
    let mut option: Option<NonCopyable> = None;
    match option {
        Some(x) => x,
        None => {
            option = Some(NonCopyable);
            // some more code ...
            option.unwrap()
        },
    };
}

(playground)

is turned into:

struct NonCopyable;

fn main() {
    let mut option: Option<NonCopyable> = None;
    option.unwrap_or_else(|| {
        option = Some(NonCopyable);
        // some more code ...
        option.unwrap()
    });
}

(playground)

I see at least two options:

  1. We check that the T in Option<T> is Copy, otherwise we bail out
  2. We check that the None arm is not modifying the scrutinee.

I'm more hesitant about making the lint enabled by default for now, I think we might be missing other stuff when turning an arm value into a closure. What do you think?

@tnielens
Copy link
Contributor Author

Great catch! @ebroto

Here is another problem related to ownership:

fn main() {
    let option: Option<&str> = None;
    match option {
        Some(s) => s,
        None => &format!("{} {}!", "hello", "world"),
    };
    
    option.unwrap_or_else(|| {
        // compilation error here, it can't return a reference to a value owned by the closure body
        &format!("{} {}!", "hello", "world")
    });
}

Indeed, the risk of hitting an ownership bug is high no matter what exception rules we put in place.
Should we stick to constant none arms only and only suggest the unwrap_or variant?

@ebroto
Copy link
Member

ebroto commented Oct 13, 2020

Oh, right, that one is more probable :)

Indeed, let's be safe and lint only the unwrap_or case 👍

@tnielens
Copy link
Contributor Author

The unwrap_or_else suggestions are removed.

@ebroto
Copy link
Member

ebroto commented Oct 16, 2020

@bors r+

Thanks!

@bors
Copy link
Collaborator

bors commented Oct 16, 2020

📌 Commit 690a6a6 has been approved by ebroto

@bors
Copy link
Collaborator

bors commented Oct 16, 2020

⌛ Testing commit 690a6a6 with merge 4e83a38...

@bors
Copy link
Collaborator

bors commented Oct 16, 2020

☀️ Test successful - checks-action_dev_test, checks-action_remark_test, checks-action_test
Approved by: ebroto
Pushing 4e83a38 to master...

@bors bors merged commit 4e83a38 into rust-lang:master Oct 16, 2020
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 from the author. (Use `@rustbot ready` to update this status)
Projects
None yet
Development

Successfully merging this pull request may close these issues.

6 participants