From 9e9110e4f3fd8d982dbde873b0c5168b8a3968ed Mon Sep 17 00:00:00 2001 From: Jason Newcomb Date: Tue, 11 Jan 2022 14:31:35 -0500 Subject: [PATCH] Remove final reference on fields and method calls in `needless_borrow` --- CHANGELOG.md | 2 +- clippy_lints/src/dereference.rs | 210 +++++++++++++++++---------- clippy_lints/src/implicit_hasher.rs | 2 +- clippy_lints/src/octal_escapes.rs | 2 +- clippy_utils/src/sugg.rs | 2 +- tests/ui/bytecount.rs | 2 + tests/ui/bytecount.stderr | 8 +- tests/ui/clone_on_copy.fixed | 3 +- tests/ui/clone_on_copy.rs | 3 +- tests/ui/clone_on_copy.stderr | 16 +- tests/ui/duration_subsec.fixed | 2 +- tests/ui/duration_subsec.rs | 2 +- tests/ui/eta.fixed | 9 +- tests/ui/eta.rs | 7 +- tests/ui/eta.stderr | 50 +++---- tests/ui/for_loop_fixable.fixed | 7 +- tests/ui/for_loop_fixable.rs | 7 +- tests/ui/for_loop_fixable.stderr | 30 ++-- tests/ui/needless_borrow.fixed | 10 ++ tests/ui/needless_borrow.rs | 10 ++ tests/ui/needless_borrow.stderr | 74 ++++++++-- tests/ui/useless_asref.fixed | 2 +- tests/ui/useless_asref.rs | 2 +- tests/ui/write_literal.rs | 48 +++--- tests/ui/write_literal.stderr | 110 +++++++------- tests/ui/write_literal_2.rs | 16 +- tests/ui/write_literal_2.stderr | 50 +++---- tests/ui/write_with_newline.rs | 56 +++---- tests/ui/write_with_newline.stderr | 72 ++++----- tests/ui/writeln_empty_string.fixed | 10 +- tests/ui/writeln_empty_string.rs | 10 +- tests/ui/writeln_empty_string.stderr | 12 +- 32 files changed, 484 insertions(+), 362 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 258a8256f53..8e65a799ead 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -981,7 +981,7 @@ Released 2021-03-25 [#6532](https://github.com/rust-lang/rust-clippy/pull/6532) * [`single_match`] Suggest `if` over `if let` when possible [#6574](https://github.com/rust-lang/rust-clippy/pull/6574) -* [`ref_in_deref`] Use parentheses correctly in suggestion +* `ref_in_deref` Use parentheses correctly in suggestion [#6609](https://github.com/rust-lang/rust-clippy/pull/6609) * [`stable_sort_primitive`] Clarify error message [#6611](https://github.com/rust-lang/rust-clippy/pull/6611) diff --git a/clippy_lints/src/dereference.rs b/clippy_lints/src/dereference.rs index 9645f1a03be..70f45646596 100644 --- a/clippy_lints/src/dereference.rs +++ b/clippy_lints/src/dereference.rs @@ -1,5 +1,6 @@ use clippy_utils::diagnostics::{span_lint_and_sugg, span_lint_and_then}; use clippy_utils::source::{snippet_with_applicability, snippet_with_context}; +use clippy_utils::sugg::has_enclosing_paren; use clippy_utils::ty::peel_mid_ty_refs; use clippy_utils::{get_parent_expr, get_parent_node, is_lint_allowed, path_to_local}; use rustc_ast::util::parser::{PREC_POSTFIX, PREC_PREFIX}; @@ -130,8 +131,6 @@ pub struct Dereferencing { struct StateData { /// Span of the top level expression span: Span, - /// The required mutability - target_mut: Mutability, } enum State { @@ -140,9 +139,13 @@ enum State { // The number of calls in a sequence which changed the referenced type ty_changed_count: usize, is_final_ufcs: bool, + /// The required mutability + target_mut: Mutability, }, DerefedBorrow { - count: u32, + count: usize, + required_precedence: i8, + msg: &'static str, }, } @@ -213,77 +216,98 @@ impl<'tcx> LateLintPass<'tcx> for Dereferencing { 1 }, is_final_ufcs: matches!(expr.kind, ExprKind::Call(..)), - }, - StateData { - span: expr.span, target_mut, }, + StateData { span: expr.span }, )); }, RefOp::AddrOf => { // Find the number of times the borrow is auto-derefed. let mut iter = find_adjustments(cx.tcx, typeck, expr).iter(); - if let Some((i, adjust)) = iter.by_ref().enumerate().find_map(|(i, adjust)| { - if !matches!(adjust.kind, Adjust::Deref(_)) { - Some((i, Some(adjust))) - } else if !adjust.target.is_ref() { - // Include the current deref. - Some((i + 1, None)) - } else { - None - } - }) { - if i > 1 { - // If the next adjustment is a mutable borrow, then check to see if the compiler will - // insert a re-borrow here. If not, leave an extra borrow here to avoid attempting to - // move the a mutable reference. - let (i, target_mut) = if let Some(&Adjust::Borrow(AutoBorrow::Ref(_, mutability))) = - adjust.or_else(|| iter.next()).map(|a| &a.kind) - { - if matches!(mutability, AutoBorrowMutability::Mut { .. }) - && !is_auto_reborrow_position(parent, expr.hir_id) - { - (i - 1, Mutability::Mut) - } else { - (i, mutability.into()) + let mut deref_count = 0usize; + let next_adjust = loop { + match iter.next() { + Some(adjust) => { + if !matches!(adjust.kind, Adjust::Deref(_)) { + break Some(adjust); + } else if !adjust.target.is_ref() { + deref_count += 1; + break iter.next(); } - } else { - ( - i, - iter.find_map(|adjust| match adjust.kind { - Adjust::Borrow(AutoBorrow::Ref(_, m)) => Some(m.into()), - _ => None, - }) - // This default should never happen. Auto-deref always reborrows. - .unwrap_or(Mutability::Not), - ) - }; + deref_count += 1; + }, + None => break None, + }; + }; - if i > 1 { - self.state = Some(( - // Subtract one for the current borrow expression, and one to cover the last - // reference which can't be removed (it's either reborrowed, or needed for - // auto-deref to happen). - State::DerefedBorrow { - count: - // Truncation here would require more than a `u32::MAX` level reference. The compiler - // does not support this. - #[allow(clippy::cast_possible_truncation)] - { i as u32 - 2 } - }, - StateData { - span: expr.span, - target_mut, - }, - )); - } + // Determine the required number of references before any can be removed. In all cases the + // reference made by the current expression will be removed. After that there are four cases to + // handle. + // + // 1. Auto-borrow will trigger in the current position, so no further references are required. + // 2. Auto-deref ends at a reference, or the underlying type, so one extra needs to be left to + // handle the automatically inserted re-borrow. + // 3. Auto-deref hits a user-defined `Deref` impl, so at least one reference needs to exist to + // start auto-deref. + // 4. If the chain of non-user-defined derefs ends with a mutable re-borrow, and re-borrow + // adjustments will not be inserted automatically, then leave one further reference to avoid + // moving a mutable borrow. + // e.g. + // fn foo(x: &mut Option<&mut T>, y: &mut T) { + // let x = match x { + // // Removing the borrow will cause `x` to be moved + // Some(x) => &mut *x, + // None => y + // }; + // } + let deref_msg = + "this expression creates a reference which is immediately dereferenced by the compiler"; + let borrow_msg = "this expression borrows a value the compiler would automatically borrow"; + + let (required_refs, required_precedence, msg) = if is_auto_borrow_position(parent, expr.hir_id) + { + (1, PREC_POSTFIX, if deref_count == 1 { borrow_msg } else { deref_msg }) + } else if let Some(&Adjust::Borrow(AutoBorrow::Ref(_, mutability))) = + next_adjust.map(|a| &a.kind) + { + if matches!(mutability, AutoBorrowMutability::Mut { .. }) + && !is_auto_reborrow_position(parent) + { + (3, 0, deref_msg) + } else { + (2, 0, deref_msg) } + } else { + (2, 0, deref_msg) + }; + + if deref_count >= required_refs { + self.state = Some(( + State::DerefedBorrow { + // One of the required refs is for the current borrow expression, the remaining ones + // can't be removed without breaking the code. See earlier comment. + count: deref_count - required_refs, + required_precedence, + msg, + }, + StateData { span: expr.span }, + )); } }, _ => (), } }, - (Some((State::DerefMethod { ty_changed_count, .. }, data)), RefOp::Method(_)) => { + ( + Some(( + State::DerefMethod { + target_mut, + ty_changed_count, + .. + }, + data, + )), + RefOp::Method(_), + ) => { self.state = Some(( State::DerefMethod { ty_changed_count: if deref_method_same_type(typeck.expr_ty(expr), typeck.expr_ty(sub_expr)) { @@ -292,12 +316,30 @@ impl<'tcx> LateLintPass<'tcx> for Dereferencing { ty_changed_count + 1 }, is_final_ufcs: matches!(expr.kind, ExprKind::Call(..)), + target_mut, }, data, )); }, - (Some((State::DerefedBorrow { count }, data)), RefOp::AddrOf) if count != 0 => { - self.state = Some((State::DerefedBorrow { count: count - 1 }, data)); + ( + Some(( + State::DerefedBorrow { + count, + required_precedence, + msg, + }, + data, + )), + RefOp::AddrOf, + ) if count != 0 => { + self.state = Some(( + State::DerefedBorrow { + count: count - 1, + required_precedence, + msg, + }, + data, + )); }, (Some((state, data)), _) => report(cx, expr, state, data), @@ -475,18 +517,28 @@ fn is_linted_explicit_deref_position(parent: Option>, child_id: HirId, /// Checks if the given expression is in a position which can be auto-reborrowed. /// Note: This is only correct assuming auto-deref is already occurring. -fn is_auto_reborrow_position(parent: Option>, child_id: HirId) -> bool { +fn is_auto_reborrow_position(parent: Option>) -> bool { match parent { - Some(Node::Expr(parent)) => match parent.kind { - ExprKind::MethodCall(..) => true, - ExprKind::Call(callee, _) => callee.hir_id != child_id, - _ => false, - }, + Some(Node::Expr(parent)) => matches!(parent.kind, ExprKind::MethodCall(..) | ExprKind::Call(..)), Some(Node::Local(_)) => true, _ => false, } } +/// Checks if the given expression is a position which can auto-borrow. +fn is_auto_borrow_position(parent: Option>, child_id: HirId) -> bool { + if let Some(Node::Expr(parent)) = parent { + match parent.kind { + ExprKind::MethodCall(_, _, [self_arg, ..], _) => self_arg.hir_id == child_id, + ExprKind::Field(..) => true, + ExprKind::Call(f, _) => f.hir_id == child_id, + _ => false, + } + } else { + false + } +} + /// Adjustments are sometimes made in the parent block rather than the expression itself. fn find_adjustments<'tcx>( tcx: TyCtxt<'tcx>, @@ -535,6 +587,7 @@ fn report(cx: &LateContext<'_>, expr: &Expr<'_>, state: State, data: StateData) State::DerefMethod { ty_changed_count, is_final_ufcs, + target_mut, } => { let mut app = Applicability::MachineApplicable; let (expr_str, expr_is_macro_call) = snippet_with_context(cx, expr.span, data.span.ctxt(), "..", &mut app); @@ -549,12 +602,12 @@ fn report(cx: &LateContext<'_>, expr: &Expr<'_>, state: State, data: StateData) }; let addr_of_str = if ty_changed_count < ref_count { // Check if a reborrow from &mut T -> &T is required. - if data.target_mut == Mutability::Not && matches!(ty.kind(), ty::Ref(_, _, Mutability::Mut)) { + if target_mut == Mutability::Not && matches!(ty.kind(), ty::Ref(_, _, Mutability::Mut)) { "&*" } else { "" } - } else if data.target_mut == Mutability::Mut { + } else if target_mut == Mutability::Mut { "&mut " } else { "&" @@ -570,7 +623,7 @@ fn report(cx: &LateContext<'_>, expr: &Expr<'_>, state: State, data: StateData) cx, EXPLICIT_DEREF_METHODS, data.span, - match data.target_mut { + match target_mut { Mutability::Not => "explicit `deref` method call", Mutability::Mut => "explicit `deref_mut` method call", }, @@ -579,19 +632,24 @@ fn report(cx: &LateContext<'_>, expr: &Expr<'_>, state: State, data: StateData) app, ); }, - State::DerefedBorrow { .. } => { + State::DerefedBorrow { + required_precedence, + msg, + .. + } => { let mut app = Applicability::MachineApplicable; let snip = snippet_with_context(cx, expr.span, data.span.ctxt(), "..", &mut app).0; span_lint_and_sugg( cx, NEEDLESS_BORROW, data.span, - &format!( - "this expression borrows a reference (`{}`) that is immediately dereferenced by the compiler", - cx.typeck_results().expr_ty(expr), - ), + msg, "change this to", - snip.into(), + if required_precedence > expr.precedence().order() && !has_enclosing_paren(&snip) { + format!("({})", snip) + } else { + snip.into() + }, app, ); }, diff --git a/clippy_lints/src/implicit_hasher.rs b/clippy_lints/src/implicit_hasher.rs index 6358228dd47..2818b3e006a 100644 --- a/clippy_lints/src/implicit_hasher.rs +++ b/clippy_lints/src/implicit_hasher.rs @@ -179,7 +179,7 @@ impl<'tcx> LateLintPass<'tcx> for ImplicitHasher { ) .and_then(|snip| { let i = snip.find("fn")?; - Some(item.span.lo() + BytePos((i + (&snip[i..]).find('(')?) as u32)) + Some(item.span.lo() + BytePos((i + snip[i..].find('(')?) as u32)) }) .expect("failed to create span for type parameters"); Span::new(pos, pos, item.span.ctxt(), item.span.parent()) diff --git a/clippy_lints/src/octal_escapes.rs b/clippy_lints/src/octal_escapes.rs index e0da12f77fc..b446cf9b6c2 100644 --- a/clippy_lints/src/octal_escapes.rs +++ b/clippy_lints/src/octal_escapes.rs @@ -101,7 +101,7 @@ fn check_lit(cx: &EarlyContext<'_>, lit: &Lit, span: Span, is_string: bool) { // construct a replacement escape // the maximum value is \077, or \x3f, so u8 is sufficient here if let Ok(n) = u8::from_str_radix(&contents[from + 1..to], 8) { - write!(&mut suggest_1, "\\x{:02x}", n).unwrap(); + write!(suggest_1, "\\x{:02x}", n).unwrap(); } // append the null byte as \x00 and the following digits literally diff --git a/clippy_utils/src/sugg.rs b/clippy_utils/src/sugg.rs index 87bc8232dde..be1928045b8 100644 --- a/clippy_utils/src/sugg.rs +++ b/clippy_utils/src/sugg.rs @@ -388,7 +388,7 @@ fn binop_to_string(op: AssocOp, lhs: &str, rhs: &str) -> String { } /// Return `true` if `sugg` is enclosed in parenthesis. -fn has_enclosing_paren(sugg: impl AsRef) -> bool { +pub fn has_enclosing_paren(sugg: impl AsRef) -> bool { let mut chars = sugg.as_ref().chars(); if chars.next() == Some('(') { let mut depth = 1; diff --git a/tests/ui/bytecount.rs b/tests/ui/bytecount.rs index c724ee21be3..d3ad26921bf 100644 --- a/tests/ui/bytecount.rs +++ b/tests/ui/bytecount.rs @@ -1,3 +1,5 @@ +#![allow(clippy::needless_borrow)] + #[deny(clippy::naive_bytecount)] fn main() { let x = vec![0_u8; 16]; diff --git a/tests/ui/bytecount.stderr b/tests/ui/bytecount.stderr index 1dc37fc8b25..68d838c1f82 100644 --- a/tests/ui/bytecount.stderr +++ b/tests/ui/bytecount.stderr @@ -1,23 +1,23 @@ error: you appear to be counting bytes the naive way - --> $DIR/bytecount.rs:5:13 + --> $DIR/bytecount.rs:7:13 | LL | let _ = x.iter().filter(|&&a| a == 0).count(); // naive byte count | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using the bytecount crate: `bytecount::count(x, 0)` | note: the lint level is defined here - --> $DIR/bytecount.rs:1:8 + --> $DIR/bytecount.rs:3:8 | LL | #[deny(clippy::naive_bytecount)] | ^^^^^^^^^^^^^^^^^^^^^^^ error: you appear to be counting bytes the naive way - --> $DIR/bytecount.rs:7:13 + --> $DIR/bytecount.rs:9:13 | LL | let _ = (&x[..]).iter().filter(|&a| *a == 0).count(); // naive byte count | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using the bytecount crate: `bytecount::count((&x[..]), 0)` error: you appear to be counting bytes the naive way - --> $DIR/bytecount.rs:19:13 + --> $DIR/bytecount.rs:21:13 | LL | let _ = x.iter().filter(|a| b + 1 == **a).count(); // naive byte count | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using the bytecount crate: `bytecount::count(x, b + 1)` diff --git a/tests/ui/clone_on_copy.fixed b/tests/ui/clone_on_copy.fixed index 8d43f64768d..dc062762604 100644 --- a/tests/ui/clone_on_copy.fixed +++ b/tests/ui/clone_on_copy.fixed @@ -7,7 +7,8 @@ clippy::no_effect, clippy::unnecessary_operation, clippy::vec_init_then_push, - clippy::toplevel_ref_arg + clippy::toplevel_ref_arg, + clippy::needless_borrow )] use std::cell::RefCell; diff --git a/tests/ui/clone_on_copy.rs b/tests/ui/clone_on_copy.rs index f15501f7184..8c39d0d55dd 100644 --- a/tests/ui/clone_on_copy.rs +++ b/tests/ui/clone_on_copy.rs @@ -7,7 +7,8 @@ clippy::no_effect, clippy::unnecessary_operation, clippy::vec_init_then_push, - clippy::toplevel_ref_arg + clippy::toplevel_ref_arg, + clippy::needless_borrow )] use std::cell::RefCell; diff --git a/tests/ui/clone_on_copy.stderr b/tests/ui/clone_on_copy.stderr index e7d28b4320b..861543d0aa9 100644 --- a/tests/ui/clone_on_copy.stderr +++ b/tests/ui/clone_on_copy.stderr @@ -1,5 +1,5 @@ error: using `clone` on type `i32` which implements the `Copy` trait - --> $DIR/clone_on_copy.rs:24:5 + --> $DIR/clone_on_copy.rs:25:5 | LL | 42.clone(); | ^^^^^^^^^^ help: try removing the `clone` call: `42` @@ -7,43 +7,43 @@ LL | 42.clone(); = note: `-D clippy::clone-on-copy` implied by `-D warnings` error: using `clone` on type `i32` which implements the `Copy` trait - --> $DIR/clone_on_copy.rs:28:5 + --> $DIR/clone_on_copy.rs:29:5 | LL | (&42).clone(); | ^^^^^^^^^^^^^ help: try dereferencing it: `*(&42)` error: using `clone` on type `i32` which implements the `Copy` trait - --> $DIR/clone_on_copy.rs:31:5 + --> $DIR/clone_on_copy.rs:32:5 | LL | rc.borrow().clone(); | ^^^^^^^^^^^^^^^^^^^ help: try dereferencing it: `*rc.borrow()` error: using `clone` on type `u32` which implements the `Copy` trait - --> $DIR/clone_on_copy.rs:34:5 + --> $DIR/clone_on_copy.rs:35:5 | LL | x.clone().rotate_left(1); | ^^^^^^^^^ help: try removing the `clone` call: `x` error: using `clone` on type `i32` which implements the `Copy` trait - --> $DIR/clone_on_copy.rs:48:5 + --> $DIR/clone_on_copy.rs:49:5 | LL | m!(42).clone(); | ^^^^^^^^^^^^^^ help: try removing the `clone` call: `m!(42)` error: using `clone` on type `[u32; 2]` which implements the `Copy` trait - --> $DIR/clone_on_copy.rs:58:5 + --> $DIR/clone_on_copy.rs:59:5 | LL | x.clone()[0]; | ^^^^^^^^^ help: try dereferencing it: `(*x)` error: using `clone` on type `char` which implements the `Copy` trait - --> $DIR/clone_on_copy.rs:68:14 + --> $DIR/clone_on_copy.rs:69:14 | LL | is_ascii('z'.clone()); | ^^^^^^^^^^^ help: try removing the `clone` call: `'z'` error: using `clone` on type `i32` which implements the `Copy` trait - --> $DIR/clone_on_copy.rs:72:14 + --> $DIR/clone_on_copy.rs:73:14 | LL | vec.push(42.clone()); | ^^^^^^^^^^ help: try removing the `clone` call: `42` diff --git a/tests/ui/duration_subsec.fixed b/tests/ui/duration_subsec.fixed index ee5c7863eff..d92b8998e88 100644 --- a/tests/ui/duration_subsec.fixed +++ b/tests/ui/duration_subsec.fixed @@ -1,5 +1,5 @@ // run-rustfix -#![allow(dead_code)] +#![allow(dead_code, clippy::needless_borrow)] #![warn(clippy::duration_subsec)] use std::time::Duration; diff --git a/tests/ui/duration_subsec.rs b/tests/ui/duration_subsec.rs index 3c9d2a28621..08da804996d 100644 --- a/tests/ui/duration_subsec.rs +++ b/tests/ui/duration_subsec.rs @@ -1,5 +1,5 @@ // run-rustfix -#![allow(dead_code)] +#![allow(dead_code, clippy::needless_borrow)] #![warn(clippy::duration_subsec)] use std::time::Duration; diff --git a/tests/ui/eta.fixed b/tests/ui/eta.fixed index f938f710688..618f80cdcf8 100644 --- a/tests/ui/eta.fixed +++ b/tests/ui/eta.fixed @@ -5,13 +5,10 @@ clippy::no_effect, clippy::redundant_closure_call, clippy::needless_pass_by_value, - clippy::option_map_unit_fn -)] -#![warn( - clippy::redundant_closure, - clippy::redundant_closure_for_method_calls, + clippy::option_map_unit_fn, clippy::needless_borrow )] +#![warn(clippy::redundant_closure, clippy::redundant_closure_for_method_calls)] use std::path::{Path, PathBuf}; @@ -34,7 +31,7 @@ fn main() { Some(1).map(closure_mac!()); // don't lint closure in macro expansion let _: Option> = true.then(std::vec::Vec::new); // special case vec! let d = Some(1u8).map(|a| foo(foo2(a))); //is adjusted? - all(&[1, 2, 3], &2, below); //is adjusted + all(&[1, 2, 3], &&2, below); //is adjusted unsafe { Some(1u8).map(|a| unsafe_fn(a)); // unsafe fn } diff --git a/tests/ui/eta.rs b/tests/ui/eta.rs index 075bbc74922..a759e6eb514 100644 --- a/tests/ui/eta.rs +++ b/tests/ui/eta.rs @@ -5,13 +5,10 @@ clippy::no_effect, clippy::redundant_closure_call, clippy::needless_pass_by_value, - clippy::option_map_unit_fn -)] -#![warn( - clippy::redundant_closure, - clippy::redundant_closure_for_method_calls, + clippy::option_map_unit_fn, clippy::needless_borrow )] +#![warn(clippy::redundant_closure, clippy::redundant_closure_for_method_calls)] use std::path::{Path, PathBuf}; diff --git a/tests/ui/eta.stderr b/tests/ui/eta.stderr index 8092f04c3fc..cda84982c9b 100644 --- a/tests/ui/eta.stderr +++ b/tests/ui/eta.stderr @@ -1,5 +1,5 @@ error: redundant closure - --> $DIR/eta.rs:31:27 + --> $DIR/eta.rs:28:27 | LL | let a = Some(1u8).map(|a| foo(a)); | ^^^^^^^^^^ help: replace the closure with the function itself: `foo` @@ -7,45 +7,37 @@ LL | let a = Some(1u8).map(|a| foo(a)); = note: `-D clippy::redundant-closure` implied by `-D warnings` error: redundant closure - --> $DIR/eta.rs:35:40 + --> $DIR/eta.rs:32:40 | LL | let _: Option> = true.then(|| vec![]); // special case vec! | ^^^^^^^^^ help: replace the closure with `Vec::new`: `std::vec::Vec::new` error: redundant closure - --> $DIR/eta.rs:36:35 + --> $DIR/eta.rs:33:35 | LL | let d = Some(1u8).map(|a| foo((|b| foo2(b))(a))); //is adjusted? | ^^^^^^^^^^^^^ help: replace the closure with the function itself: `foo2` -error: this expression borrows a reference (`&u8`) that is immediately dereferenced by the compiler - --> $DIR/eta.rs:37:21 - | -LL | all(&[1, 2, 3], &&2, |x, y| below(x, y)); //is adjusted - | ^^^ help: change this to: `&2` - | - = note: `-D clippy::needless-borrow` implied by `-D warnings` - error: redundant closure - --> $DIR/eta.rs:37:26 + --> $DIR/eta.rs:34:26 | LL | all(&[1, 2, 3], &&2, |x, y| below(x, y)); //is adjusted | ^^^^^^^^^^^^^^^^^^ help: replace the closure with the function itself: `below` error: redundant closure - --> $DIR/eta.rs:43:27 + --> $DIR/eta.rs:40:27 | LL | let e = Some(1u8).map(|a| divergent(a)); | ^^^^^^^^^^^^^^^^ help: replace the closure with the function itself: `divergent` error: redundant closure - --> $DIR/eta.rs:44:27 + --> $DIR/eta.rs:41:27 | LL | let e = Some(1u8).map(|a| generic(a)); | ^^^^^^^^^^^^^^ help: replace the closure with the function itself: `generic` error: redundant closure - --> $DIR/eta.rs:90:51 + --> $DIR/eta.rs:87:51 | LL | let e = Some(TestStruct { some_ref: &i }).map(|a| a.foo()); | ^^^^^^^^^^^ help: replace the closure with the method itself: `TestStruct::foo` @@ -53,82 +45,82 @@ LL | let e = Some(TestStruct { some_ref: &i }).map(|a| a.foo()); = note: `-D clippy::redundant-closure-for-method-calls` implied by `-D warnings` error: redundant closure - --> $DIR/eta.rs:91:51 + --> $DIR/eta.rs:88:51 | LL | let e = Some(TestStruct { some_ref: &i }).map(|a| a.trait_foo()); | ^^^^^^^^^^^^^^^^^ help: replace the closure with the method itself: `TestTrait::trait_foo` error: redundant closure - --> $DIR/eta.rs:93:42 + --> $DIR/eta.rs:90:42 | LL | let e = Some(&mut vec![1, 2, 3]).map(|v| v.clear()); | ^^^^^^^^^^^^^ help: replace the closure with the method itself: `std::vec::Vec::clear` error: redundant closure - --> $DIR/eta.rs:97:29 + --> $DIR/eta.rs:94:29 | LL | let e = Some("str").map(|s| s.to_string()); | ^^^^^^^^^^^^^^^^^ help: replace the closure with the method itself: `std::string::ToString::to_string` error: redundant closure - --> $DIR/eta.rs:98:27 + --> $DIR/eta.rs:95:27 | LL | let e = Some('a').map(|s| s.to_uppercase()); | ^^^^^^^^^^^^^^^^^^^^ help: replace the closure with the method itself: `char::to_uppercase` error: redundant closure - --> $DIR/eta.rs:100:65 + --> $DIR/eta.rs:97:65 | LL | let e: std::vec::Vec = vec!['a', 'b', 'c'].iter().map(|c| c.to_ascii_uppercase()).collect(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: replace the closure with the method itself: `char::to_ascii_uppercase` error: redundant closure - --> $DIR/eta.rs:163:22 + --> $DIR/eta.rs:160:22 | LL | requires_fn_once(|| x()); | ^^^^^^ help: replace the closure with the function itself: `x` error: redundant closure - --> $DIR/eta.rs:170:27 + --> $DIR/eta.rs:167:27 | LL | let a = Some(1u8).map(|a| foo_ptr(a)); | ^^^^^^^^^^^^^^ help: replace the closure with the function itself: `foo_ptr` error: redundant closure - --> $DIR/eta.rs:175:27 + --> $DIR/eta.rs:172:27 | LL | let a = Some(1u8).map(|a| closure(a)); | ^^^^^^^^^^^^^^ help: replace the closure with the function itself: `closure` error: redundant closure - --> $DIR/eta.rs:207:28 + --> $DIR/eta.rs:204:28 | LL | x.into_iter().for_each(|x| add_to_res(x)); | ^^^^^^^^^^^^^^^^^ help: replace the closure with the function itself: `&mut add_to_res` error: redundant closure - --> $DIR/eta.rs:208:28 + --> $DIR/eta.rs:205:28 | LL | y.into_iter().for_each(|x| add_to_res(x)); | ^^^^^^^^^^^^^^^^^ help: replace the closure with the function itself: `&mut add_to_res` error: redundant closure - --> $DIR/eta.rs:209:28 + --> $DIR/eta.rs:206:28 | LL | z.into_iter().for_each(|x| add_to_res(x)); | ^^^^^^^^^^^^^^^^^ help: replace the closure with the function itself: `add_to_res` error: redundant closure - --> $DIR/eta.rs:216:21 + --> $DIR/eta.rs:213:21 | LL | Some(1).map(|n| closure(n)); | ^^^^^^^^^^^^^^ help: replace the closure with the function itself: `&mut closure` error: redundant closure - --> $DIR/eta.rs:235:21 + --> $DIR/eta.rs:232:21 | LL | map_str_to_path(|s| s.as_ref()); | ^^^^^^^^^^^^^^ help: replace the closure with the method itself: `std::convert::AsRef::as_ref` -error: aborting due to 21 previous errors +error: aborting due to 20 previous errors diff --git a/tests/ui/for_loop_fixable.fixed b/tests/ui/for_loop_fixable.fixed index f373e905d05..aa69781d15a 100644 --- a/tests/ui/for_loop_fixable.fixed +++ b/tests/ui/for_loop_fixable.fixed @@ -23,7 +23,12 @@ impl Unrelated { clippy::iter_next_loop, clippy::for_kv_map )] -#[allow(clippy::linkedlist, clippy::unnecessary_mut_passed, clippy::similar_names)] +#[allow( + clippy::linkedlist, + clippy::unnecessary_mut_passed, + clippy::similar_names, + clippy::needless_borrow +)] #[allow(unused_variables)] fn main() { let mut vec = vec![1, 2, 3, 4]; diff --git a/tests/ui/for_loop_fixable.rs b/tests/ui/for_loop_fixable.rs index 3814583bb6e..7c063d99511 100644 --- a/tests/ui/for_loop_fixable.rs +++ b/tests/ui/for_loop_fixable.rs @@ -23,7 +23,12 @@ impl Unrelated { clippy::iter_next_loop, clippy::for_kv_map )] -#[allow(clippy::linkedlist, clippy::unnecessary_mut_passed, clippy::similar_names)] +#[allow( + clippy::linkedlist, + clippy::unnecessary_mut_passed, + clippy::similar_names, + clippy::needless_borrow +)] #[allow(unused_variables)] fn main() { let mut vec = vec![1, 2, 3, 4]; diff --git a/tests/ui/for_loop_fixable.stderr b/tests/ui/for_loop_fixable.stderr index 009dbe1a0bf..ddfe66d675f 100644 --- a/tests/ui/for_loop_fixable.stderr +++ b/tests/ui/for_loop_fixable.stderr @@ -1,5 +1,5 @@ error: it is more concise to loop over references to containers instead of using explicit iteration methods - --> $DIR/for_loop_fixable.rs:38:15 + --> $DIR/for_loop_fixable.rs:43:15 | LL | for _v in vec.iter() {} | ^^^^^^^^^^ help: to write this more concisely, try: `&vec` @@ -7,13 +7,13 @@ LL | for _v in vec.iter() {} = note: `-D clippy::explicit-iter-loop` implied by `-D warnings` error: it is more concise to loop over references to containers instead of using explicit iteration methods - --> $DIR/for_loop_fixable.rs:40:15 + --> $DIR/for_loop_fixable.rs:45:15 | LL | for _v in vec.iter_mut() {} | ^^^^^^^^^^^^^^ help: to write this more concisely, try: `&mut vec` error: it is more concise to loop over containers instead of using explicit iteration methods - --> $DIR/for_loop_fixable.rs:43:15 + --> $DIR/for_loop_fixable.rs:48:15 | LL | for _v in out_vec.into_iter() {} | ^^^^^^^^^^^^^^^^^^^ help: to write this more concisely, try: `out_vec` @@ -21,73 +21,73 @@ LL | for _v in out_vec.into_iter() {} = note: `-D clippy::explicit-into-iter-loop` implied by `-D warnings` error: it is more concise to loop over references to containers instead of using explicit iteration methods - --> $DIR/for_loop_fixable.rs:48:15 + --> $DIR/for_loop_fixable.rs:53:15 | LL | for _v in [1, 2, 3].iter() {} | ^^^^^^^^^^^^^^^^ help: to write this more concisely, try: `&[1, 2, 3]` error: it is more concise to loop over references to containers instead of using explicit iteration methods - --> $DIR/for_loop_fixable.rs:52:15 + --> $DIR/for_loop_fixable.rs:57:15 | LL | for _v in [0; 32].iter() {} | ^^^^^^^^^^^^^^ help: to write this more concisely, try: `&[0; 32]` error: it is more concise to loop over references to containers instead of using explicit iteration methods - --> $DIR/for_loop_fixable.rs:57:15 + --> $DIR/for_loop_fixable.rs:62:15 | LL | for _v in ll.iter() {} | ^^^^^^^^^ help: to write this more concisely, try: `&ll` error: it is more concise to loop over references to containers instead of using explicit iteration methods - --> $DIR/for_loop_fixable.rs:60:15 + --> $DIR/for_loop_fixable.rs:65:15 | LL | for _v in vd.iter() {} | ^^^^^^^^^ help: to write this more concisely, try: `&vd` error: it is more concise to loop over references to containers instead of using explicit iteration methods - --> $DIR/for_loop_fixable.rs:63:15 + --> $DIR/for_loop_fixable.rs:68:15 | LL | for _v in bh.iter() {} | ^^^^^^^^^ help: to write this more concisely, try: `&bh` error: it is more concise to loop over references to containers instead of using explicit iteration methods - --> $DIR/for_loop_fixable.rs:66:15 + --> $DIR/for_loop_fixable.rs:71:15 | LL | for _v in hm.iter() {} | ^^^^^^^^^ help: to write this more concisely, try: `&hm` error: it is more concise to loop over references to containers instead of using explicit iteration methods - --> $DIR/for_loop_fixable.rs:69:15 + --> $DIR/for_loop_fixable.rs:74:15 | LL | for _v in bt.iter() {} | ^^^^^^^^^ help: to write this more concisely, try: `&bt` error: it is more concise to loop over references to containers instead of using explicit iteration methods - --> $DIR/for_loop_fixable.rs:72:15 + --> $DIR/for_loop_fixable.rs:77:15 | LL | for _v in hs.iter() {} | ^^^^^^^^^ help: to write this more concisely, try: `&hs` error: it is more concise to loop over references to containers instead of using explicit iteration methods - --> $DIR/for_loop_fixable.rs:75:15 + --> $DIR/for_loop_fixable.rs:80:15 | LL | for _v in bs.iter() {} | ^^^^^^^^^ help: to write this more concisely, try: `&bs` error: it is more concise to loop over containers instead of using explicit iteration methods - --> $DIR/for_loop_fixable.rs:250:18 + --> $DIR/for_loop_fixable.rs:255:18 | LL | for i in iterator.into_iter() { | ^^^^^^^^^^^^^^^^^^^^ help: to write this more concisely, try: `iterator` error: it is more concise to loop over references to containers instead of using explicit iteration methods - --> $DIR/for_loop_fixable.rs:270:18 + --> $DIR/for_loop_fixable.rs:275:18 | LL | for _ in t.into_iter() {} | ^^^^^^^^^^^^^ help: to write this more concisely, try: `&t` error: it is more concise to loop over containers instead of using explicit iteration methods - --> $DIR/for_loop_fixable.rs:272:18 + --> $DIR/for_loop_fixable.rs:277:18 | LL | for _ in r.into_iter() {} | ^^^^^^^^^^^^^ help: to write this more concisely, try: `r` diff --git a/tests/ui/needless_borrow.fixed b/tests/ui/needless_borrow.fixed index 2a87b520ce5..b856f1375d3 100644 --- a/tests/ui/needless_borrow.fixed +++ b/tests/ui/needless_borrow.fixed @@ -62,6 +62,16 @@ fn main() { }; *x = 5; + + let s = String::new(); + let _ = s.len(); + let _ = s.capacity(); + let _ = s.capacity(); + + let x = (1, 2); + let _ = x.0; + let x = &x as *const (i32, i32); + let _ = unsafe { (*x).0 }; } #[allow(clippy::needless_borrowed_reference)] diff --git a/tests/ui/needless_borrow.rs b/tests/ui/needless_borrow.rs index 4a98350711f..0bfe222a3dc 100644 --- a/tests/ui/needless_borrow.rs +++ b/tests/ui/needless_borrow.rs @@ -62,6 +62,16 @@ fn main() { }; *x = 5; + + let s = String::new(); + let _ = (&s).len(); + let _ = (&s).capacity(); + let _ = (&&s).capacity(); + + let x = (1, 2); + let _ = (&x).0; + let x = &x as *const (i32, i32); + let _ = unsafe { (&*x).0 }; } #[allow(clippy::needless_borrowed_reference)] diff --git a/tests/ui/needless_borrow.stderr b/tests/ui/needless_borrow.stderr index 2211f957982..e67718879ec 100644 --- a/tests/ui/needless_borrow.stderr +++ b/tests/ui/needless_borrow.stderr @@ -1,4 +1,18 @@ -error: this expression borrows a reference (`&i32`) that is immediately dereferenced by the compiler +error: creating a reference that is immediately dereferenced + --> $DIR/needless_borrow.rs:72:13 + | +LL | let _ = (&x).0; + | ^^^^ help: try this: `x` + | + = note: `-D clippy::ref-in-deref` implied by `-D warnings` + +error: creating a reference that is immediately dereferenced + --> $DIR/needless_borrow.rs:74:22 + | +LL | let _ = unsafe { (&*x).0 }; + | ^^^^^ help: try this: `(*x)` + +error: this expression creates a reference which is immediately dereferenced by the compiler --> $DIR/needless_borrow.rs:9:15 | LL | let _ = x(&&a); // warn @@ -6,83 +20,113 @@ LL | let _ = x(&&a); // warn | = note: `-D clippy::needless-borrow` implied by `-D warnings` -error: this expression borrows a reference (`&mut i32`) that is immediately dereferenced by the compiler +error: this expression creates a reference which is immediately dereferenced by the compiler --> $DIR/needless_borrow.rs:13:13 | LL | mut_ref(&mut &mut b); // warn | ^^^^^^^^^^^ help: change this to: `&mut b` -error: this expression borrows a reference (`&i32`) that is immediately dereferenced by the compiler +error: this expression creates a reference which is immediately dereferenced by the compiler --> $DIR/needless_borrow.rs:25:13 | LL | &&a | ^^^ help: change this to: `&a` -error: this expression borrows a reference (`&i32`) that is immediately dereferenced by the compiler +error: this expression creates a reference which is immediately dereferenced by the compiler --> $DIR/needless_borrow.rs:27:15 | LL | 46 => &&a, | ^^^ help: change this to: `&a` -error: this expression borrows a reference (`&i32`) that is immediately dereferenced by the compiler +error: this expression creates a reference which is immediately dereferenced by the compiler --> $DIR/needless_borrow.rs:33:27 | LL | break &ref_a; | ^^^^^^ help: change this to: `ref_a` -error: this expression borrows a reference (`&i32`) that is immediately dereferenced by the compiler +error: this expression creates a reference which is immediately dereferenced by the compiler --> $DIR/needless_borrow.rs:40:15 | LL | let _ = x(&&&a); | ^^^^ help: change this to: `&a` -error: this expression borrows a reference (`&i32`) that is immediately dereferenced by the compiler +error: this expression creates a reference which is immediately dereferenced by the compiler --> $DIR/needless_borrow.rs:41:15 | LL | let _ = x(&mut &&a); | ^^^^^^^^ help: change this to: `&a` -error: this expression borrows a reference (`&mut i32`) that is immediately dereferenced by the compiler +error: this expression creates a reference which is immediately dereferenced by the compiler --> $DIR/needless_borrow.rs:42:15 | LL | let _ = x(&&&mut b); | ^^^^^^^^ help: change this to: `&mut b` -error: this expression borrows a reference (`&i32`) that is immediately dereferenced by the compiler +error: this expression creates a reference which is immediately dereferenced by the compiler --> $DIR/needless_borrow.rs:43:15 | LL | let _ = x(&&ref_a); | ^^^^^^^ help: change this to: `ref_a` -error: this expression borrows a reference (`&mut i32`) that is immediately dereferenced by the compiler +error: this expression creates a reference which is immediately dereferenced by the compiler --> $DIR/needless_borrow.rs:46:11 | LL | x(&b); | ^^ help: change this to: `b` -error: this expression borrows a reference (`&mut i32`) that is immediately dereferenced by the compiler +error: this expression creates a reference which is immediately dereferenced by the compiler --> $DIR/needless_borrow.rs:53:13 | LL | mut_ref(&mut x); | ^^^^^^ help: change this to: `x` -error: this expression borrows a reference (`&mut i32`) that is immediately dereferenced by the compiler +error: this expression creates a reference which is immediately dereferenced by the compiler --> $DIR/needless_borrow.rs:54:13 | LL | mut_ref(&mut &mut x); | ^^^^^^^^^^^ help: change this to: `x` -error: this expression borrows a reference (`&mut i32`) that is immediately dereferenced by the compiler +error: this expression creates a reference which is immediately dereferenced by the compiler --> $DIR/needless_borrow.rs:55:23 | LL | let y: &mut i32 = &mut x; | ^^^^^^ help: change this to: `x` -error: this expression borrows a reference (`&mut i32`) that is immediately dereferenced by the compiler +error: this expression creates a reference which is immediately dereferenced by the compiler --> $DIR/needless_borrow.rs:56:23 | LL | let y: &mut i32 = &mut &mut x; | ^^^^^^^^^^^ help: change this to: `x` -error: aborting due to 14 previous errors +error: this expression borrows a value the compiler would automatically borrow + --> $DIR/needless_borrow.rs:67:13 + | +LL | let _ = (&s).len(); + | ^^^^ help: change this to: `s` + +error: this expression borrows a value the compiler would automatically borrow + --> $DIR/needless_borrow.rs:68:13 + | +LL | let _ = (&s).capacity(); + | ^^^^ help: change this to: `s` + +error: this expression creates a reference which is immediately dereferenced by the compiler + --> $DIR/needless_borrow.rs:69:13 + | +LL | let _ = (&&s).capacity(); + | ^^^^^ help: change this to: `s` + +error: this expression borrows a value the compiler would automatically borrow + --> $DIR/needless_borrow.rs:72:13 + | +LL | let _ = (&x).0; + | ^^^^ help: change this to: `x` + +error: this expression borrows a value the compiler would automatically borrow + --> $DIR/needless_borrow.rs:74:22 + | +LL | let _ = unsafe { (&*x).0 }; + | ^^^^^ help: change this to: `(*x)` + +error: aborting due to 21 previous errors diff --git a/tests/ui/useless_asref.fixed b/tests/ui/useless_asref.fixed index e356f13d087..e431661d180 100644 --- a/tests/ui/useless_asref.fixed +++ b/tests/ui/useless_asref.fixed @@ -67,7 +67,7 @@ fn not_ok() { foo_rslice(mrrrrrslice); foo_rslice(mrrrrrslice); } - #[allow(unused_parens, clippy::double_parens)] + #[allow(unused_parens, clippy::double_parens, clippy::needless_borrow)] foo_rrrrmr((&&&&MoreRef)); generic_not_ok(mrslice); diff --git a/tests/ui/useless_asref.rs b/tests/ui/useless_asref.rs index 2a80291f5d8..6ae931d7aa4 100644 --- a/tests/ui/useless_asref.rs +++ b/tests/ui/useless_asref.rs @@ -67,7 +67,7 @@ fn not_ok() { foo_rslice(mrrrrrslice.as_ref()); foo_rslice(mrrrrrslice); } - #[allow(unused_parens, clippy::double_parens)] + #[allow(unused_parens, clippy::double_parens, clippy::needless_borrow)] foo_rrrrmr((&&&&MoreRef).as_ref()); generic_not_ok(mrslice); diff --git a/tests/ui/write_literal.rs b/tests/ui/write_literal.rs index 0a127858def..44669174411 100644 --- a/tests/ui/write_literal.rs +++ b/tests/ui/write_literal.rs @@ -7,37 +7,37 @@ fn main() { let mut v = Vec::new(); // these should be fine - write!(&mut v, "Hello"); - writeln!(&mut v, "Hello"); + write!(v, "Hello"); + writeln!(v, "Hello"); let world = "world"; - writeln!(&mut v, "Hello {}", world); - writeln!(&mut v, "Hello {world}", world = world); - writeln!(&mut v, "3 in hex is {:X}", 3); - writeln!(&mut v, "2 + 1 = {:.4}", 3); - writeln!(&mut v, "2 + 1 = {:5.4}", 3); - writeln!(&mut v, "Debug test {:?}", "hello, world"); - writeln!(&mut v, "{0:8} {1:>8}", "hello", "world"); - writeln!(&mut v, "{1:8} {0:>8}", "hello", "world"); - writeln!(&mut v, "{foo:8} {bar:>8}", foo = "hello", bar = "world"); - writeln!(&mut v, "{bar:8} {foo:>8}", foo = "hello", bar = "world"); - writeln!(&mut v, "{number:>width$}", number = 1, width = 6); - writeln!(&mut v, "{number:>0width$}", number = 1, width = 6); - writeln!(&mut v, "{} of {:b} people know binary, the other half doesn't", 1, 2); - writeln!(&mut v, "10 / 4 is {}", 2.5); - writeln!(&mut v, "2 + 1 = {}", 3); + writeln!(v, "Hello {}", world); + writeln!(v, "Hello {world}", world = world); + writeln!(v, "3 in hex is {:X}", 3); + writeln!(v, "2 + 1 = {:.4}", 3); + writeln!(v, "2 + 1 = {:5.4}", 3); + writeln!(v, "Debug test {:?}", "hello, world"); + writeln!(v, "{0:8} {1:>8}", "hello", "world"); + writeln!(v, "{1:8} {0:>8}", "hello", "world"); + writeln!(v, "{foo:8} {bar:>8}", foo = "hello", bar = "world"); + writeln!(v, "{bar:8} {foo:>8}", foo = "hello", bar = "world"); + writeln!(v, "{number:>width$}", number = 1, width = 6); + writeln!(v, "{number:>0width$}", number = 1, width = 6); + writeln!(v, "{} of {:b} people know binary, the other half doesn't", 1, 2); + writeln!(v, "10 / 4 is {}", 2.5); + writeln!(v, "2 + 1 = {}", 3); // these should throw warnings - write!(&mut v, "Hello {}", "world"); - writeln!(&mut v, "Hello {} {}", world, "world"); - writeln!(&mut v, "Hello {}", "world"); + write!(v, "Hello {}", "world"); + writeln!(v, "Hello {} {}", world, "world"); + writeln!(v, "Hello {}", "world"); // positional args don't change the fact // that we're using a literal -- this should // throw a warning - writeln!(&mut v, "{0} {1}", "hello", "world"); - writeln!(&mut v, "{1} {0}", "hello", "world"); + writeln!(v, "{0} {1}", "hello", "world"); + writeln!(v, "{1} {0}", "hello", "world"); // named args shouldn't change anything either - writeln!(&mut v, "{foo} {bar}", foo = "hello", bar = "world"); - writeln!(&mut v, "{bar} {foo}", foo = "hello", bar = "world"); + writeln!(v, "{foo} {bar}", foo = "hello", bar = "world"); + writeln!(v, "{bar} {foo}", foo = "hello", bar = "world"); } diff --git a/tests/ui/write_literal.stderr b/tests/ui/write_literal.stderr index e0297c00231..593e9493ec5 100644 --- a/tests/ui/write_literal.stderr +++ b/tests/ui/write_literal.stderr @@ -1,134 +1,134 @@ error: literal with an empty format string - --> $DIR/write_literal.rs:30:32 + --> $DIR/write_literal.rs:30:27 | -LL | write!(&mut v, "Hello {}", "world"); - | ^^^^^^^ +LL | write!(v, "Hello {}", "world"); + | ^^^^^^^ | = note: `-D clippy::write-literal` implied by `-D warnings` help: try this | -LL - write!(&mut v, "Hello {}", "world"); -LL + write!(&mut v, "Hello world"); +LL - write!(v, "Hello {}", "world"); +LL + write!(v, "Hello world"); | error: literal with an empty format string - --> $DIR/write_literal.rs:31:44 + --> $DIR/write_literal.rs:31:39 | -LL | writeln!(&mut v, "Hello {} {}", world, "world"); - | ^^^^^^^ +LL | writeln!(v, "Hello {} {}", world, "world"); + | ^^^^^^^ | help: try this | -LL - writeln!(&mut v, "Hello {} {}", world, "world"); -LL + writeln!(&mut v, "Hello {} world", world); +LL - writeln!(v, "Hello {} {}", world, "world"); +LL + writeln!(v, "Hello {} world", world); | error: literal with an empty format string - --> $DIR/write_literal.rs:32:34 + --> $DIR/write_literal.rs:32:29 | -LL | writeln!(&mut v, "Hello {}", "world"); - | ^^^^^^^ +LL | writeln!(v, "Hello {}", "world"); + | ^^^^^^^ | help: try this | -LL - writeln!(&mut v, "Hello {}", "world"); -LL + writeln!(&mut v, "Hello world"); +LL - writeln!(v, "Hello {}", "world"); +LL + writeln!(v, "Hello world"); | error: literal with an empty format string - --> $DIR/write_literal.rs:37:33 + --> $DIR/write_literal.rs:37:28 | -LL | writeln!(&mut v, "{0} {1}", "hello", "world"); - | ^^^^^^^ +LL | writeln!(v, "{0} {1}", "hello", "world"); + | ^^^^^^^ | help: try this | -LL - writeln!(&mut v, "{0} {1}", "hello", "world"); -LL + writeln!(&mut v, "hello {1}", "world"); +LL - writeln!(v, "{0} {1}", "hello", "world"); +LL + writeln!(v, "hello {1}", "world"); | error: literal with an empty format string - --> $DIR/write_literal.rs:37:42 + --> $DIR/write_literal.rs:37:37 | -LL | writeln!(&mut v, "{0} {1}", "hello", "world"); - | ^^^^^^^ +LL | writeln!(v, "{0} {1}", "hello", "world"); + | ^^^^^^^ | help: try this | -LL - writeln!(&mut v, "{0} {1}", "hello", "world"); -LL + writeln!(&mut v, "{0} world", "hello"); +LL - writeln!(v, "{0} {1}", "hello", "world"); +LL + writeln!(v, "{0} world", "hello"); | error: literal with an empty format string - --> $DIR/write_literal.rs:38:33 + --> $DIR/write_literal.rs:38:28 | -LL | writeln!(&mut v, "{1} {0}", "hello", "world"); - | ^^^^^^^ +LL | writeln!(v, "{1} {0}", "hello", "world"); + | ^^^^^^^ | help: try this | -LL - writeln!(&mut v, "{1} {0}", "hello", "world"); -LL + writeln!(&mut v, "{1} hello", "world"); +LL - writeln!(v, "{1} {0}", "hello", "world"); +LL + writeln!(v, "{1} hello", "world"); | error: literal with an empty format string - --> $DIR/write_literal.rs:38:42 + --> $DIR/write_literal.rs:38:37 | -LL | writeln!(&mut v, "{1} {0}", "hello", "world"); - | ^^^^^^^ +LL | writeln!(v, "{1} {0}", "hello", "world"); + | ^^^^^^^ | help: try this | -LL - writeln!(&mut v, "{1} {0}", "hello", "world"); -LL + writeln!(&mut v, "world {0}", "hello"); +LL - writeln!(v, "{1} {0}", "hello", "world"); +LL + writeln!(v, "world {0}", "hello"); | error: literal with an empty format string - --> $DIR/write_literal.rs:41:37 + --> $DIR/write_literal.rs:41:32 | -LL | writeln!(&mut v, "{foo} {bar}", foo = "hello", bar = "world"); - | ^^^^^^^^^^^^^ +LL | writeln!(v, "{foo} {bar}", foo = "hello", bar = "world"); + | ^^^^^^^^^^^^^ | help: try this | -LL - writeln!(&mut v, "{foo} {bar}", foo = "hello", bar = "world"); -LL + writeln!(&mut v, "hello {bar}", bar = "world"); +LL - writeln!(v, "{foo} {bar}", foo = "hello", bar = "world"); +LL + writeln!(v, "hello {bar}", bar = "world"); | error: literal with an empty format string - --> $DIR/write_literal.rs:41:52 + --> $DIR/write_literal.rs:41:47 | -LL | writeln!(&mut v, "{foo} {bar}", foo = "hello", bar = "world"); - | ^^^^^^^^^^^^^ +LL | writeln!(v, "{foo} {bar}", foo = "hello", bar = "world"); + | ^^^^^^^^^^^^^ | help: try this | -LL - writeln!(&mut v, "{foo} {bar}", foo = "hello", bar = "world"); -LL + writeln!(&mut v, "{foo} world", foo = "hello"); +LL - writeln!(v, "{foo} {bar}", foo = "hello", bar = "world"); +LL + writeln!(v, "{foo} world", foo = "hello"); | error: literal with an empty format string - --> $DIR/write_literal.rs:42:37 + --> $DIR/write_literal.rs:42:32 | -LL | writeln!(&mut v, "{bar} {foo}", foo = "hello", bar = "world"); - | ^^^^^^^^^^^^^ +LL | writeln!(v, "{bar} {foo}", foo = "hello", bar = "world"); + | ^^^^^^^^^^^^^ | help: try this | -LL - writeln!(&mut v, "{bar} {foo}", foo = "hello", bar = "world"); -LL + writeln!(&mut v, "{bar} hello", bar = "world"); +LL - writeln!(v, "{bar} {foo}", foo = "hello", bar = "world"); +LL + writeln!(v, "{bar} hello", bar = "world"); | error: literal with an empty format string - --> $DIR/write_literal.rs:42:52 + --> $DIR/write_literal.rs:42:47 | -LL | writeln!(&mut v, "{bar} {foo}", foo = "hello", bar = "world"); - | ^^^^^^^^^^^^^ +LL | writeln!(v, "{bar} {foo}", foo = "hello", bar = "world"); + | ^^^^^^^^^^^^^ | help: try this | -LL - writeln!(&mut v, "{bar} {foo}", foo = "hello", bar = "world"); -LL + writeln!(&mut v, "world {foo}", foo = "hello"); +LL - writeln!(v, "{bar} {foo}", foo = "hello", bar = "world"); +LL + writeln!(v, "world {foo}", foo = "hello"); | error: aborting due to 11 previous errors diff --git a/tests/ui/write_literal_2.rs b/tests/ui/write_literal_2.rs index f341e8215e1..ba0d7be5eaa 100644 --- a/tests/ui/write_literal_2.rs +++ b/tests/ui/write_literal_2.rs @@ -6,20 +6,20 @@ use std::io::Write; fn main() { let mut v = Vec::new(); - writeln!(&mut v, "{}", "{hello}"); - writeln!(&mut v, r"{}", r"{hello}"); - writeln!(&mut v, "{}", '\''); - writeln!(&mut v, "{}", '"'); - writeln!(&mut v, r"{}", '"'); // don't lint - writeln!(&mut v, r"{}", '\''); + writeln!(v, "{}", "{hello}"); + writeln!(v, r"{}", r"{hello}"); + writeln!(v, "{}", '\''); + writeln!(v, "{}", '"'); + writeln!(v, r"{}", '"'); // don't lint + writeln!(v, r"{}", '\''); writeln!( - &mut v, + v, "some {}", "hello \ world!" ); writeln!( - &mut v, + v, "some {}\ {} \\ {}", "1", "2", "3", diff --git a/tests/ui/write_literal_2.stderr b/tests/ui/write_literal_2.stderr index 73c6b885813..fc40fbfa9e2 100644 --- a/tests/ui/write_literal_2.stderr +++ b/tests/ui/write_literal_2.stderr @@ -1,62 +1,62 @@ error: literal with an empty format string - --> $DIR/write_literal_2.rs:9:28 + --> $DIR/write_literal_2.rs:9:23 | -LL | writeln!(&mut v, "{}", "{hello}"); - | ^^^^^^^^^ +LL | writeln!(v, "{}", "{hello}"); + | ^^^^^^^^^ | = note: `-D clippy::write-literal` implied by `-D warnings` help: try this | -LL - writeln!(&mut v, "{}", "{hello}"); -LL + writeln!(&mut v, "{{hello}}"); +LL - writeln!(v, "{}", "{hello}"); +LL + writeln!(v, "{{hello}}"); | error: literal with an empty format string - --> $DIR/write_literal_2.rs:10:29 + --> $DIR/write_literal_2.rs:10:24 | -LL | writeln!(&mut v, r"{}", r"{hello}"); - | ^^^^^^^^^^ +LL | writeln!(v, r"{}", r"{hello}"); + | ^^^^^^^^^^ | help: try this | -LL - writeln!(&mut v, r"{}", r"{hello}"); -LL + writeln!(&mut v, r"{{hello}}"); +LL - writeln!(v, r"{}", r"{hello}"); +LL + writeln!(v, r"{{hello}}"); | error: literal with an empty format string - --> $DIR/write_literal_2.rs:11:28 + --> $DIR/write_literal_2.rs:11:23 | -LL | writeln!(&mut v, "{}", '/''); - | ^^^^ +LL | writeln!(v, "{}", '/''); + | ^^^^ | help: try this | -LL - writeln!(&mut v, "{}", '/''); -LL + writeln!(&mut v, "'"); +LL - writeln!(v, "{}", '/''); +LL + writeln!(v, "'"); | error: literal with an empty format string - --> $DIR/write_literal_2.rs:12:28 + --> $DIR/write_literal_2.rs:12:23 | -LL | writeln!(&mut v, "{}", '"'); - | ^^^ +LL | writeln!(v, "{}", '"'); + | ^^^ | help: try this | -LL - writeln!(&mut v, "{}", '"'); -LL + writeln!(&mut v, "/""); +LL - writeln!(v, "{}", '"'); +LL + writeln!(v, "/""); | error: literal with an empty format string - --> $DIR/write_literal_2.rs:14:29 + --> $DIR/write_literal_2.rs:14:24 | -LL | writeln!(&mut v, r"{}", '/''); - | ^^^^ +LL | writeln!(v, r"{}", '/''); + | ^^^^ | help: try this | -LL - writeln!(&mut v, r"{}", '/''); -LL + writeln!(&mut v, r"'"); +LL - writeln!(v, r"{}", '/''); +LL + writeln!(v, r"'"); | error: literal with an empty format string diff --git a/tests/ui/write_with_newline.rs b/tests/ui/write_with_newline.rs index 1c1b1b58402..446d6914d34 100644 --- a/tests/ui/write_with_newline.rs +++ b/tests/ui/write_with_newline.rs @@ -10,50 +10,50 @@ fn main() { let mut v = Vec::new(); // These should fail - write!(&mut v, "Hello\n"); - write!(&mut v, "Hello {}\n", "world"); - write!(&mut v, "Hello {} {}\n", "world", "#2"); - write!(&mut v, "{}\n", 1265); - write!(&mut v, "\n"); + write!(v, "Hello\n"); + write!(v, "Hello {}\n", "world"); + write!(v, "Hello {} {}\n", "world", "#2"); + write!(v, "{}\n", 1265); + write!(v, "\n"); // These should be fine - write!(&mut v, ""); - write!(&mut v, "Hello"); - writeln!(&mut v, "Hello"); - writeln!(&mut v, "Hello\n"); - writeln!(&mut v, "Hello {}\n", "world"); - write!(&mut v, "Issue\n{}", 1265); - write!(&mut v, "{}", 1265); - write!(&mut v, "\n{}", 1275); - write!(&mut v, "\n\n"); - write!(&mut v, "like eof\n\n"); - write!(&mut v, "Hello {} {}\n\n", "world", "#2"); - writeln!(&mut v, "\ndon't\nwarn\nfor\nmultiple\nnewlines\n"); // #3126 - writeln!(&mut v, "\nbla\n\n"); // #3126 + write!(v, ""); + write!(v, "Hello"); + writeln!(v, "Hello"); + writeln!(v, "Hello\n"); + writeln!(v, "Hello {}\n", "world"); + write!(v, "Issue\n{}", 1265); + write!(v, "{}", 1265); + write!(v, "\n{}", 1275); + write!(v, "\n\n"); + write!(v, "like eof\n\n"); + write!(v, "Hello {} {}\n\n", "world", "#2"); + writeln!(v, "\ndon't\nwarn\nfor\nmultiple\nnewlines\n"); // #3126 + writeln!(v, "\nbla\n\n"); // #3126 // Escaping - write!(&mut v, "\\n"); // #3514 - write!(&mut v, "\\\n"); // should fail - write!(&mut v, "\\\\n"); + write!(v, "\\n"); // #3514 + write!(v, "\\\n"); // should fail + write!(v, "\\\\n"); // Raw strings - write!(&mut v, r"\n"); // #3778 + write!(v, r"\n"); // #3778 // Literal newlines should also fail write!( - &mut v, + v, " " ); write!( - &mut v, + v, r" " ); // Don't warn on CRLF (#4208) - write!(&mut v, "\r\n"); - write!(&mut v, "foo\r\n"); - write!(&mut v, "\\r\n"); //~ ERROR - write!(&mut v, "foo\rbar\n"); + write!(v, "\r\n"); + write!(v, "foo\r\n"); + write!(v, "\\r\n"); //~ ERROR + write!(v, "foo\rbar\n"); } diff --git a/tests/ui/write_with_newline.stderr b/tests/ui/write_with_newline.stderr index 186459e50b6..3314a2a6e24 100644 --- a/tests/ui/write_with_newline.stderr +++ b/tests/ui/write_with_newline.stderr @@ -1,81 +1,81 @@ error: using `write!()` with a format string that ends in a single newline --> $DIR/write_with_newline.rs:13:5 | -LL | write!(&mut v, "Hello/n"); - | ^^^^^^^^^^^^^^^^^^^^^^^^^ +LL | write!(v, "Hello/n"); + | ^^^^^^^^^^^^^^^^^^^^ | = note: `-D clippy::write-with-newline` implied by `-D warnings` help: use `writeln!()` instead | -LL - write!(&mut v, "Hello/n"); -LL + writeln!(&mut v, "Hello"); +LL - write!(v, "Hello/n"); +LL + writeln!(v, "Hello"); | error: using `write!()` with a format string that ends in a single newline --> $DIR/write_with_newline.rs:14:5 | -LL | write!(&mut v, "Hello {}/n", "world"); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +LL | write!(v, "Hello {}/n", "world"); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | help: use `writeln!()` instead | -LL - write!(&mut v, "Hello {}/n", "world"); -LL + writeln!(&mut v, "Hello {}", "world"); +LL - write!(v, "Hello {}/n", "world"); +LL + writeln!(v, "Hello {}", "world"); | error: using `write!()` with a format string that ends in a single newline --> $DIR/write_with_newline.rs:15:5 | -LL | write!(&mut v, "Hello {} {}/n", "world", "#2"); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +LL | write!(v, "Hello {} {}/n", "world", "#2"); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | help: use `writeln!()` instead | -LL - write!(&mut v, "Hello {} {}/n", "world", "#2"); -LL + writeln!(&mut v, "Hello {} {}", "world", "#2"); +LL - write!(v, "Hello {} {}/n", "world", "#2"); +LL + writeln!(v, "Hello {} {}", "world", "#2"); | error: using `write!()` with a format string that ends in a single newline --> $DIR/write_with_newline.rs:16:5 | -LL | write!(&mut v, "{}/n", 1265); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +LL | write!(v, "{}/n", 1265); + | ^^^^^^^^^^^^^^^^^^^^^^^ | help: use `writeln!()` instead | -LL - write!(&mut v, "{}/n", 1265); -LL + writeln!(&mut v, "{}", 1265); +LL - write!(v, "{}/n", 1265); +LL + writeln!(v, "{}", 1265); | error: using `write!()` with a format string that ends in a single newline --> $DIR/write_with_newline.rs:17:5 | -LL | write!(&mut v, "/n"); - | ^^^^^^^^^^^^^^^^^^^^ +LL | write!(v, "/n"); + | ^^^^^^^^^^^^^^^ | help: use `writeln!()` instead | -LL - write!(&mut v, "/n"); -LL + writeln!(&mut v); +LL - write!(v, "/n"); +LL + writeln!(v); | error: using `write!()` with a format string that ends in a single newline --> $DIR/write_with_newline.rs:36:5 | -LL | write!(&mut v, "//n"); // should fail - | ^^^^^^^^^^^^^^^^^^^^^^ +LL | write!(v, "//n"); // should fail + | ^^^^^^^^^^^^^^^^^ | help: use `writeln!()` instead | -LL - write!(&mut v, "//n"); // should fail -LL + writeln!(&mut v, "/"); // should fail +LL - write!(v, "//n"); // should fail +LL + writeln!(v, "/"); // should fail | error: using `write!()` with a format string that ends in a single newline --> $DIR/write_with_newline.rs:43:5 | LL | / write!( -LL | | &mut v, +LL | | v, LL | | " LL | | " LL | | ); @@ -84,7 +84,7 @@ LL | | ); help: use `writeln!()` instead | LL ~ writeln!( -LL | &mut v, +LL | v, LL ~ "" | @@ -92,7 +92,7 @@ error: using `write!()` with a format string that ends in a single newline --> $DIR/write_with_newline.rs:48:5 | LL | / write!( -LL | | &mut v, +LL | | v, LL | | r" LL | | " LL | | ); @@ -101,32 +101,32 @@ LL | | ); help: use `writeln!()` instead | LL ~ writeln!( -LL | &mut v, +LL | v, LL ~ r"" | error: using `write!()` with a format string that ends in a single newline --> $DIR/write_with_newline.rs:57:5 | -LL | write!(&mut v, "/r/n"); //~ ERROR - | ^^^^^^^^^^^^^^^^^^^^^^^ +LL | write!(v, "/r/n"); //~ ERROR + | ^^^^^^^^^^^^^^^^^^ | help: use `writeln!()` instead | -LL - write!(&mut v, "/r/n"); //~ ERROR -LL + writeln!(&mut v, "/r"); //~ ERROR +LL - write!(v, "/r/n"); //~ ERROR +LL + writeln!(v, "/r"); //~ ERROR | error: using `write!()` with a format string that ends in a single newline --> $DIR/write_with_newline.rs:58:5 | -LL | write!(&mut v, "foo/rbar/n"); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +LL | write!(v, "foo/rbar/n"); + | ^^^^^^^^^^^^^^^^^^^^^^^ | help: use `writeln!()` instead | -LL - write!(&mut v, "foo/rbar/n"); -LL + writeln!(&mut v, "foo/rbar"); +LL - write!(v, "foo/rbar/n"); +LL + writeln!(v, "foo/rbar"); | error: aborting due to 10 previous errors diff --git a/tests/ui/writeln_empty_string.fixed b/tests/ui/writeln_empty_string.fixed index c3ac15b0375..e7d94acd130 100644 --- a/tests/ui/writeln_empty_string.fixed +++ b/tests/ui/writeln_empty_string.fixed @@ -8,13 +8,13 @@ fn main() { let mut v = Vec::new(); // These should fail - writeln!(&mut v); + writeln!(v); let mut suggestion = Vec::new(); - writeln!(&mut suggestion); + writeln!(suggestion); // These should be fine - writeln!(&mut v); - writeln!(&mut v, " "); - write!(&mut v, ""); + writeln!(v); + writeln!(v, " "); + write!(v, ""); } diff --git a/tests/ui/writeln_empty_string.rs b/tests/ui/writeln_empty_string.rs index 9a8894b6c0d..662c62f0211 100644 --- a/tests/ui/writeln_empty_string.rs +++ b/tests/ui/writeln_empty_string.rs @@ -8,13 +8,13 @@ fn main() { let mut v = Vec::new(); // These should fail - writeln!(&mut v, ""); + writeln!(v, ""); let mut suggestion = Vec::new(); - writeln!(&mut suggestion, ""); + writeln!(suggestion, ""); // These should be fine - writeln!(&mut v); - writeln!(&mut v, " "); - write!(&mut v, ""); + writeln!(v); + writeln!(v, " "); + write!(v, ""); } diff --git a/tests/ui/writeln_empty_string.stderr b/tests/ui/writeln_empty_string.stderr index 99635229b3e..ac65aadfc0e 100644 --- a/tests/ui/writeln_empty_string.stderr +++ b/tests/ui/writeln_empty_string.stderr @@ -1,16 +1,16 @@ -error: using `writeln!(&mut v, "")` +error: using `writeln!(v, "")` --> $DIR/writeln_empty_string.rs:11:5 | -LL | writeln!(&mut v, ""); - | ^^^^^^^^^^^^^^^^^^^^ help: replace it with: `writeln!(&mut v)` +LL | writeln!(v, ""); + | ^^^^^^^^^^^^^^^ help: replace it with: `writeln!(v)` | = note: `-D clippy::writeln-empty-string` implied by `-D warnings` -error: using `writeln!(&mut suggestion, "")` +error: using `writeln!(suggestion, "")` --> $DIR/writeln_empty_string.rs:14:5 | -LL | writeln!(&mut suggestion, ""); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: replace it with: `writeln!(&mut suggestion)` +LL | writeln!(suggestion, ""); + | ^^^^^^^^^^^^^^^^^^^^^^^^ help: replace it with: `writeln!(suggestion)` error: aborting due to 2 previous errors