Skip to content

Commit b9ca319

Browse files
committed
Auto merge of #9791 - smoelius:issues-9739-9782, r=Jarcho
Address issues 9739 and 9782 This PR fixes #9739 in the manner I suggested in #9739 (comment). This PR also fixes the compilation failures in #9782 (but doesn't address `@e00E's` other objections). Fixes #9739 r? `@Jarcho` changelog: Fix two `needless_borrow` false positives, one involving borrows in `if`-`else`s, the other involving qualified function calls
2 parents 4e31877 + 50f63a0 commit b9ca319

File tree

4 files changed

+233
-24
lines changed

4 files changed

+233
-24
lines changed

clippy_lints/src/dereference.rs

Lines changed: 46 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -805,30 +805,39 @@ fn walk_parents<'tcx>(
805805
.position(|arg| arg.hir_id == child_id)
806806
.zip(expr_sig(cx, func))
807807
.and_then(|(i, sig)| {
808-
sig.input_with_hir(i).map(|(hir_ty, ty)| match hir_ty {
809-
// Type inference for closures can depend on how they're called. Only go by the explicit
810-
// types here.
811-
Some(hir_ty) => binding_ty_auto_deref_stability(cx, hir_ty, precedence, ty.bound_vars()),
812-
None => {
813-
if let ty::Param(param_ty) = ty.skip_binder().kind() {
814-
needless_borrow_impl_arg_position(
815-
cx,
816-
possible_borrowers,
817-
parent,
818-
i,
819-
*param_ty,
820-
e,
821-
precedence,
822-
msrv,
823-
)
824-
} else {
825-
ty_auto_deref_stability(cx, cx.tcx.erase_late_bound_regions(ty), precedence)
826-
.position_for_arg()
827-
}
828-
},
808+
sig.input_with_hir(i).map(|(hir_ty, ty)| {
809+
match hir_ty {
810+
// Type inference for closures can depend on how they're called. Only go by the explicit
811+
// types here.
812+
Some(hir_ty) => {
813+
binding_ty_auto_deref_stability(cx, hir_ty, precedence, ty.bound_vars())
814+
},
815+
None => {
816+
// `e.hir_id == child_id` for https://github.com/rust-lang/rust-clippy/issues/9739
817+
// `!call_is_qualified(func)` for https://github.com/rust-lang/rust-clippy/issues/9782
818+
if e.hir_id == child_id
819+
&& !call_is_qualified(func)
820+
&& let ty::Param(param_ty) = ty.skip_binder().kind()
821+
{
822+
needless_borrow_impl_arg_position(
823+
cx,
824+
possible_borrowers,
825+
parent,
826+
i,
827+
*param_ty,
828+
e,
829+
precedence,
830+
msrv,
831+
)
832+
} else {
833+
ty_auto_deref_stability(cx, cx.tcx.erase_late_bound_regions(ty), precedence)
834+
.position_for_arg()
835+
}
836+
},
837+
}
829838
})
830839
}),
831-
ExprKind::MethodCall(_, receiver, args, _) => {
840+
ExprKind::MethodCall(method, receiver, args, _) => {
832841
let id = cx.typeck_results().type_dependent_def_id(parent.hir_id).unwrap();
833842
if receiver.hir_id == child_id {
834843
// Check for calls to trait methods where the trait is implemented on a reference.
@@ -866,7 +875,9 @@ fn walk_parents<'tcx>(
866875
}
867876
args.iter().position(|arg| arg.hir_id == child_id).map(|i| {
868877
let ty = cx.tcx.fn_sig(id).skip_binder().inputs()[i + 1];
869-
if let ty::Param(param_ty) = ty.kind() {
878+
// `e.hir_id == child_id` for https://github.com/rust-lang/rust-clippy/issues/9739
879+
// `method.args.is_none()` for https://github.com/rust-lang/rust-clippy/issues/9782
880+
if e.hir_id == child_id && method.args.is_none() && let ty::Param(param_ty) = ty.kind() {
870881
needless_borrow_impl_arg_position(
871882
cx,
872883
possible_borrowers,
@@ -1044,6 +1055,18 @@ fn ty_contains_infer(ty: &hir::Ty<'_>) -> bool {
10441055
v.0
10451056
}
10461057

1058+
fn call_is_qualified(expr: &Expr<'_>) -> bool {
1059+
if let ExprKind::Path(path) = &expr.kind {
1060+
match path {
1061+
QPath::Resolved(_, path) => path.segments.last().map_or(false, |segment| segment.args.is_some()),
1062+
QPath::TypeRelative(_, segment) => segment.args.is_some(),
1063+
QPath::LangItem(..) => false,
1064+
}
1065+
} else {
1066+
false
1067+
}
1068+
}
1069+
10471070
// Checks whether:
10481071
// * child is an expression of the form `&e` in an argument position requiring an `impl Trait`
10491072
// * `e`'s type implements `Trait` and is copyable

tests/ui/needless_borrow.fixed

Lines changed: 90 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -420,3 +420,93 @@ mod issue_9710 {
420420

421421
fn f<T: AsRef<str>>(_: T) {}
422422
}
423+
424+
#[allow(dead_code)]
425+
mod issue_9739 {
426+
fn foo<D: std::fmt::Display>(_it: impl IntoIterator<Item = D>) {}
427+
428+
fn main() {
429+
foo(if std::env::var_os("HI").is_some() {
430+
&[0]
431+
} else {
432+
&[] as &[u32]
433+
});
434+
}
435+
}
436+
437+
#[allow(dead_code)]
438+
mod issue_9739_method_variant {
439+
struct S;
440+
441+
impl S {
442+
fn foo<D: std::fmt::Display>(&self, _it: impl IntoIterator<Item = D>) {}
443+
}
444+
445+
fn main() {
446+
S.foo(if std::env::var_os("HI").is_some() {
447+
&[0]
448+
} else {
449+
&[] as &[u32]
450+
});
451+
}
452+
}
453+
454+
#[allow(dead_code)]
455+
mod issue_9782 {
456+
fn foo<T: AsRef<[u8]>>(t: T) {
457+
println!("{}", std::mem::size_of::<T>());
458+
let _t: &[u8] = t.as_ref();
459+
}
460+
461+
fn main() {
462+
let a: [u8; 100] = [0u8; 100];
463+
464+
// 100
465+
foo::<[u8; 100]>(a);
466+
foo(a);
467+
468+
// 16
469+
foo::<&[u8]>(&a);
470+
foo(a.as_slice());
471+
472+
// 8
473+
foo::<&[u8; 100]>(&a);
474+
foo(a);
475+
}
476+
}
477+
478+
#[allow(dead_code)]
479+
mod issue_9782_type_relative_variant {
480+
struct S;
481+
482+
impl S {
483+
fn foo<T: AsRef<[u8]>>(t: T) {
484+
println!("{}", std::mem::size_of::<T>());
485+
let _t: &[u8] = t.as_ref();
486+
}
487+
}
488+
489+
fn main() {
490+
let a: [u8; 100] = [0u8; 100];
491+
492+
S::foo::<&[u8; 100]>(&a);
493+
}
494+
}
495+
496+
#[allow(dead_code)]
497+
mod issue_9782_method_variant {
498+
struct S;
499+
500+
impl S {
501+
fn foo<T: AsRef<[u8]>>(&self, t: T) {
502+
println!("{}", std::mem::size_of::<T>());
503+
let _t: &[u8] = t.as_ref();
504+
}
505+
}
506+
507+
fn main() {
508+
let a: [u8; 100] = [0u8; 100];
509+
510+
S.foo::<&[u8; 100]>(&a);
511+
}
512+
}

tests/ui/needless_borrow.rs

Lines changed: 90 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -420,3 +420,93 @@ mod issue_9710 {
420420

421421
fn f<T: AsRef<str>>(_: T) {}
422422
}
423+
424+
#[allow(dead_code)]
425+
mod issue_9739 {
426+
fn foo<D: std::fmt::Display>(_it: impl IntoIterator<Item = D>) {}
427+
428+
fn main() {
429+
foo(if std::env::var_os("HI").is_some() {
430+
&[0]
431+
} else {
432+
&[] as &[u32]
433+
});
434+
}
435+
}
436+
437+
#[allow(dead_code)]
438+
mod issue_9739_method_variant {
439+
struct S;
440+
441+
impl S {
442+
fn foo<D: std::fmt::Display>(&self, _it: impl IntoIterator<Item = D>) {}
443+
}
444+
445+
fn main() {
446+
S.foo(if std::env::var_os("HI").is_some() {
447+
&[0]
448+
} else {
449+
&[] as &[u32]
450+
});
451+
}
452+
}
453+
454+
#[allow(dead_code)]
455+
mod issue_9782 {
456+
fn foo<T: AsRef<[u8]>>(t: T) {
457+
println!("{}", std::mem::size_of::<T>());
458+
let _t: &[u8] = t.as_ref();
459+
}
460+
461+
fn main() {
462+
let a: [u8; 100] = [0u8; 100];
463+
464+
// 100
465+
foo::<[u8; 100]>(a);
466+
foo(a);
467+
468+
// 16
469+
foo::<&[u8]>(&a);
470+
foo(a.as_slice());
471+
472+
// 8
473+
foo::<&[u8; 100]>(&a);
474+
foo(&a);
475+
}
476+
}
477+
478+
#[allow(dead_code)]
479+
mod issue_9782_type_relative_variant {
480+
struct S;
481+
482+
impl S {
483+
fn foo<T: AsRef<[u8]>>(t: T) {
484+
println!("{}", std::mem::size_of::<T>());
485+
let _t: &[u8] = t.as_ref();
486+
}
487+
}
488+
489+
fn main() {
490+
let a: [u8; 100] = [0u8; 100];
491+
492+
S::foo::<&[u8; 100]>(&a);
493+
}
494+
}
495+
496+
#[allow(dead_code)]
497+
mod issue_9782_method_variant {
498+
struct S;
499+
500+
impl S {
501+
fn foo<T: AsRef<[u8]>>(&self, t: T) {
502+
println!("{}", std::mem::size_of::<T>());
503+
let _t: &[u8] = t.as_ref();
504+
}
505+
}
506+
507+
fn main() {
508+
let a: [u8; 100] = [0u8; 100];
509+
510+
S.foo::<&[u8; 100]>(&a);
511+
}
512+
}

tests/ui/needless_borrow.stderr

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -210,5 +210,11 @@ error: the borrowed expression implements the required traits
210210
LL | use_x(&x);
211211
| ^^ help: change this to: `x`
212212

213-
error: aborting due to 35 previous errors
213+
error: the borrowed expression implements the required traits
214+
--> $DIR/needless_borrow.rs:474:13
215+
|
216+
LL | foo(&a);
217+
| ^^ help: change this to: `a`
218+
219+
error: aborting due to 36 previous errors
214220

0 commit comments

Comments
 (0)