From 8494a062406d509c6a3d752c0523c46fc0f395f4 Mon Sep 17 00:00:00 2001 From: Catherine Date: Wed, 19 Jul 2023 02:36:09 -0500 Subject: [PATCH 1/2] Take into account lint attributes in `single_call_fn` + other misc changes. --- clippy_lints/src/needless_pass_by_ref_mut.rs | 7 +-- clippy_lints/src/single_call_fn.rs | 12 ++-- tests/ui/infinite_loop.rs | 2 + tests/ui/infinite_loop.stderr | 32 ++++------ tests/ui/let_underscore_future.rs | 2 + tests/ui/let_underscore_future.stderr | 16 ++--- tests/ui/mut_key.rs | 2 + tests/ui/mut_key.stderr | 44 ++++++-------- tests/ui/mut_reference.rs | 2 +- tests/ui/mut_reference.stderr | 10 +--- tests/ui/needless_pass_by_ref_mut.stderr | 60 +++++++++---------- tests/ui/should_impl_trait/method_list_2.rs | 1 + .../ui/should_impl_trait/method_list_2.stderr | 41 +++++-------- tests/ui/single_call_fn.rs | 8 +++ tests/ui/slow_vector_initialization.rs | 2 + tests/ui/slow_vector_initialization.stderr | 34 ++++------- 16 files changed, 122 insertions(+), 153 deletions(-) diff --git a/clippy_lints/src/needless_pass_by_ref_mut.rs b/clippy_lints/src/needless_pass_by_ref_mut.rs index c634de960d13..077c147de1d3 100644 --- a/clippy_lints/src/needless_pass_by_ref_mut.rs +++ b/clippy_lints/src/needless_pass_by_ref_mut.rs @@ -21,7 +21,7 @@ use rustc_target::spec::abi::Abi; declare_clippy_lint! { /// ### What it does - /// Check if a `&mut` function argument is actually used mutably. + /// Checks if a `&mut` function argument is actually used mutably. /// /// Be careful if the function is publicly reexported as it would break compatibility with /// users of this function. @@ -89,7 +89,6 @@ fn should_skip<'tcx>( } } - // All spans generated from a proc-macro invocation are the same... is_from_proc_macro(cx, &input) } @@ -203,11 +202,11 @@ impl<'tcx> LateLintPass<'tcx> for NeedlessPassByRefMut<'tcx> { NEEDLESS_PASS_BY_REF_MUT, cx.tcx.hir().local_def_id_to_hir_id(*fn_def_id), sp, - "this argument is a mutable reference, but not used mutably", + "this argument is a mutable reference, but never used mutably", |diag| { diag.span_suggestion( sp, - "consider changing to".to_string(), + "consider using an immutable reference instead", format!("&{}", snippet(cx, cx.tcx.hir().span(inner_ty.ty.hir_id), "_"),), Applicability::Unspecified, ); diff --git a/clippy_lints/src/single_call_fn.rs b/clippy_lints/src/single_call_fn.rs index 7bbe98e0a7f9..a17e5d8cd69a 100644 --- a/clippy_lints/src/single_call_fn.rs +++ b/clippy_lints/src/single_call_fn.rs @@ -1,4 +1,4 @@ -use clippy_utils::diagnostics::span_lint_and_help; +use clippy_utils::diagnostics::span_lint_hir_and_then; use clippy_utils::{is_from_proc_macro, is_in_test_function}; use rustc_data_structures::fx::FxHashMap; use rustc_hir::def_id::LocalDefId; @@ -88,16 +88,18 @@ impl<'tcx> LateLintPass<'tcx> for SingleCallFn { }; cx.tcx.hir().visit_all_item_likes_in_crate(&mut v); - for usage in self.def_id_to_usage.values() { + for (def_id, usage) in &self.def_id_to_usage { let single_call_fn_span = usage.0; if let [caller_span] = *usage.1 { - span_lint_and_help( + span_lint_hir_and_then( cx, SINGLE_CALL_FN, + cx.tcx.hir().local_def_id_to_hir_id(*def_id), single_call_fn_span, "this function is only used once", - Some(caller_span), - "used here", + |diag| { + diag.span_help(caller_span, "used here"); + }, ); } } diff --git a/tests/ui/infinite_loop.rs b/tests/ui/infinite_loop.rs index 38e64b9ac0ad..5ab450ee8d71 100644 --- a/tests/ui/infinite_loop.rs +++ b/tests/ui/infinite_loop.rs @@ -1,3 +1,5 @@ +#![allow(clippy::needless_pass_by_ref_mut)] + fn fn_val(i: i32) -> i32 { unimplemented!() } diff --git a/tests/ui/infinite_loop.stderr b/tests/ui/infinite_loop.stderr index 04559f9ada43..f79486d2ab9d 100644 --- a/tests/ui/infinite_loop.stderr +++ b/tests/ui/infinite_loop.stderr @@ -1,5 +1,5 @@ error: variables in the condition are not mutated in the loop body - --> $DIR/infinite_loop.rs:20:11 + --> $DIR/infinite_loop.rs:22:11 | LL | while y < 10 { | ^^^^^^ @@ -8,7 +8,7 @@ LL | while y < 10 { = note: `#[deny(clippy::while_immutable_condition)]` on by default error: variables in the condition are not mutated in the loop body - --> $DIR/infinite_loop.rs:25:11 + --> $DIR/infinite_loop.rs:27:11 | LL | while y < 10 && x < 3 { | ^^^^^^^^^^^^^^^ @@ -16,7 +16,7 @@ LL | while y < 10 && x < 3 { = note: this may lead to an infinite or to a never running loop error: variables in the condition are not mutated in the loop body - --> $DIR/infinite_loop.rs:32:11 + --> $DIR/infinite_loop.rs:34:11 | LL | while !cond { | ^^^^^ @@ -24,7 +24,7 @@ LL | while !cond { = note: this may lead to an infinite or to a never running loop error: variables in the condition are not mutated in the loop body - --> $DIR/infinite_loop.rs:76:11 + --> $DIR/infinite_loop.rs:78:11 | LL | while i < 3 { | ^^^^^ @@ -32,7 +32,7 @@ LL | while i < 3 { = note: this may lead to an infinite or to a never running loop error: variables in the condition are not mutated in the loop body - --> $DIR/infinite_loop.rs:81:11 + --> $DIR/infinite_loop.rs:83:11 | LL | while i < 3 && j > 0 { | ^^^^^^^^^^^^^^ @@ -40,7 +40,7 @@ LL | while i < 3 && j > 0 { = note: this may lead to an infinite or to a never running loop error: variables in the condition are not mutated in the loop body - --> $DIR/infinite_loop.rs:85:11 + --> $DIR/infinite_loop.rs:87:11 | LL | while i < 3 { | ^^^^^ @@ -48,7 +48,7 @@ LL | while i < 3 { = note: this may lead to an infinite or to a never running loop error: variables in the condition are not mutated in the loop body - --> $DIR/infinite_loop.rs:100:11 + --> $DIR/infinite_loop.rs:102:11 | LL | while i < 3 { | ^^^^^ @@ -56,7 +56,7 @@ LL | while i < 3 { = note: this may lead to an infinite or to a never running loop error: variables in the condition are not mutated in the loop body - --> $DIR/infinite_loop.rs:105:11 + --> $DIR/infinite_loop.rs:107:11 | LL | while i < 3 { | ^^^^^ @@ -64,7 +64,7 @@ LL | while i < 3 { = note: this may lead to an infinite or to a never running loop error: variables in the condition are not mutated in the loop body - --> $DIR/infinite_loop.rs:171:15 + --> $DIR/infinite_loop.rs:173:15 | LL | while self.count < n { | ^^^^^^^^^^^^^^ @@ -72,7 +72,7 @@ LL | while self.count < n { = note: this may lead to an infinite or to a never running loop error: variables in the condition are not mutated in the loop body - --> $DIR/infinite_loop.rs:179:11 + --> $DIR/infinite_loop.rs:181:11 | LL | while y < 10 { | ^^^^^^ @@ -82,7 +82,7 @@ LL | while y < 10 { = help: rewrite it as `if cond { loop { } }` error: variables in the condition are not mutated in the loop body - --> $DIR/infinite_loop.rs:186:11 + --> $DIR/infinite_loop.rs:188:11 | LL | while y < 10 { | ^^^^^^ @@ -91,13 +91,5 @@ LL | while y < 10 { = note: this loop contains `return`s or `break`s = help: rewrite it as `if cond { loop { } }` -error: this argument is a mutable reference, but not used mutably - --> $DIR/infinite_loop.rs:7:17 - | -LL | fn fn_mutref(i: &mut i32) { - | ^^^^^^^^ help: consider changing to: `&i32` - | - = note: `-D clippy::needless-pass-by-ref-mut` implied by `-D warnings` - -error: aborting due to 12 previous errors +error: aborting due to 11 previous errors diff --git a/tests/ui/let_underscore_future.rs b/tests/ui/let_underscore_future.rs index d8f54cdca912..8212b9c777ad 100644 --- a/tests/ui/let_underscore_future.rs +++ b/tests/ui/let_underscore_future.rs @@ -1,3 +1,5 @@ +#![allow(clippy::needless_pass_by_ref_mut)] + use std::future::Future; async fn some_async_fn() {} diff --git a/tests/ui/let_underscore_future.stderr b/tests/ui/let_underscore_future.stderr index ff1e2b8c9019..a16371fb811c 100644 --- a/tests/ui/let_underscore_future.stderr +++ b/tests/ui/let_underscore_future.stderr @@ -1,5 +1,5 @@ error: non-binding `let` on a future - --> $DIR/let_underscore_future.rs:14:5 + --> $DIR/let_underscore_future.rs:16:5 | LL | let _ = some_async_fn(); | ^^^^^^^^^^^^^^^^^^^^^^^^ @@ -8,7 +8,7 @@ LL | let _ = some_async_fn(); = note: `-D clippy::let-underscore-future` implied by `-D warnings` error: non-binding `let` on a future - --> $DIR/let_underscore_future.rs:15:5 + --> $DIR/let_underscore_future.rs:17:5 | LL | let _ = custom(); | ^^^^^^^^^^^^^^^^^ @@ -16,20 +16,12 @@ LL | let _ = custom(); = help: consider awaiting the future or dropping explicitly with `std::mem::drop` error: non-binding `let` on a future - --> $DIR/let_underscore_future.rs:19:5 + --> $DIR/let_underscore_future.rs:21:5 | LL | let _ = future; | ^^^^^^^^^^^^^^^ | = help: consider awaiting the future or dropping explicitly with `std::mem::drop` -error: this argument is a mutable reference, but not used mutably - --> $DIR/let_underscore_future.rs:11:35 - | -LL | fn do_something_to_future(future: &mut impl Future) {} - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider changing to: `&impl Future` - | - = note: `-D clippy::needless-pass-by-ref-mut` implied by `-D warnings` - -error: aborting due to 4 previous errors +error: aborting due to 3 previous errors diff --git a/tests/ui/mut_key.rs b/tests/ui/mut_key.rs index 15d68c08984f..d95e1a4e04ca 100644 --- a/tests/ui/mut_key.rs +++ b/tests/ui/mut_key.rs @@ -1,3 +1,5 @@ +#![allow(clippy::needless_pass_by_ref_mut)] + use std::cell::Cell; use std::collections::{BTreeMap, BTreeSet, HashMap, HashSet}; use std::hash::{Hash, Hasher}; diff --git a/tests/ui/mut_key.stderr b/tests/ui/mut_key.stderr index 3f756f5f0e59..66f1362719ee 100644 --- a/tests/ui/mut_key.stderr +++ b/tests/ui/mut_key.stderr @@ -1,5 +1,5 @@ error: mutable key type - --> $DIR/mut_key.rs:31:32 + --> $DIR/mut_key.rs:33:32 | LL | fn should_not_take_this_arg(m: &mut HashMap, _n: usize) -> HashSet { | ^^^^^^^^^^^^^^^^^^^^^^^^ @@ -7,108 +7,100 @@ LL | fn should_not_take_this_arg(m: &mut HashMap, _n: usize) -> Hash = note: `-D clippy::mutable-key-type` implied by `-D warnings` error: mutable key type - --> $DIR/mut_key.rs:31:72 + --> $DIR/mut_key.rs:33:72 | LL | fn should_not_take_this_arg(m: &mut HashMap, _n: usize) -> HashSet { | ^^^^^^^^^^^^ error: mutable key type - --> $DIR/mut_key.rs:32:5 + --> $DIR/mut_key.rs:34:5 | LL | let _other: HashMap = HashMap::new(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: mutable key type - --> $DIR/mut_key.rs:59:22 + --> $DIR/mut_key.rs:61:22 | LL | fn tuples_bad(_m: &mut HashMap<(Key, U), bool>) {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: mutable key type - --> $DIR/mut_key.rs:71:5 + --> $DIR/mut_key.rs:73:5 | LL | let _map = HashMap::, usize>::new(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: mutable key type - --> $DIR/mut_key.rs:72:5 + --> $DIR/mut_key.rs:74:5 | LL | let _map = HashMap::<&mut Cell, usize>::new(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: mutable key type - --> $DIR/mut_key.rs:73:5 + --> $DIR/mut_key.rs:75:5 | LL | let _map = HashMap::<&mut usize, usize>::new(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: mutable key type - --> $DIR/mut_key.rs:75:5 + --> $DIR/mut_key.rs:77:5 | LL | let _map = HashMap::>, usize>::new(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: mutable key type - --> $DIR/mut_key.rs:76:5 + --> $DIR/mut_key.rs:78:5 | LL | let _map = HashMap::, ()>, usize>::new(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: mutable key type - --> $DIR/mut_key.rs:77:5 + --> $DIR/mut_key.rs:79:5 | LL | let _map = HashMap::>, usize>::new(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: mutable key type - --> $DIR/mut_key.rs:78:5 + --> $DIR/mut_key.rs:80:5 | LL | let _map = HashMap::>, usize>::new(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: mutable key type - --> $DIR/mut_key.rs:79:5 + --> $DIR/mut_key.rs:81:5 | LL | let _map = HashMap::>, usize>::new(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: mutable key type - --> $DIR/mut_key.rs:80:5 + --> $DIR/mut_key.rs:82:5 | LL | let _map = HashMap::>>, usize>::new(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: mutable key type - --> $DIR/mut_key.rs:81:5 + --> $DIR/mut_key.rs:83:5 | LL | let _map = HashMap::, usize>::new(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: mutable key type - --> $DIR/mut_key.rs:83:5 + --> $DIR/mut_key.rs:85:5 | LL | let _map = HashMap::>, usize>::new(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: mutable key type - --> $DIR/mut_key.rs:84:5 + --> $DIR/mut_key.rs:86:5 | LL | let _map = HashMap::>, usize>::new(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: mutable key type - --> $DIR/mut_key.rs:85:5 + --> $DIR/mut_key.rs:87:5 | LL | let _map = HashMap::>, usize>::new(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -error: this argument is a mutable reference, but not used mutably - --> $DIR/mut_key.rs:31:32 - | -LL | fn should_not_take_this_arg(m: &mut HashMap, _n: usize) -> HashSet { - | ^^^^^^^^^^^^^^^^^^^^^^^^ help: consider changing to: `&HashMap` - | - = note: `-D clippy::needless-pass-by-ref-mut` implied by `-D warnings` - -error: aborting due to 18 previous errors +error: aborting due to 17 previous errors diff --git a/tests/ui/mut_reference.rs b/tests/ui/mut_reference.rs index 00661c51a78f..050702483084 100644 --- a/tests/ui/mut_reference.rs +++ b/tests/ui/mut_reference.rs @@ -1,4 +1,4 @@ -#![allow(unused_variables, dead_code)] +#![allow(clippy::needless_pass_by_ref_mut, unused_variables, dead_code)] fn takes_an_immutable_reference(a: &i32) {} fn takes_a_mutable_reference(a: &mut i32) {} diff --git a/tests/ui/mut_reference.stderr b/tests/ui/mut_reference.stderr index d8a71d264610..4ce1cfa4f137 100644 --- a/tests/ui/mut_reference.stderr +++ b/tests/ui/mut_reference.stderr @@ -18,13 +18,5 @@ error: the method `takes_an_immutable_reference` doesn't need a mutable referenc LL | my_struct.takes_an_immutable_reference(&mut 42); | ^^^^^^^ -error: this argument is a mutable reference, but not used mutably - --> $DIR/mut_reference.rs:24:44 - | -LL | fn takes_a_mutable_reference(&self, a: &mut i32) {} - | ^^^^^^^^ help: consider changing to: `&i32` - | - = note: `-D clippy::needless-pass-by-ref-mut` implied by `-D warnings` - -error: aborting due to 4 previous errors +error: aborting due to 3 previous errors diff --git a/tests/ui/needless_pass_by_ref_mut.stderr b/tests/ui/needless_pass_by_ref_mut.stderr index 0d426ce32f9d..756be15af94f 100644 --- a/tests/ui/needless_pass_by_ref_mut.stderr +++ b/tests/ui/needless_pass_by_ref_mut.stderr @@ -1,96 +1,96 @@ -error: this argument is a mutable reference, but not used mutably +error: this argument is a mutable reference, but never used mutably --> $DIR/needless_pass_by_ref_mut.rs:6:11 | LL | fn foo(s: &mut Vec, b: &u32, x: &mut u32) { - | ^^^^^^^^^^^^^ help: consider changing to: `&Vec` + | ^^^^^^^^^^^^^ help: consider using an immutable reference instead: `&Vec` | = note: `-D clippy::needless-pass-by-ref-mut` implied by `-D warnings` -error: this argument is a mutable reference, but not used mutably +error: this argument is a mutable reference, but never used mutably --> $DIR/needless_pass_by_ref_mut.rs:31:12 | LL | fn foo6(s: &mut Vec) { - | ^^^^^^^^^^^^^ help: consider changing to: `&Vec` + | ^^^^^^^^^^^^^ help: consider using an immutable reference instead: `&Vec` -error: this argument is a mutable reference, but not used mutably +error: this argument is a mutable reference, but never used mutably --> $DIR/needless_pass_by_ref_mut.rs:44:29 | LL | fn mushroom(&self, vec: &mut Vec) -> usize { - | ^^^^^^^^^^^^^ help: consider changing to: `&Vec` + | ^^^^^^^^^^^^^ help: consider using an immutable reference instead: `&Vec` -error: this argument is a mutable reference, but not used mutably +error: this argument is a mutable reference, but never used mutably --> $DIR/needless_pass_by_ref_mut.rs:49:31 | LL | fn badger(&mut self, vec: &mut Vec) -> usize { - | ^^^^^^^^^^^^^ help: consider changing to: `&Vec` + | ^^^^^^^^^^^^^ help: consider using an immutable reference instead: `&Vec` -error: this argument is a mutable reference, but not used mutably +error: this argument is a mutable reference, but never used mutably --> $DIR/needless_pass_by_ref_mut.rs:126:16 | LL | async fn a1(x: &mut i32) { - | ^^^^^^^^ help: consider changing to: `&i32` + | ^^^^^^^^ help: consider using an immutable reference instead: `&i32` -error: this argument is a mutable reference, but not used mutably +error: this argument is a mutable reference, but never used mutably --> $DIR/needless_pass_by_ref_mut.rs:130:16 | LL | async fn a2(x: &mut i32, y: String) { - | ^^^^^^^^ help: consider changing to: `&i32` + | ^^^^^^^^ help: consider using an immutable reference instead: `&i32` -error: this argument is a mutable reference, but not used mutably +error: this argument is a mutable reference, but never used mutably --> $DIR/needless_pass_by_ref_mut.rs:134:16 | LL | async fn a3(x: &mut i32, y: String, z: String) { - | ^^^^^^^^ help: consider changing to: `&i32` + | ^^^^^^^^ help: consider using an immutable reference instead: `&i32` -error: this argument is a mutable reference, but not used mutably +error: this argument is a mutable reference, but never used mutably --> $DIR/needless_pass_by_ref_mut.rs:138:16 | LL | async fn a4(x: &mut i32, y: i32) { - | ^^^^^^^^ help: consider changing to: `&i32` + | ^^^^^^^^ help: consider using an immutable reference instead: `&i32` -error: this argument is a mutable reference, but not used mutably +error: this argument is a mutable reference, but never used mutably --> $DIR/needless_pass_by_ref_mut.rs:142:24 | LL | async fn a5(x: i32, y: &mut i32) { - | ^^^^^^^^ help: consider changing to: `&i32` + | ^^^^^^^^ help: consider using an immutable reference instead: `&i32` -error: this argument is a mutable reference, but not used mutably +error: this argument is a mutable reference, but never used mutably --> $DIR/needless_pass_by_ref_mut.rs:146:24 | LL | async fn a6(x: i32, y: &mut i32) { - | ^^^^^^^^ help: consider changing to: `&i32` + | ^^^^^^^^ help: consider using an immutable reference instead: `&i32` -error: this argument is a mutable reference, but not used mutably +error: this argument is a mutable reference, but never used mutably --> $DIR/needless_pass_by_ref_mut.rs:150:32 | LL | async fn a7(x: i32, y: i32, z: &mut i32) { - | ^^^^^^^^ help: consider changing to: `&i32` + | ^^^^^^^^ help: consider using an immutable reference instead: `&i32` -error: this argument is a mutable reference, but not used mutably +error: this argument is a mutable reference, but never used mutably --> $DIR/needless_pass_by_ref_mut.rs:154:24 | LL | async fn a8(x: i32, a: &mut i32, y: i32, z: &mut i32) { - | ^^^^^^^^ help: consider changing to: `&i32` + | ^^^^^^^^ help: consider using an immutable reference instead: `&i32` -error: this argument is a mutable reference, but not used mutably +error: this argument is a mutable reference, but never used mutably --> $DIR/needless_pass_by_ref_mut.rs:154:45 | LL | async fn a8(x: i32, a: &mut i32, y: i32, z: &mut i32) { - | ^^^^^^^^ help: consider changing to: `&i32` + | ^^^^^^^^ help: consider using an immutable reference instead: `&i32` -error: this argument is a mutable reference, but not used mutably +error: this argument is a mutable reference, but never used mutably --> $DIR/needless_pass_by_ref_mut.rs:188:16 | LL | fn cfg_warn(s: &mut u32) {} - | ^^^^^^^^ help: consider changing to: `&u32` + | ^^^^^^^^ help: consider using an immutable reference instead: `&u32` | = note: this is cfg-gated and may require further changes -error: this argument is a mutable reference, but not used mutably +error: this argument is a mutable reference, but never used mutably --> $DIR/needless_pass_by_ref_mut.rs:194:20 | LL | fn cfg_warn(s: &mut u32) {} - | ^^^^^^^^ help: consider changing to: `&u32` + | ^^^^^^^^ help: consider using an immutable reference instead: `&u32` | = note: this is cfg-gated and may require further changes diff --git a/tests/ui/should_impl_trait/method_list_2.rs b/tests/ui/should_impl_trait/method_list_2.rs index 3efec1c52023..57807664d86d 100644 --- a/tests/ui/should_impl_trait/method_list_2.rs +++ b/tests/ui/should_impl_trait/method_list_2.rs @@ -1,6 +1,7 @@ #![warn(clippy::all, clippy::pedantic)] #![allow( clippy::missing_errors_doc, + clippy::needless_pass_by_ref_mut, clippy::needless_pass_by_value, clippy::must_use_candidate, clippy::unused_self, diff --git a/tests/ui/should_impl_trait/method_list_2.stderr b/tests/ui/should_impl_trait/method_list_2.stderr index a3bb05bf176b..550e51803452 100644 --- a/tests/ui/should_impl_trait/method_list_2.stderr +++ b/tests/ui/should_impl_trait/method_list_2.stderr @@ -1,5 +1,5 @@ error: method `eq` can be confused for the standard trait method `std::cmp::PartialEq::eq` - --> $DIR/method_list_2.rs:26:5 + --> $DIR/method_list_2.rs:27:5 | LL | / pub fn eq(&self, other: &Self) -> bool { LL | | unimplemented!() @@ -10,7 +10,7 @@ LL | | } = note: `-D clippy::should-implement-trait` implied by `-D warnings` error: method `from_iter` can be confused for the standard trait method `std::iter::FromIterator::from_iter` - --> $DIR/method_list_2.rs:30:5 + --> $DIR/method_list_2.rs:31:5 | LL | / pub fn from_iter(iter: T) -> Self { LL | | unimplemented!() @@ -20,7 +20,7 @@ LL | | } = help: consider implementing the trait `std::iter::FromIterator` or choosing a less ambiguous method name error: method `from_str` can be confused for the standard trait method `std::str::FromStr::from_str` - --> $DIR/method_list_2.rs:34:5 + --> $DIR/method_list_2.rs:35:5 | LL | / pub fn from_str(s: &str) -> Result { LL | | unimplemented!() @@ -30,7 +30,7 @@ LL | | } = help: consider implementing the trait `std::str::FromStr` or choosing a less ambiguous method name error: method `hash` can be confused for the standard trait method `std::hash::Hash::hash` - --> $DIR/method_list_2.rs:38:5 + --> $DIR/method_list_2.rs:39:5 | LL | / pub fn hash(&self, state: &mut T) { LL | | unimplemented!() @@ -40,7 +40,7 @@ LL | | } = help: consider implementing the trait `std::hash::Hash` or choosing a less ambiguous method name error: method `index` can be confused for the standard trait method `std::ops::Index::index` - --> $DIR/method_list_2.rs:42:5 + --> $DIR/method_list_2.rs:43:5 | LL | / pub fn index(&self, index: usize) -> &Self { LL | | unimplemented!() @@ -50,7 +50,7 @@ LL | | } = help: consider implementing the trait `std::ops::Index` or choosing a less ambiguous method name error: method `index_mut` can be confused for the standard trait method `std::ops::IndexMut::index_mut` - --> $DIR/method_list_2.rs:46:5 + --> $DIR/method_list_2.rs:47:5 | LL | / pub fn index_mut(&mut self, index: usize) -> &mut Self { LL | | unimplemented!() @@ -60,7 +60,7 @@ LL | | } = help: consider implementing the trait `std::ops::IndexMut` or choosing a less ambiguous method name error: method `into_iter` can be confused for the standard trait method `std::iter::IntoIterator::into_iter` - --> $DIR/method_list_2.rs:50:5 + --> $DIR/method_list_2.rs:51:5 | LL | / pub fn into_iter(self) -> Self { LL | | unimplemented!() @@ -70,7 +70,7 @@ LL | | } = help: consider implementing the trait `std::iter::IntoIterator` or choosing a less ambiguous method name error: method `mul` can be confused for the standard trait method `std::ops::Mul::mul` - --> $DIR/method_list_2.rs:54:5 + --> $DIR/method_list_2.rs:55:5 | LL | / pub fn mul(self, rhs: Self) -> Self { LL | | unimplemented!() @@ -80,7 +80,7 @@ LL | | } = help: consider implementing the trait `std::ops::Mul` or choosing a less ambiguous method name error: method `neg` can be confused for the standard trait method `std::ops::Neg::neg` - --> $DIR/method_list_2.rs:58:5 + --> $DIR/method_list_2.rs:59:5 | LL | / pub fn neg(self) -> Self { LL | | unimplemented!() @@ -90,7 +90,7 @@ LL | | } = help: consider implementing the trait `std::ops::Neg` or choosing a less ambiguous method name error: method `next` can be confused for the standard trait method `std::iter::Iterator::next` - --> $DIR/method_list_2.rs:62:5 + --> $DIR/method_list_2.rs:63:5 | LL | / pub fn next(&mut self) -> Option { LL | | unimplemented!() @@ -100,7 +100,7 @@ LL | | } = help: consider implementing the trait `std::iter::Iterator` or choosing a less ambiguous method name error: method `not` can be confused for the standard trait method `std::ops::Not::not` - --> $DIR/method_list_2.rs:66:5 + --> $DIR/method_list_2.rs:67:5 | LL | / pub fn not(self) -> Self { LL | | unimplemented!() @@ -110,7 +110,7 @@ LL | | } = help: consider implementing the trait `std::ops::Not` or choosing a less ambiguous method name error: method `rem` can be confused for the standard trait method `std::ops::Rem::rem` - --> $DIR/method_list_2.rs:70:5 + --> $DIR/method_list_2.rs:71:5 | LL | / pub fn rem(self, rhs: Self) -> Self { LL | | unimplemented!() @@ -120,7 +120,7 @@ LL | | } = help: consider implementing the trait `std::ops::Rem` or choosing a less ambiguous method name error: method `shl` can be confused for the standard trait method `std::ops::Shl::shl` - --> $DIR/method_list_2.rs:74:5 + --> $DIR/method_list_2.rs:75:5 | LL | / pub fn shl(self, rhs: Self) -> Self { LL | | unimplemented!() @@ -130,7 +130,7 @@ LL | | } = help: consider implementing the trait `std::ops::Shl` or choosing a less ambiguous method name error: method `shr` can be confused for the standard trait method `std::ops::Shr::shr` - --> $DIR/method_list_2.rs:78:5 + --> $DIR/method_list_2.rs:79:5 | LL | / pub fn shr(self, rhs: Self) -> Self { LL | | unimplemented!() @@ -140,7 +140,7 @@ LL | | } = help: consider implementing the trait `std::ops::Shr` or choosing a less ambiguous method name error: method `sub` can be confused for the standard trait method `std::ops::Sub::sub` - --> $DIR/method_list_2.rs:82:5 + --> $DIR/method_list_2.rs:83:5 | LL | / pub fn sub(self, rhs: Self) -> Self { LL | | unimplemented!() @@ -149,14 +149,5 @@ LL | | } | = help: consider implementing the trait `std::ops::Sub` or choosing a less ambiguous method name -error: this argument is a mutable reference, but not used mutably - --> $DIR/method_list_2.rs:38:31 - | -LL | pub fn hash(&self, state: &mut T) { - | ^^^^^^ help: consider changing to: `&T` - | - = warning: changing this function will impact semver compatibility - = note: `-D clippy::needless-pass-by-ref-mut` implied by `-D warnings` - -error: aborting due to 16 previous errors +error: aborting due to 15 previous errors diff --git a/tests/ui/single_call_fn.rs b/tests/ui/single_call_fn.rs index 76e175014b87..f5996036f30f 100644 --- a/tests/ui/single_call_fn.rs +++ b/tests/ui/single_call_fn.rs @@ -72,3 +72,11 @@ fn k() {} fn l() { k(); } + +// Make sure lint attributes work properly +#[allow(clippy::single_call_fn)] +fn lint_attr_test() {} + +fn lint_attr_test_caller() { + lint_attr_test(); +} diff --git a/tests/ui/slow_vector_initialization.rs b/tests/ui/slow_vector_initialization.rs index cfb856861b8c..b48668282c6d 100644 --- a/tests/ui/slow_vector_initialization.rs +++ b/tests/ui/slow_vector_initialization.rs @@ -1,3 +1,5 @@ +#![allow(clippy::needless_pass_by_ref_mut)] + use std::iter::repeat; fn main() { diff --git a/tests/ui/slow_vector_initialization.stderr b/tests/ui/slow_vector_initialization.stderr index 532ce4ac1911..0b74db2d8002 100644 --- a/tests/ui/slow_vector_initialization.stderr +++ b/tests/ui/slow_vector_initialization.stderr @@ -1,5 +1,5 @@ error: slow zero-filling initialization - --> $DIR/slow_vector_initialization.rs:14:5 + --> $DIR/slow_vector_initialization.rs:16:5 | LL | let mut vec1 = Vec::with_capacity(len); | ----------------------- help: consider replacing this with: `vec![0; len]` @@ -9,7 +9,7 @@ LL | vec1.extend(repeat(0).take(len)); = note: `-D clippy::slow-vector-initialization` implied by `-D warnings` error: slow zero-filling initialization - --> $DIR/slow_vector_initialization.rs:18:5 + --> $DIR/slow_vector_initialization.rs:20:5 | LL | let mut vec2 = Vec::with_capacity(len - 10); | ---------------------------- help: consider replacing this with: `vec![0; len - 10]` @@ -17,7 +17,7 @@ LL | vec2.extend(repeat(0).take(len - 10)); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: slow zero-filling initialization - --> $DIR/slow_vector_initialization.rs:25:5 + --> $DIR/slow_vector_initialization.rs:27:5 | LL | let mut vec4 = Vec::with_capacity(len); | ----------------------- help: consider replacing this with: `vec![0; len]` @@ -25,7 +25,7 @@ LL | vec4.extend(repeat(0).take(vec4.capacity())); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: slow zero-filling initialization - --> $DIR/slow_vector_initialization.rs:35:5 + --> $DIR/slow_vector_initialization.rs:37:5 | LL | let mut resized_vec = Vec::with_capacity(30); | ---------------------- help: consider replacing this with: `vec![0; 30]` @@ -33,7 +33,7 @@ LL | resized_vec.resize(30, 0); | ^^^^^^^^^^^^^^^^^^^^^^^^^ error: slow zero-filling initialization - --> $DIR/slow_vector_initialization.rs:38:5 + --> $DIR/slow_vector_initialization.rs:40:5 | LL | let mut extend_vec = Vec::with_capacity(30); | ---------------------- help: consider replacing this with: `vec![0; 30]` @@ -41,7 +41,7 @@ LL | extend_vec.extend(repeat(0).take(30)); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: slow zero-filling initialization - --> $DIR/slow_vector_initialization.rs:45:5 + --> $DIR/slow_vector_initialization.rs:47:5 | LL | let mut vec1 = Vec::with_capacity(len); | ----------------------- help: consider replacing this with: `vec![0; len]` @@ -49,7 +49,7 @@ LL | vec1.resize(len, 0); | ^^^^^^^^^^^^^^^^^^^ error: slow zero-filling initialization - --> $DIR/slow_vector_initialization.rs:53:5 + --> $DIR/slow_vector_initialization.rs:55:5 | LL | let mut vec3 = Vec::with_capacity(len - 10); | ---------------------------- help: consider replacing this with: `vec![0; len - 10]` @@ -57,7 +57,7 @@ LL | vec3.resize(len - 10, 0); | ^^^^^^^^^^^^^^^^^^^^^^^^ error: slow zero-filling initialization - --> $DIR/slow_vector_initialization.rs:56:5 + --> $DIR/slow_vector_initialization.rs:58:5 | LL | let mut vec4 = Vec::with_capacity(len); | ----------------------- help: consider replacing this with: `vec![0; len]` @@ -65,7 +65,7 @@ LL | vec4.resize(vec4.capacity(), 0); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: slow zero-filling initialization - --> $DIR/slow_vector_initialization.rs:60:5 + --> $DIR/slow_vector_initialization.rs:62:5 | LL | vec1 = Vec::with_capacity(10); | ---------------------- help: consider replacing this with: `vec![0; 10]` @@ -73,7 +73,7 @@ LL | vec1.resize(10, 0); | ^^^^^^^^^^^^^^^^^^ error: slow zero-filling initialization - --> $DIR/slow_vector_initialization.rs:67:5 + --> $DIR/slow_vector_initialization.rs:69:5 | LL | let mut vec1 = Vec::new(); | ---------- help: consider replacing this with: `vec![0; len]` @@ -81,7 +81,7 @@ LL | vec1.resize(len, 0); | ^^^^^^^^^^^^^^^^^^^ error: slow zero-filling initialization - --> $DIR/slow_vector_initialization.rs:71:5 + --> $DIR/slow_vector_initialization.rs:73:5 | LL | let mut vec3 = Vec::new(); | ---------- help: consider replacing this with: `vec![0; len - 10]` @@ -89,20 +89,12 @@ LL | vec3.resize(len - 10, 0); | ^^^^^^^^^^^^^^^^^^^^^^^^ error: slow zero-filling initialization - --> $DIR/slow_vector_initialization.rs:75:5 + --> $DIR/slow_vector_initialization.rs:77:5 | LL | vec1 = Vec::new(); | ---------- help: consider replacing this with: `vec![0; 10]` LL | vec1.resize(10, 0); | ^^^^^^^^^^^^^^^^^^ -error: this argument is a mutable reference, but not used mutably - --> $DIR/slow_vector_initialization.rs:78:18 - | -LL | fn do_stuff(vec: &mut [u8]) {} - | ^^^^^^^^^ help: consider changing to: `&[u8]` - | - = note: `-D clippy::needless-pass-by-ref-mut` implied by `-D warnings` - -error: aborting due to 13 previous errors +error: aborting due to 12 previous errors From 86ce182b5a4c4e87189ac0c22fb2516b46f9fad1 Mon Sep 17 00:00:00 2001 From: Catherine Flores Date: Wed, 19 Jul 2023 04:46:41 -0500 Subject: [PATCH 2/2] Bump `clippy::version` for some lints Also moves `tuple_array_conversions` to `pedantic`, because #11171 didn't contain it fsr --- clippy_lints/src/error_impl_error.rs | 2 +- clippy_lints/src/excessive_nesting.rs | 2 +- clippy_lints/src/four_forward_slashes.rs | 2 +- clippy_lints/src/methods/mod.rs | 7 +++-- clippy_lints/src/needless_pass_by_ref_mut.rs | 2 +- clippy_lints/src/tuple_array_conversions.rs | 2 +- tests/ui/needless_pass_by_ref_mut.rs | 32 ++++++++++---------- tests/ui/needless_pass_by_ref_mut.stderr | 4 +-- 8 files changed, 27 insertions(+), 26 deletions(-) diff --git a/clippy_lints/src/error_impl_error.rs b/clippy_lints/src/error_impl_error.rs index 379af9b2234c..486a0bdde5b4 100644 --- a/clippy_lints/src/error_impl_error.rs +++ b/clippy_lints/src/error_impl_error.rs @@ -28,7 +28,7 @@ declare_clippy_lint! { /// /// impl std::error::Error for Error { ... } /// ``` - #[clippy::version = "1.72.0"] + #[clippy::version = "1.73.0"] pub ERROR_IMPL_ERROR, restriction, "exported types named `Error` that implement `Error`" diff --git a/clippy_lints/src/excessive_nesting.rs b/clippy_lints/src/excessive_nesting.rs index 8911f1872c2c..83480fc5eebe 100644 --- a/clippy_lints/src/excessive_nesting.rs +++ b/clippy_lints/src/excessive_nesting.rs @@ -56,7 +56,7 @@ declare_clippy_lint! { /// // lib.rs /// pub mod a; /// ``` - #[clippy::version = "1.70.0"] + #[clippy::version = "1.72.0"] pub EXCESSIVE_NESTING, complexity, "checks for blocks nested beyond a certain threshold" diff --git a/clippy_lints/src/four_forward_slashes.rs b/clippy_lints/src/four_forward_slashes.rs index 419c77343441..0ec52f89e716 100644 --- a/clippy_lints/src/four_forward_slashes.rs +++ b/clippy_lints/src/four_forward_slashes.rs @@ -28,7 +28,7 @@ declare_clippy_lint! { /// // ... /// } /// ``` - #[clippy::version = "1.72.0"] + #[clippy::version = "1.73.0"] pub FOUR_FORWARD_SLASHES, suspicious, "comments with 4 forward slashes (`////`) likely intended to be doc comments (`///`)" diff --git a/clippy_lints/src/methods/mod.rs b/clippy_lints/src/methods/mod.rs index dd694ce7393e..33a5bc9d32f0 100644 --- a/clippy_lints/src/methods/mod.rs +++ b/clippy_lints/src/methods/mod.rs @@ -3365,6 +3365,7 @@ declare_clippy_lint! { } declare_clippy_lint! { + /// ### What it does /// Looks for calls to [`Stdin::read_line`] to read a line from the standard input /// into a string, then later attempting to parse this string into a type without first trimming it, which will /// always fail because the string has a trailing newline in it. @@ -3415,7 +3416,7 @@ declare_clippy_lint! { /// # let c = 'c'; /// matches!(c, '\\' | '.' | '+' | '*' | '(' | ')' | '|' | '[' | ']' | '{' | '}' | '^' | '$' | '#' | '&' | '-' | '~'); /// ``` - #[clippy::version = "1.72.0"] + #[clippy::version = "1.73.0"] pub STRING_LIT_CHARS_ANY, restriction, "checks for `.chars().any(|i| i == c)`" @@ -3450,7 +3451,7 @@ declare_clippy_lint! { /// }) /// } /// ``` - #[clippy::version = "1.72.0"] + #[clippy::version = "1.73.0"] pub FORMAT_COLLECT, perf, "`format!`ing every element in a collection, then collecting the strings into a new `String`" @@ -3471,7 +3472,7 @@ declare_clippy_lint! { /// let y = v.iter().collect::>(); /// assert_eq!(x, y); /// ``` - #[clippy::version = "1.72.0"] + #[clippy::version = "1.73.0"] pub ITER_SKIP_ZERO, correctness, "disallows `.skip(0)`" diff --git a/clippy_lints/src/needless_pass_by_ref_mut.rs b/clippy_lints/src/needless_pass_by_ref_mut.rs index 077c147de1d3..dbd58392b768 100644 --- a/clippy_lints/src/needless_pass_by_ref_mut.rs +++ b/clippy_lints/src/needless_pass_by_ref_mut.rs @@ -214,7 +214,7 @@ impl<'tcx> LateLintPass<'tcx> for NeedlessPassByRefMut<'tcx> { diag.warn("changing this function will impact semver compatibility"); } if *is_cfged { - diag.note("this is cfg-gated and may require further changes"); + diag.note("this is `cfg`-gated and may require further changes"); } }, ); diff --git a/clippy_lints/src/tuple_array_conversions.rs b/clippy_lints/src/tuple_array_conversions.rs index 7eec69820924..791cbe2fead7 100644 --- a/clippy_lints/src/tuple_array_conversions.rs +++ b/clippy_lints/src/tuple_array_conversions.rs @@ -37,7 +37,7 @@ declare_clippy_lint! { /// ``` #[clippy::version = "1.72.0"] pub TUPLE_ARRAY_CONVERSIONS, - nursery, + pedantic, "checks for tuple<=>array conversions that are not done with `.into()`" } impl_lint_pass!(TupleArrayConversions => [TUPLE_ARRAY_CONVERSIONS]); diff --git a/tests/ui/needless_pass_by_ref_mut.rs b/tests/ui/needless_pass_by_ref_mut.rs index ae7b018d0e25..0e6a3dfbd8c5 100644 --- a/tests/ui/needless_pass_by_ref_mut.rs +++ b/tests/ui/needless_pass_by_ref_mut.rs @@ -4,7 +4,7 @@ use std::ptr::NonNull; fn foo(s: &mut Vec, b: &u32, x: &mut u32) { - //~^ ERROR: this argument is a mutable reference, but not used mutably + //~^ ERROR: this argument is a mutable reference, but never used mutably *x += *b + s.len() as u32; } @@ -29,7 +29,7 @@ fn foo5(s: &mut Vec) { } fn foo6(s: &mut Vec) { - //~^ ERROR: this argument is a mutable reference, but not used mutably + //~^ ERROR: this argument is a mutable reference, but never used mutably non_mut_ref(s); } @@ -42,12 +42,12 @@ impl Bar { fn bar(&mut self) {} fn mushroom(&self, vec: &mut Vec) -> usize { - //~^ ERROR: this argument is a mutable reference, but not used mutably + //~^ ERROR: this argument is a mutable reference, but never used mutably vec.len() } fn badger(&mut self, vec: &mut Vec) -> usize { - //~^ ERROR: this argument is a mutable reference, but not used mutably + //~^ ERROR: this argument is a mutable reference, but never used mutably vec.len() } } @@ -124,35 +124,35 @@ async fn f7(x: &mut i32, y: i32, z: &mut i32, a: i32) { } async fn a1(x: &mut i32) { - //~^ ERROR: this argument is a mutable reference, but not used mutably + //~^ ERROR: this argument is a mutable reference, but never used mutably println!("{:?}", x); } async fn a2(x: &mut i32, y: String) { - //~^ ERROR: this argument is a mutable reference, but not used mutably + //~^ ERROR: this argument is a mutable reference, but never used mutably println!("{:?}", x); } async fn a3(x: &mut i32, y: String, z: String) { - //~^ ERROR: this argument is a mutable reference, but not used mutably + //~^ ERROR: this argument is a mutable reference, but never used mutably println!("{:?}", x); } async fn a4(x: &mut i32, y: i32) { - //~^ ERROR: this argument is a mutable reference, but not used mutably + //~^ ERROR: this argument is a mutable reference, but never used mutably println!("{:?}", x); } async fn a5(x: i32, y: &mut i32) { - //~^ ERROR: this argument is a mutable reference, but not used mutably + //~^ ERROR: this argument is a mutable reference, but never used mutably println!("{:?}", x); } async fn a6(x: i32, y: &mut i32) { - //~^ ERROR: this argument is a mutable reference, but not used mutably + //~^ ERROR: this argument is a mutable reference, but never used mutably println!("{:?}", x); } async fn a7(x: i32, y: i32, z: &mut i32) { - //~^ ERROR: this argument is a mutable reference, but not used mutably + //~^ ERROR: this argument is a mutable reference, but never used mutably println!("{:?}", z); } async fn a8(x: i32, a: &mut i32, y: i32, z: &mut i32) { - //~^ ERROR: this argument is a mutable reference, but not used mutably + //~^ ERROR: this argument is a mutable reference, but never used mutably println!("{:?}", z); } @@ -186,14 +186,14 @@ fn lint_attr(s: &mut u32) {} #[cfg(not(feature = "a"))] fn cfg_warn(s: &mut u32) {} -//~^ ERROR: this argument is a mutable reference, but not used mutably -//~| NOTE: this is cfg-gated and may require further changes +//~^ ERROR: this argument is a mutable reference, but never used mutably +//~| NOTE: this is `cfg`-gated and may require further changes #[cfg(not(feature = "a"))] mod foo { fn cfg_warn(s: &mut u32) {} - //~^ ERROR: this argument is a mutable reference, but not used mutably - //~| NOTE: this is cfg-gated and may require further changes + //~^ ERROR: this argument is a mutable reference, but never used mutably + //~| NOTE: this is `cfg`-gated and may require further changes } fn main() { diff --git a/tests/ui/needless_pass_by_ref_mut.stderr b/tests/ui/needless_pass_by_ref_mut.stderr index 756be15af94f..c78e3e1d0791 100644 --- a/tests/ui/needless_pass_by_ref_mut.stderr +++ b/tests/ui/needless_pass_by_ref_mut.stderr @@ -84,7 +84,7 @@ error: this argument is a mutable reference, but never used mutably LL | fn cfg_warn(s: &mut u32) {} | ^^^^^^^^ help: consider using an immutable reference instead: `&u32` | - = note: this is cfg-gated and may require further changes + = note: this is `cfg`-gated and may require further changes error: this argument is a mutable reference, but never used mutably --> $DIR/needless_pass_by_ref_mut.rs:194:20 @@ -92,7 +92,7 @@ error: this argument is a mutable reference, but never used mutably LL | fn cfg_warn(s: &mut u32) {} | ^^^^^^^^ help: consider using an immutable reference instead: `&u32` | - = note: this is cfg-gated and may require further changes + = note: this is `cfg`-gated and may require further changes error: aborting due to 15 previous errors