Skip to content

Commit c4c41d1

Browse files
committed
Fix 12969 and fix 9841
1 parent 388de38 commit c4c41d1

File tree

5 files changed

+46
-20
lines changed

5 files changed

+46
-20
lines changed

clippy_lints/src/dereference.rs

+23-10
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,8 @@ use clippy_utils::source::{snippet_with_applicability, snippet_with_context};
33
use clippy_utils::sugg::has_enclosing_paren;
44
use clippy_utils::ty::{implements_trait, is_manually_drop, peel_mid_ty_refs};
55
use clippy_utils::{
6-
expr_use_ctxt, get_parent_expr, is_block_like, is_lint_allowed, path_to_local, DefinedTy, ExprUseNode,
6+
expr_use_ctxt, get_parent_expr, is_block_like, is_lint_allowed, path_to_local, peel_middle_ty_refs, DefinedTy,
7+
ExprUseNode,
78
};
89
use core::mem;
910
use rustc_ast::util::parser::{PREC_POSTFIX, PREC_PREFIX};
@@ -1044,16 +1045,28 @@ fn report<'tcx>(
10441045
return;
10451046
}
10461047

1047-
let (prefix, precedence) = if let Some(mutability) = mutability
1048-
&& !typeck.expr_ty(expr).is_ref()
1048+
let ty = typeck.expr_ty(expr);
1049+
1050+
// `&&[T; N]`, or `&&..&[T; N]` (src) cannot coerce to `&[T]` (dst).
1051+
if let ty::Ref(_, dst, _) = data.adjusted_ty.kind()
1052+
&& dst.is_slice()
10491053
{
1050-
let prefix = match mutability {
1051-
Mutability::Not => "&",
1052-
Mutability::Mut => "&mut ",
1053-
};
1054-
(prefix, PREC_PREFIX)
1055-
} else {
1056-
("", 0)
1054+
let (src, n_src_refs) = peel_middle_ty_refs(ty);
1055+
if n_src_refs >= 2 && src.is_array() {
1056+
return;
1057+
}
1058+
}
1059+
1060+
let (prefix, precedence) = match mutability {
1061+
Some(mutability) if !ty.is_ref() => {
1062+
let prefix = match mutability {
1063+
Mutability::Not => "&",
1064+
Mutability::Mut => "&mut ",
1065+
};
1066+
(prefix, PREC_PREFIX)
1067+
},
1068+
None if !ty.is_ref() && data.adjusted_ty.is_ref() => ("&", 0),
1069+
_ => ("", 0),
10571070
};
10581071
span_lint_hir_and_then(
10591072
cx,

clippy_utils/src/lib.rs

+11
Original file line numberDiff line numberDiff line change
@@ -2471,6 +2471,17 @@ pub fn peel_hir_ty_refs<'a>(mut ty: &'a hir::Ty<'a>) -> (&'a hir::Ty<'a>, usize)
24712471
}
24722472
}
24732473

2474+
/// Peels off all references on the type. Returns the underlying type and the number of references
2475+
/// removed.
2476+
pub fn peel_middle_ty_refs(mut ty: Ty<'_>) -> (Ty<'_>, usize) {
2477+
let mut count = 0;
2478+
while let rustc_ty::Ref(_, dest_ty, _) = ty.kind() {
2479+
ty = *dest_ty;
2480+
count += 1;
2481+
}
2482+
(ty, count)
2483+
}
2484+
24742485
/// Removes `AddrOf` operators (`&`) or deref operators (`*`), but only if a reference type is
24752486
/// dereferenced. An overloaded deref such as `Vec` to slice would not be removed.
24762487
pub fn peel_ref_operators<'hir>(cx: &LateContext<'_>, mut expr: &'hir Expr<'hir>) -> &'hir Expr<'hir> {

tests/ui/explicit_auto_deref.fixed

+6-2
Original file line numberDiff line numberDiff line change
@@ -364,13 +364,17 @@ mod issue_12969 {
364364
fn bar() {
365365
let wrapped_bar = Wrapper("");
366366

367-
foo(wrapped_bar);
367+
foo(&wrapped_bar);
368368
}
369369
}
370370

371371
mod issue_9841 {
372372
fn takes_array_ref<T, const N: usize>(array: &&[T; N]) {
373-
takes_slice(array)
373+
takes_slice(*array)
374+
}
375+
376+
fn takes_array_ref_ref<T, const N: usize>(array: &&&[T; N]) {
377+
takes_slice(**array)
374378
}
375379

376380
fn takes_slice<T>(slice: &[T]) {

tests/ui/explicit_auto_deref.rs

+4
Original file line numberDiff line numberDiff line change
@@ -373,6 +373,10 @@ mod issue_9841 {
373373
takes_slice(*array)
374374
}
375375

376+
fn takes_array_ref_ref<T, const N: usize>(array: &&&[T; N]) {
377+
takes_slice(**array)
378+
}
379+
376380
fn takes_slice<T>(slice: &[T]) {
377381
todo!()
378382
}

tests/ui/explicit_auto_deref.stderr

+2-8
Original file line numberDiff line numberDiff line change
@@ -275,13 +275,7 @@ error: deref which would be done by auto-deref
275275
--> tests/ui/explicit_auto_deref.rs:367:13
276276
|
277277
LL | foo(&*wrapped_bar);
278-
| ^^^^^^^^^^^^^ help: try: `wrapped_bar`
278+
| ^^^^^^^^^^^^^ help: try: `&wrapped_bar`
279279

280-
error: deref which would be done by auto-deref
281-
--> tests/ui/explicit_auto_deref.rs:373:21
282-
|
283-
LL | takes_slice(*array)
284-
| ^^^^^^ help: try: `array`
285-
286-
error: aborting due to 47 previous errors
280+
error: aborting due to 46 previous errors
287281

0 commit comments

Comments
 (0)