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

Fix handling of Deref in assigning_clones #12473

Merged
merged 1 commit into from
Jul 25, 2024

Conversation

Kobzol
Copy link
Contributor

@Kobzol Kobzol commented Mar 12, 2024

The assigning_clones lint had a special case for producing a bit nicer code for mutable references:

fn clone_function_lhs_mut_ref(mut_thing: &mut HasCloneFrom, ref_thing: &HasCloneFrom) {
    *mut_thing = Clone::clone(ref_thing);
}
//v
fn clone_function_lhs_mut_ref(mut_thing: &mut HasCloneFrom, ref_thing: &HasCloneFrom) {
    Clone::clone_from(mut_thing, ref_thing);
}

However, this could break when combined with Deref.

This PR removes the special case, so that the generated code should work more generally. Later we can improve the detection of Deref and put the special case back in a way that does not break code.

Fixes: #12437

r? @blyxyas

changelog: [assigning_clones]: change applicability to Unspecified and fix a problem with Deref.

@rustbot rustbot added the S-waiting-on-review Status: Awaiting review from the assignee but also interested parties label Mar 12, 2024
@Kobzol Kobzol changed the title Assigning clones deref Remove special case from assigning_clones Mar 12, 2024
@blyxyas
Copy link
Member

blyxyas commented Mar 18, 2024

Hmmmm... What if instead of outright removing it, we could check for the Deref lang item?
It would just add a few lines. Here's the code that you can copy and here's LangItem::Deref

@Kobzol
Copy link
Contributor Author

Kobzol commented Mar 18, 2024

I mostly wanted a hotfix so that this doesn't break so often for people, and my experience from writing IDE plugins is that this stuff around Deref handling etc. can be incredibly tricky to get right, so it might take some time :)

I will take a look at what you sent me, thanks.

@bors
Copy link
Collaborator

bors commented Mar 20, 2024

☔ The latest upstream changes (presumably #12511) made this pull request unmergeable. Please resolve the merge conflicts.

@Kobzol
Copy link
Contributor Author

Kobzol commented Mar 21, 2024

It's a bit more complicated than I thought. This works fine:

// #[derive(Clone)]
struct DerefWrapper(DerefInner);

impl Deref for DerefWrapper {
    type Target = DerefInner;

    fn deref(&self) -> &Self::Target {
        &self.0
    }
}

impl DerefMut for DerefWrapper {
    fn deref_mut(&mut self) -> &mut Self::Target {
        &mut self.0
    }
}

#[derive(Clone)]
struct DerefInner;

fn clone_into_deref_method(mut a: DerefWrapper, b: DerefInner) {
    *a = b.clone();
    a.clone_from(&b);
}

But it doesn't work when we uncomment the Clone derive on DerefWrapper. So the issue is not Deref per-se, but the problem is if both the Deref wrapper and the Deref target implement Clone. Maybe it is unnecessary to also check for this, as just keeping * should be enough. I'll try.

@Kobzol
Copy link
Contributor Author

Kobzol commented Mar 21, 2024

So, some of the stuff works, but I'm having some trouble with recognizing if Deref was actually applied. Using this:

let ty = cx.typeck_results().expr_ty(ref_expr);
let impls_deref = cx.tcx.lang_items().deref_mut_trait().map_or(false, |id| implements_trait(cx, ty, id, &[]));

also fires here:

fn clone_function_lhs_mut_ref(mut_thing: &mut HasCloneFrom, ref_thing: &HasCloneFrom) {
    *mut_thing = Clone::clone(ref_thing);
}

because the LHS has type &ReErased mut HasCloneFrom, which apparently implements Deref, even though HasCloneFrom doesn't.

I tried using typeck_results().expr_adjustments(), but that doesn't actually contain a Deref adjustment even if LHS goes through a Deref type...

@Kobzol
Copy link
Contributor Author

Kobzol commented Mar 21, 2024

I pushed my code. The second commit shows that some unnecessary &mut * is being generated.

@Kobzol Kobzol changed the title Remove special case from assigning_clones Fix handling of Deref in assigning_clones Mar 21, 2024
bors added a commit that referenced this pull request Mar 25, 2024
Change applicability of `assigning_clones` to `Unspecified`

Before we deal with #12473 and the borrow checker errors, I think that it would be better to downgrade this lint, since it can break code.

changelog: Change the applicability of `assigning_clones` to `Unspecified`

r? `@blyxyas`
@gibfahn
Copy link
Contributor

gibfahn commented Mar 27, 2024

Hmmmm... What if instead of outright removing it, we could check for the Deref lang item?

Could we remove the special-case first, and then continue this PR to add it back later? Having clippy autofix working code to broken code (even on nightly) feels like a "revert first, improve later" situation to me (as a user).

@Kobzol
Copy link
Contributor Author

Kobzol commented Mar 27, 2024

Could we remove the special-case first, and then continue this PR to add it back later?

I agree, that's why I changed the applicability here. Therefore this lint should no longer autofix.

@bors
Copy link
Collaborator

bors commented Apr 3, 2024

☔ The latest upstream changes (presumably #12615) made this pull request unmergeable. Please resolve the merge conflicts.

@xFrednet
Copy link
Member

Hey @Kobzol, this is a ping from triage, since there hasn't been any activity in some time. Are you still planning to continue this implementation?

If you have any questions, you're always welcome to ask them in this PR or on Zulip.

@rustbot author

@rustbot rustbot 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 Jun 20, 2024
@Kobzol
Copy link
Contributor Author

Kobzol commented Jun 20, 2024

Well, it was waiting for a review :) I'll try to rebase it.

@xFrednet
Copy link
Member

Ahh okay, I guessed that but wasn't sure. Then let's pick a new reviewer:

r? clippy

@rustbot rustbot assigned dswij and unassigned blyxyas Jun 20, 2024
@xFrednet
Copy link
Member

r? clippy

@rustbot rustbot assigned Alexendoo and unassigned dswij Jun 20, 2024
@xFrednet
Copy link
Member

Hey @Alexendoo, rustbot has picked you as a new reviewer. If you don't have the time, you can give the PR to me. Just comment r? @xFrednet

@Kobzol
Copy link
Contributor Author

Kobzol commented Jun 21, 2024

Rebased. It's still WIP, but I'd appreciate some feedback on the approach that I have used here.

@Alexendoo
Copy link
Member

Great, thank you!

@bors r+

@bors
Copy link
Collaborator

bors commented Jul 25, 2024

📌 Commit e9852cc has been approved by Alexendoo

It is now in the queue for this repository.

@bors
Copy link
Collaborator

bors commented Jul 25, 2024

⌛ Testing commit e9852cc with merge 533c377...

@bors
Copy link
Collaborator

bors commented Jul 25, 2024

☀️ Test successful - checks-action_dev_test, checks-action_remark_test, checks-action_test
Approved by: Alexendoo
Pushing 533c377 to master...

@bors bors merged commit 533c377 into rust-lang:master Jul 25, 2024
8 checks passed
@Kobzol Kobzol deleted the assigning-clones-deref branch July 25, 2024 20:50
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.

assigning_clones: Wrong suggestion with deref
8 participants