-
Notifications
You must be signed in to change notification settings - Fork 1.9k
Fix cloned_ref_to_slice_refs FN on to_owned()
#16329
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
base: master
Are you sure you want to change the base?
Conversation
|
There are more cases of implicit clone, see: #16320 (comment). |
|
Added. Thank you for the advice! |
f78757d to
f870001
Compare
This comment has been minimized.
This comment has been minimized.
|
This lint also has the macro expansion problem. The fix now is also included in this PR. |
There was a problem hiding this 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.
|
Can you explain more? This lint does not check for string originally |
|
Lots of types implement |
|
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 |
|
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. |
|
Updated thanks to @xtqqczze's advices. |
| && 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) |
There was a problem hiding this comment.
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.
| let return_type = cx.typeck_results().expr_ty(item); | ||
| let input_type = cx.typeck_results().expr_ty(val); | ||
| return_type == input_type.peel_refs() |
There was a problem hiding this comment.
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));There was a problem hiding this comment.
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
Closes #16320
changelog: [
cloned_ref_to_slice_refs] fix FN onto_owned()