Skip to content

Conversation

@profetia
Copy link
Member

@profetia profetia commented Jan 2, 2026

Closes #16320

changelog: [cloned_ref_to_slice_refs] fix FN on to_owned()

@rustbot rustbot added the S-waiting-on-review Status: Awaiting review from the assignee but also interested parties label Jan 2, 2026
@rustbot
Copy link
Collaborator

rustbot commented Jan 2, 2026

r? @Jarcho

rustbot has assigned @Jarcho.
They will have a look at your PR within the next two weeks and either review your PR or reassign to another reviewer.

Use r? to explicitly pick a reviewer

@xtqqczze
Copy link
Contributor

xtqqczze commented Jan 2, 2026

There are more cases of implicit clone, see: #16320 (comment).

@profetia
Copy link
Member Author

profetia commented Jan 2, 2026

Added. Thank you for the advice!

@profetia profetia force-pushed the issue16320 branch 2 times, most recently from f78757d to f870001 Compare January 2, 2026 19:51
@rustbot

This comment has been minimized.

@profetia
Copy link
Member Author

profetia commented Jan 2, 2026

This lint also has the macro expansion problem. The fix now is also included in this PR.

Copy link
Contributor

@Jarcho Jarcho left a comment

Choose a reason for hiding this comment

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

This needs to check the result type. &[x.to_string()] has a clone only if x is a string. This is the same for every clone-like function.

View changes since this review

@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 Jan 6, 2026
@profetia
Copy link
Member Author

profetia commented Jan 6, 2026

Can you explain more? This lint does not check for string originally

@Jarcho
Copy link
Contributor

Jarcho commented Jan 6, 2026

Lots of types implement ToString, but only <String as ToString>::to_string is actually a clone. A similar issue happens with Path::to_path_buf which is only a clone when the receiver is a derefed PathBuf. Depending on the method you'll have to check either the adjusted or unadjusted type against the result type.

@xtqqczze
Copy link
Contributor

xtqqczze commented Jan 6, 2026

Right, it would be a false positive to trigger in the following case:

#[derive(Clone)]
struct A(i32);

impl std::fmt::Display for A {
    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
        write!(f, "{}", self.0)
    }
}

pub fn main() {
    let a = A(42);
    _ = &[a.to_string()];
}

We need to ensure return_type == input_type, like implicit_clone does.

@rustbot
Copy link
Collaborator

rustbot commented Jan 7, 2026

This PR was rebased onto a different master commit. Here's a range-diff highlighting what actually changed.

Rebasing is a normal part of keeping PRs up to date, so no action is needed—this note is just to help reviewers.

@profetia
Copy link
Member Author

profetia commented Jan 7, 2026

Updated thanks to @xtqqczze's advices.

@profetia profetia requested a review from Jarcho January 7, 2026 23:21
@rustbot rustbot added S-waiting-on-review Status: Awaiting review from the assignee but also interested parties and removed S-waiting-on-author Status: This is awaiting some action from the author. (Use `@rustbot ready` to update this status) labels Jan 7, 2026
&& let ExprKind::MethodCall(_, val, _, _) = item.kind
&& cx.ty_based_def(item).opt_parent(cx).is_diag_item(cx, sym::Clone)
&& let ExprKind::MethodCall(path, val, _, _) = item.kind
&& let opt_parent_def = cx.ty_based_def(item).opt_parent(cx)
Copy link
Contributor

Choose a reason for hiding this comment

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

Should just be let Some(parent_def) = since you need to unwrap is later.

Comment on lines +85 to +87
let return_type = cx.typeck_results().expr_ty(item);
let input_type = cx.typeck_results().expr_ty(val);
return_type == input_type.peel_refs()
Copy link
Contributor

Choose a reason for hiding this comment

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

This will have FNs when custom deref adjusments occur. You will also have a broken suggestion when the initial type is double reference (other than to_owned, that works the same way clone does).

You'll need something like:

let mut ty = expr_ty(recv);
let mut deref_count = 0u32;
let mut has_custom = false;
let mut adjustments = expr_adjustments(recv).iter();
while ty != target_ty {
  if let Some(adjust) = adjustments.next()
    && let Adjust::Deref(kind) = adjust.kind
  {
    ty = adjust.ty;
    deref_count += 1;
    has_custom |= kind.is_some();
  } else {
    return None
  }
}

let needs_borrow = deref_count == 0 || has_custom
deref_count -= (!has_custom) as u32;
return Some((deref_count, needs_borrow));

Copy link
Member Author

Choose a reason for hiding this comment

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

Emm.. I'm comparing the orignial type (i.e. expr_ty()) not the adjusted one (i.e. expr_ty_adjusted()), so I think custom deref should not be a problem

@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 Jan 8, 2026
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.

cloned_ref_to_slice_refs doesn't trigger on implicit clone

4 participants