diff --git a/clippy_lints/src/dereference.rs b/clippy_lints/src/dereference.rs index cd1ad57ee828..4335e637936c 100644 --- a/clippy_lints/src/dereference.rs +++ b/clippy_lints/src/dereference.rs @@ -6,19 +6,21 @@ use clippy_utils::ty::{ adjust_derefs_manually_drop, get_adt_inherent_method, implements_trait, is_manually_drop, peel_and_count_ty_refs, }; use clippy_utils::{ - DefinedTy, ExprUseNode, get_expr_use_site, get_parent_expr, is_block_like, is_from_proc_macro, is_lint_allowed, sym, + DefinedTy, ExprUseNode, expr_use_sites, get_expr_use_site, get_parent_expr, is_block_like, is_from_proc_macro, + is_lint_allowed, sym, }; use rustc_ast::util::parser::ExprPrecedence; use rustc_data_structures::fx::FxIndexMap; use rustc_errors::Applicability; +use rustc_hir::attrs::{AttributeKind, HasAttrs as _}; use rustc_hir::def_id::DefId; use rustc_hir::intravisit::{InferKind, Visitor, VisitorExt as _, walk_ty}; use rustc_hir::{ - self as hir, AmbigArg, BindingMode, Body, BodyId, BorrowKind, Expr, ExprKind, HirId, Item, MatchSource, Mutability, - Node, OwnerId, Pat, PatKind, Path, QPath, TyKind, UnOp, + self as hir, AmbigArg, Attribute, BindingMode, Body, BodyId, BorrowKind, Expr, ExprKind, HirId, Item, MatchSource, + Mutability, Node, OwnerId, Pat, PatKind, Path, QPath, TyKind, UnOp, }; use rustc_lint::{LateContext, LateLintPass}; -use rustc_middle::ty::adjustment::{Adjust, Adjustment, AutoBorrow, AutoBorrowMutability}; +use rustc_middle::ty::adjustment::{Adjust, Adjustment, AutoBorrow, AutoBorrowMutability, DerefAdjustKind}; use rustc_middle::ty::{self, AssocTag, Ty, TyCtxt, TypeVisitableExt as _, TypeckResults, Unnormalized}; use rustc_session::impl_lint_pass; use rustc_span::{Span, Symbol, SyntaxContext}; @@ -275,6 +277,10 @@ impl<'tcx> LateLintPass<'tcx> for Dereferencing<'tcx> { return; } + if need_explicit_ref(cx, typeck, expr) { + return; + } + match (self.state.take(), kind) { (None, kind) => { let expr_ty = typeck.expr_ty(expr); @@ -441,6 +447,7 @@ impl<'tcx> LateLintPass<'tcx> for Dereferencing<'tcx> { true } }, + ExprUseNode::Index(base, _) if expr.hir_id == base.hir_id => true, _ => false, }; @@ -732,6 +739,94 @@ impl<'tcx> LateLintPass<'tcx> for Dereferencing<'tcx> { } } +// Issue: https://github.com/rust-lang/rust-clippy/issues/17414 +// Related: https://doc.rust-lang.org/beta/nightly-rustc/rustc_lint/autorefs/static.DANGEROUS_IMPLICIT_AUTOREFS.html +// A raw pointer need explicit ref to prevent from dangerous_implicit_autorefs. +// Recognize whether the ref of expr must be explicit. Similar Logic to `rustc_lint::autorefs` . +// 1. expr is a AddrOf Ref. +// 2. Loop sub_expr of expr if sub_expr is index/field, and is a deref of a raw ptr at the end. +// 3. Not all raw ptr need explicit ref. Only if it is in a danger invoke chain. Will check in +// method check_invoke_chain_danger. +fn need_explicit_ref<'tcx>(cx: &LateContext<'tcx>, typeck: &'tcx TypeckResults<'tcx>, expr: &'tcx Expr<'tcx>) -> bool { + match expr.kind { + ExprKind::AddrOf(BorrowKind::Ref, _, mut sub_expr) => { + typeck + .expr_ty(loop { + match sub_expr.kind { + ExprKind::Index(e, _, _) | ExprKind::Field(e, _) => sub_expr = e, + ExprKind::Unary(UnOp::Deref, e) => break e, + _ => break sub_expr, + } + }) + .is_raw_ptr() + && check_invoke_chain_danger(cx, typeck, expr) + }, + _ => false, + } +} + +// Check expr whether in a danger invoke chain. +// 1. Loop use site of expr. +// 2. Get adjustments. +// 3. If adjs list pattern [N * Deref Adjust, 1 * AutoBorrow Adjust], means auto ref exist. +// 3. Get use node. +// 4. If node is field or index and auto ref exist, return true, else continue loop. +// 5. If method call, check method has `RustcNoImplicitAutorefs` attr. +fn check_invoke_chain_danger<'tcx>( + cx: &LateContext<'tcx>, + typeck: &'tcx TypeckResults<'tcx>, + mut expr: &'tcx Expr<'tcx>, +) -> bool { + while let Some(use_site) = expr_use_sites(cx.tcx, typeck, SyntaxContext::root(), expr).next() { + let adjs = peel_derefs_adjustments(use_site.adjustments); + let auto_ref = if adjs.len() == 1 { adjs.first() } else { None }.is_some_and(|adj| { + matches!( + adj.kind, + Adjust::Deref(DerefAdjustKind::Overloaded(_)) | Adjust::Borrow(AutoBorrow::Ref(_)) + ) + }); + + match use_site.node { + Node::Expr(use_expr) => match use_expr.kind { + ExprKind::Field(_, _) | ExprKind::Index(_, _, _) => { + if auto_ref { + return true; + } + expr = use_expr; + }, + ExprKind::MethodCall(_, _, _, _) => { + return auto_ref + && typeck.type_dependent_def_id(use_expr.hir_id).is_some_and(|fn_id| { + fn_id + .get_attrs(&cx.tcx) // can not use private micro find_attr!() + .iter() + .any(|attr| matches!(attr, Attribute::Parsed(AttributeKind::RustcNoImplicitAutorefs))) + }); + }, + _ => return false, + }, + _ => return false, + } + } + + false +} + +// same code from rustc_lint:auto_ref.rs +fn peel_derefs_adjustments<'a>(mut adjs: &'a [Adjustment<'a>]) -> &'a [Adjustment<'a>] { + while let [ + Adjustment { + kind: Adjust::Deref(_), .. + }, + end @ .., + ] = adjs + && !end.is_empty() + { + adjs = end; + } + adjs +} + fn is_deref_or_derefmut_impl(cx: &LateContext<'_>, item: &Item<'_>) -> bool { if let hir::ItemKind::Impl(impl_) = item.kind && let Some(of_trait) = impl_.of_trait @@ -1153,15 +1248,6 @@ impl<'tcx> Dereferencing<'tcx> { ); }, State::DerefedBorrow(state) => { - // Do not suggest removing a non-mandatory `&` in `&*rawptr` in an `unsafe` context, - // as this may make rustc trigger its `dangerous_implicit_autorefs` lint. - if let ExprKind::AddrOf(BorrowKind::Ref, _, subexpr) = data.first_expr.kind - && let ExprKind::Unary(UnOp::Deref, subsubexpr) = subexpr.kind - && cx.typeck_results().expr_ty_adjusted(subsubexpr).is_raw_ptr() - { - return; - } - let mut app = Applicability::MachineApplicable; let (snip, snip_is_macro) = snippet_with_context(cx, expr.span, data.first_expr.span.ctxt(), "..", &mut app); diff --git a/clippy_utils/src/lib.rs b/clippy_utils/src/lib.rs index 3eef8e6bca36..e3f1b0a3cac8 100644 --- a/clippy_utils/src/lib.rs +++ b/clippy_utils/src/lib.rs @@ -2547,6 +2547,7 @@ impl<'tcx> ExprUseSite<'tcx> { ), ExprKind::Field(_, name) => ExprUseNode::FieldAccess(name), ExprKind::AddrOf(kind, mutbl, _) => ExprUseNode::AddrOf(kind, mutbl), + ExprKind::Index(base, idx, _) => ExprUseNode::Index(base, idx), _ => ExprUseNode::Other, }, _ => ExprUseNode::Other, @@ -2574,6 +2575,8 @@ pub enum ExprUseNode<'tcx> { FieldAccess(Ident), /// Borrow expression. AddrOf(ast::BorrowKind, Mutability), + /// Index operation: base, index num + Index(&'tcx Expr<'tcx>, &'tcx Expr<'tcx>), Other, } impl<'tcx> ExprUseNode<'tcx> { @@ -2651,7 +2654,12 @@ impl<'tcx> ExprUseNode<'tcx> { ty: sig.input(i), }) }, - Self::LetStmt(_) | Self::FieldAccess(..) | Self::Callee | Self::Other | Self::AddrOf(..) => None, + Self::LetStmt(_) + | Self::FieldAccess(..) + | Self::Callee + | Self::Other + | Self::AddrOf(..) + | Self::Index(..) => None, } } } diff --git a/tests/ui/needless_borrow.fixed b/tests/ui/needless_borrow.fixed index fd17fbb7c093..9648c02ba80c 100644 --- a/tests/ui/needless_borrow.fixed +++ b/tests/ui/needless_borrow.fixed @@ -5,6 +5,8 @@ clippy::unnecessary_mut_passed )] +use std::ops::Index; + fn main() { let a = 5; let ref_a = &a; @@ -294,3 +296,79 @@ fn issue_14743(slice: &[T]) { #[expect(dangerous_implicit_autorefs)] let _ = unsafe { (*slice).len() }; } + +fn issue_17414( + slice: &(i32, (i32, [usize])), + tuple_slice: *const (i32, [usize]), + nested_tuple: *const (i32, (i32, [usize])), +) { + let _ = slice.1.1.len(); + //~^ needless_borrow + let _ = slice.1.1.len(); + //~^ needless_borrow + let _ = slice.1.1.len(); + //~^ needless_borrow + + unsafe { + // Rule: `rustc_lint:autoref.rs` require explicit ref to arg from a [inner] derefed raw pointer + // when calling a #[rustc_no_implicit_autorefs] method. + + // 1. Issue 17414 case: deref tuple, get slice field, call [].len() method. + let _ = (&(*tuple_slice).1).len(); // necessary borrow, no lint + + // 2. simple slice + let a = [0, 1, 2]; + let b = &raw const a[0..2]; // same with raw const or raw mut + let _ = (&*b).len(); // necessary + let _ = (&*b).index(0); // necessary + let _: i32 = (*b)[0]; // success + + let _: i32 = (*b)[0]; + //~^ needless_borrow + + // 3. nested tuple + let _ = (&*nested_tuple).1.1.len(); // necessary + let _ = (&(*nested_tuple).1).1.len(); // necessary + let _ = (&(*nested_tuple).1.1).len(); // necessary + + let _ = (*nested_tuple).1.1.first(); // success + + let _ = (*nested_tuple).1.1.first(); + //~^ needless_borrow + let _ = (*nested_tuple).1.1.first(); + //~^ needless_borrow + let _ = (*nested_tuple).1.1.first(); + //~^ needless_borrow + + // 4. array + let a = [1, 2, 3]; + let b: *const [i32; 3] = &raw const a; + // let _ = (*b).index(0); // fail + let _ = (&*b).index(0); // necessary + + let _ = (*b)[0]; // ok + let _ = (*b)[0]; + //~^ needless_borrow + + // 5. trait + trait T: Index {} + struct S {} + impl Index for S { + type Output = i32; + // no attr, defined in super.index + fn index(&self, _: usize) -> &i32 { + &42 + } + } + impl T for S {} + + let s = S {}; + let t: &dyn T = &s; + let ptr: *const dyn T = t; + + // let _ = (*ptr)[0]; // fail + let _ = (&*ptr)[0]; // necessary + // let _ = (*ptr).index(0); // fail + let _ = (&*ptr).index(0); // necessary + } +} diff --git a/tests/ui/needless_borrow.rs b/tests/ui/needless_borrow.rs index a96252bcb3be..b083a2e90e7a 100644 --- a/tests/ui/needless_borrow.rs +++ b/tests/ui/needless_borrow.rs @@ -5,6 +5,8 @@ clippy::unnecessary_mut_passed )] +use std::ops::Index; + fn main() { let a = 5; let ref_a = &a; @@ -294,3 +296,79 @@ fn issue_14743(slice: &[T]) { #[expect(dangerous_implicit_autorefs)] let _ = unsafe { (*slice).len() }; } + +fn issue_17414( + slice: &(i32, (i32, [usize])), + tuple_slice: *const (i32, [usize]), + nested_tuple: *const (i32, (i32, [usize])), +) { + let _ = (&slice).1.1.len(); + //~^ needless_borrow + let _ = (&slice.1).1.len(); + //~^ needless_borrow + let _ = (&slice.1.1).len(); + //~^ needless_borrow + + unsafe { + // Rule: `rustc_lint:autoref.rs` require explicit ref to arg from a [inner] derefed raw pointer + // when calling a #[rustc_no_implicit_autorefs] method. + + // 1. Issue 17414 case: deref tuple, get slice field, call [].len() method. + let _ = (&(*tuple_slice).1).len(); // necessary borrow, no lint + + // 2. simple slice + let a = [0, 1, 2]; + let b = &raw const a[0..2]; // same with raw const or raw mut + let _ = (&*b).len(); // necessary + let _ = (&*b).index(0); // necessary + let _: i32 = (*b)[0]; // success + + let _: i32 = (&*b)[0]; + //~^ needless_borrow + + // 3. nested tuple + let _ = (&*nested_tuple).1.1.len(); // necessary + let _ = (&(*nested_tuple).1).1.len(); // necessary + let _ = (&(*nested_tuple).1.1).len(); // necessary + + let _ = (*nested_tuple).1.1.first(); // success + + let _ = (&*nested_tuple).1.1.first(); + //~^ needless_borrow + let _ = (&(*nested_tuple).1).1.first(); + //~^ needless_borrow + let _ = (&(*nested_tuple).1.1).first(); + //~^ needless_borrow + + // 4. array + let a = [1, 2, 3]; + let b: *const [i32; 3] = &raw const a; + // let _ = (*b).index(0); // fail + let _ = (&*b).index(0); // necessary + + let _ = (*b)[0]; // ok + let _ = (&*b)[0]; + //~^ needless_borrow + + // 5. trait + trait T: Index {} + struct S {} + impl Index for S { + type Output = i32; + // no attr, defined in super.index + fn index(&self, _: usize) -> &i32 { + &42 + } + } + impl T for S {} + + let s = S {}; + let t: &dyn T = &s; + let ptr: *const dyn T = t; + + // let _ = (*ptr)[0]; // fail + let _ = (&*ptr)[0]; // necessary + // let _ = (*ptr).index(0); // fail + let _ = (&*ptr).index(0); // necessary + } +} diff --git a/tests/ui/needless_borrow.stderr b/tests/ui/needless_borrow.stderr index e7a488b9ed92..eee7579e42b3 100644 --- a/tests/ui/needless_borrow.stderr +++ b/tests/ui/needless_borrow.stderr @@ -1,5 +1,5 @@ error: this expression creates a reference which is immediately dereferenced by the compiler - --> tests/ui/needless_borrow.rs:12:15 + --> tests/ui/needless_borrow.rs:14:15 | LL | let _ = x(&&a); // warn | ^^^ help: change this to: `&a` @@ -8,166 +8,214 @@ LL | let _ = x(&&a); // warn = help: to override `-D warnings` add `#[allow(clippy::needless_borrow)]` error: this expression creates a reference which is immediately dereferenced by the compiler - --> tests/ui/needless_borrow.rs:18:13 + --> tests/ui/needless_borrow.rs:20:13 | LL | mut_ref(&mut &mut b); // warn | ^^^^^^^^^^^ help: change this to: `&mut b` error: this expression creates a reference which is immediately dereferenced by the compiler - --> tests/ui/needless_borrow.rs:32:13 + --> tests/ui/needless_borrow.rs:34:13 | LL | &&a | ^^^ help: change this to: `&a` error: this expression creates a reference which is immediately dereferenced by the compiler - --> tests/ui/needless_borrow.rs:35:15 + --> tests/ui/needless_borrow.rs:37:15 | LL | 46 => &&a, | ^^^ help: change this to: `&a` error: this expression creates a reference which is immediately dereferenced by the compiler - --> tests/ui/needless_borrow.rs:42:27 + --> tests/ui/needless_borrow.rs:44:27 | LL | break &ref_a; | ^^^^^^ help: change this to: `ref_a` error: this expression creates a reference which is immediately dereferenced by the compiler - --> tests/ui/needless_borrow.rs:50:15 + --> tests/ui/needless_borrow.rs:52:15 | LL | let _ = x(&&&a); | ^^^^ help: change this to: `&a` error: this expression creates a reference which is immediately dereferenced by the compiler - --> tests/ui/needless_borrow.rs:52:15 + --> tests/ui/needless_borrow.rs:54:15 | LL | let _ = x(&mut &&a); | ^^^^^^^^ help: change this to: `&a` error: this expression creates a reference which is immediately dereferenced by the compiler - --> tests/ui/needless_borrow.rs:54:15 + --> tests/ui/needless_borrow.rs:56:15 | LL | let _ = x(&&&mut b); | ^^^^^^^^ help: change this to: `&mut b` error: this expression creates a reference which is immediately dereferenced by the compiler - --> tests/ui/needless_borrow.rs:56:15 + --> tests/ui/needless_borrow.rs:58:15 | LL | let _ = x(&&ref_a); | ^^^^^^^ help: change this to: `ref_a` error: this expression creates a reference which is immediately dereferenced by the compiler - --> tests/ui/needless_borrow.rs:60:11 + --> tests/ui/needless_borrow.rs:62:11 | LL | x(&b); | ^^ help: change this to: `b` error: this expression creates a reference which is immediately dereferenced by the compiler - --> tests/ui/needless_borrow.rs:68:13 + --> tests/ui/needless_borrow.rs:70:13 | LL | mut_ref(&mut x); | ^^^^^^ help: change this to: `x` error: this expression creates a reference which is immediately dereferenced by the compiler - --> tests/ui/needless_borrow.rs:70:13 + --> tests/ui/needless_borrow.rs:72:13 | LL | mut_ref(&mut &mut x); | ^^^^^^^^^^^ help: change this to: `x` error: this expression creates a reference which is immediately dereferenced by the compiler - --> tests/ui/needless_borrow.rs:72:23 + --> tests/ui/needless_borrow.rs:74:23 | LL | let y: &mut i32 = &mut x; | ^^^^^^ help: change this to: `x` error: this expression creates a reference which is immediately dereferenced by the compiler - --> tests/ui/needless_borrow.rs:74:23 + --> tests/ui/needless_borrow.rs:76:23 | LL | let y: &mut i32 = &mut &mut x; | ^^^^^^^^^^^ help: change this to: `x` error: this expression creates a reference which is immediately dereferenced by the compiler - --> tests/ui/needless_borrow.rs:84:14 + --> tests/ui/needless_borrow.rs:86:14 | LL | 0 => &mut x, | ^^^^^^ help: change this to: `x` error: this expression creates a reference which is immediately dereferenced by the compiler - --> tests/ui/needless_borrow.rs:91:14 + --> tests/ui/needless_borrow.rs:93:14 | LL | 0 => &mut x, | ^^^^^^ help: change this to: `x` error: this expression borrows a value the compiler would automatically borrow - --> tests/ui/needless_borrow.rs:104:13 + --> tests/ui/needless_borrow.rs:106:13 | LL | let _ = (&x).0; | ^^^^ help: change this to: `x` error: this expression creates a reference which is immediately dereferenced by the compiler - --> tests/ui/needless_borrow.rs:115:5 + --> tests/ui/needless_borrow.rs:117:5 | LL | (&&()).foo(); | ^^^^^^ help: change this to: `(&())` error: this expression creates a reference which is immediately dereferenced by the compiler - --> tests/ui/needless_borrow.rs:125:5 + --> tests/ui/needless_borrow.rs:127:5 | LL | (&&5).foo(); | ^^^^^ help: change this to: `(&5)` error: this expression creates a reference which is immediately dereferenced by the compiler - --> tests/ui/needless_borrow.rs:152:23 + --> tests/ui/needless_borrow.rs:154:23 | LL | let x: (&str,) = (&"",); | ^^^ help: change this to: `""` error: this expression borrows a value the compiler would automatically borrow - --> tests/ui/needless_borrow.rs:195:13 + --> tests/ui/needless_borrow.rs:197:13 | LL | (&self.f)() | ^^^^^^^^^ help: change this to: `(self.f)` error: this expression borrows a value the compiler would automatically borrow - --> tests/ui/needless_borrow.rs:205:13 + --> tests/ui/needless_borrow.rs:207:13 | LL | (&mut self.f)() | ^^^^^^^^^^^^^ help: change this to: `(self.f)` error: this expression borrows a value the compiler would automatically borrow - --> tests/ui/needless_borrow.rs:243:22 + --> tests/ui/needless_borrow.rs:245:22 | LL | let _ = &mut (&mut { x.u }).x; | ^^^^^^^^^^^^^^ help: change this to: `{ x.u }` error: this expression borrows a value the compiler would automatically borrow - --> tests/ui/needless_borrow.rs:251:22 + --> tests/ui/needless_borrow.rs:253:22 | LL | let _ = &mut (&mut { x.u }).x; | ^^^^^^^^^^^^^^ help: change this to: `{ x.u }` error: this expression borrows a value the compiler would automatically borrow - --> tests/ui/needless_borrow.rs:256:22 + --> tests/ui/needless_borrow.rs:258:22 | LL | let _ = &mut (&mut x.u).x; | ^^^^^^^^^^ help: change this to: `x.u` error: this expression borrows a value the compiler would automatically borrow - --> tests/ui/needless_borrow.rs:258:22 + --> tests/ui/needless_borrow.rs:260:22 | LL | let _ = &mut (&mut { x.u }).x; | ^^^^^^^^^^^^^^ help: change this to: `{ x.u }` error: this expression creates a reference which is immediately dereferenced by the compiler - --> tests/ui/needless_borrow.rs:280:23 + --> tests/ui/needless_borrow.rs:282:23 | LL | option.unwrap_or((&x.0,)); | ^^^^ help: change this to: `x.0` error: this expression creates a reference which is immediately dereferenced by the compiler - --> tests/ui/needless_borrow.rs:287:13 + --> tests/ui/needless_borrow.rs:289:13 | LL | let _ = (&slice).len(); | ^^^^^^^^ help: change this to: `slice` -error: aborting due to 28 previous errors +error: this expression creates a reference which is immediately dereferenced by the compiler + --> tests/ui/needless_borrow.rs:305:13 + | +LL | let _ = (&slice).1.1.len(); + | ^^^^^^^^ help: change this to: `slice` + +error: this expression borrows a value the compiler would automatically borrow + --> tests/ui/needless_borrow.rs:307:13 + | +LL | let _ = (&slice.1).1.len(); + | ^^^^^^^^^^ help: change this to: `slice.1` + +error: this expression borrows a value the compiler would automatically borrow + --> tests/ui/needless_borrow.rs:309:13 + | +LL | let _ = (&slice.1.1).len(); + | ^^^^^^^^^^^^ help: change this to: `slice.1.1` + +error: this expression borrows a value the compiler would automatically borrow + --> tests/ui/needless_borrow.rs:326:22 + | +LL | let _: i32 = (&*b)[0]; + | ^^^^^ help: change this to: `(*b)` + +error: this expression borrows a value the compiler would automatically borrow + --> tests/ui/needless_borrow.rs:336:17 + | +LL | let _ = (&*nested_tuple).1.1.first(); + | ^^^^^^^^^^^^^^^^ help: change this to: `(*nested_tuple)` + +error: this expression borrows a value the compiler would automatically borrow + --> tests/ui/needless_borrow.rs:338:17 + | +LL | let _ = (&(*nested_tuple).1).1.first(); + | ^^^^^^^^^^^^^^^^^^^^ help: change this to: `(*nested_tuple).1` + +error: this expression borrows a value the compiler would automatically borrow + --> tests/ui/needless_borrow.rs:340:17 + | +LL | let _ = (&(*nested_tuple).1.1).first(); + | ^^^^^^^^^^^^^^^^^^^^^^ help: change this to: `(*nested_tuple).1.1` + +error: this expression borrows a value the compiler would automatically borrow + --> tests/ui/needless_borrow.rs:350:17 + | +LL | let _ = (&*b)[0]; + | ^^^^^ help: change this to: `(*b)` + +error: aborting due to 36 previous errors diff --git a/tests/ui/redundant_slicing.fixed b/tests/ui/redundant_slicing.fixed index 2d194fa6f7b1..413e25e8aad2 100644 --- a/tests/ui/redundant_slicing.fixed +++ b/tests/ui/redundant_slicing.fixed @@ -1,5 +1,6 @@ #![warn(clippy::redundant_slicing)] #![expect(clippy::deref_by_slicing)] +#![allow(clippy::needless_borrow)] use std::io::Read; diff --git a/tests/ui/redundant_slicing.rs b/tests/ui/redundant_slicing.rs index 74fc86993a86..30e737d4e8fe 100644 --- a/tests/ui/redundant_slicing.rs +++ b/tests/ui/redundant_slicing.rs @@ -1,5 +1,6 @@ #![warn(clippy::redundant_slicing)] #![expect(clippy::deref_by_slicing)] +#![allow(clippy::needless_borrow)] use std::io::Read; diff --git a/tests/ui/redundant_slicing.stderr b/tests/ui/redundant_slicing.stderr index 964111bccf88..db1b8d4210fa 100644 --- a/tests/ui/redundant_slicing.stderr +++ b/tests/ui/redundant_slicing.stderr @@ -1,5 +1,5 @@ error: redundant slicing of the whole range - --> tests/ui/redundant_slicing.rs:8:13 + --> tests/ui/redundant_slicing.rs:9:13 | LL | let _ = &slice[..]; // Redundant slice | ^^^^^^^^^^ help: use the original value instead: `slice` @@ -8,13 +8,13 @@ LL | let _ = &slice[..]; // Redundant slice = help: to override `-D warnings` add `#[allow(clippy::redundant_slicing)]` error: redundant slicing of the whole range - --> tests/ui/redundant_slicing.rs:14:13 + --> tests/ui/redundant_slicing.rs:15:13 | LL | let _ = &(&*v)[..]; // Outer borrow is redundant | ^^^^^^^^^^ help: use the original value instead: `(&*v)` error: redundant slicing of the whole range - --> tests/ui/redundant_slicing.rs:33:13 + --> tests/ui/redundant_slicing.rs:34:13 | LL | let _ = &m!(slice)[..]; | ^^^^^^^^^^^^^^ help: use the original value instead: `slice`