about summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--clippy_lints/src/matches/rest_pat_in_fully_bound_struct.rs10
-rw-r--r--clippy_lints/src/misc_early/literal_suffix.rs30
-rw-r--r--clippy_lints/src/question_mark_used.rs10
-rw-r--r--clippy_lints/src/ref_patterns.rs14
-rw-r--r--clippy_lints/src/shadow.rs13
-rw-r--r--clippy_lints/src/single_char_lifetime_names.rs10
-rw-r--r--clippy_lints/src/std_instead_of_core.rs16
-rw-r--r--clippy_lints/src/strings.rs23
-rw-r--r--clippy_lints/src/suspicious_xor_used_as_pow.rs15
-rw-r--r--clippy_lints/src/types/rc_buffer.rs62
-rw-r--r--clippy_lints/src/types/rc_mutex.rs14
-rw-r--r--tests/ui/suspicious_xor_used_as_pow.stderr47
12 files changed, 163 insertions, 101 deletions
diff --git a/clippy_lints/src/matches/rest_pat_in_fully_bound_struct.rs b/clippy_lints/src/matches/rest_pat_in_fully_bound_struct.rs
index 316b2f63e4e..2154cd5b24a 100644
--- a/clippy_lints/src/matches/rest_pat_in_fully_bound_struct.rs
+++ b/clippy_lints/src/matches/rest_pat_in_fully_bound_struct.rs
@@ -1,4 +1,4 @@
-use clippy_utils::diagnostics::span_lint_and_help;
+use clippy_utils::diagnostics::span_lint_and_then;
 use rustc_hir::{Pat, PatKind, QPath};
 use rustc_lint::LateContext;
 use rustc_middle::ty;
@@ -15,13 +15,15 @@ pub(crate) fn check(cx: &LateContext<'_>, pat: &Pat<'_>) {
         && fields.len() == def.non_enum_variant().fields.len()
         && !def.non_enum_variant().is_field_list_non_exhaustive()
     {
-        span_lint_and_help(
+        #[expect(clippy::collapsible_span_lint_calls, reason = "rust-clippy#7797")]
+        span_lint_and_then(
             cx,
             REST_PAT_IN_FULLY_BOUND_STRUCTS,
             pat.span,
             "unnecessary use of `..` pattern in struct binding. All fields were already bound",
-            None,
-            "consider removing `..` from this binding",
+            |diag| {
+                diag.help("consider removing `..` from this binding");
+            },
         );
     }
 }
diff --git a/clippy_lints/src/misc_early/literal_suffix.rs b/clippy_lints/src/misc_early/literal_suffix.rs
index e0a5e401a50..22467999cd8 100644
--- a/clippy_lints/src/misc_early/literal_suffix.rs
+++ b/clippy_lints/src/misc_early/literal_suffix.rs
@@ -1,4 +1,4 @@
-use clippy_utils::diagnostics::span_lint_and_sugg;
+use clippy_utils::diagnostics::span_lint_and_then;
 use rustc_errors::Applicability;
 use rustc_lint::EarlyContext;
 use rustc_span::Span;
@@ -12,24 +12,36 @@ pub(super) fn check(cx: &EarlyContext<'_>, lit_span: Span, lit_snip: &str, suffi
     // Do not lint when literal is unsuffixed.
     if !suffix.is_empty() {
         if lit_snip.as_bytes()[maybe_last_sep_idx] == b'_' {
-            span_lint_and_sugg(
+            #[expect(clippy::collapsible_span_lint_calls, reason = "rust-clippy#7797")]
+            span_lint_and_then(
                 cx,
                 SEPARATED_LITERAL_SUFFIX,
                 lit_span,
                 format!("{sugg_type} type suffix should not be separated by an underscore"),
-                "remove the underscore",
-                format!("{}{suffix}", &lit_snip[..maybe_last_sep_idx]),
-                Applicability::MachineApplicable,
+                |diag| {
+                    diag.span_suggestion(
+                        lit_span,
+                        "remove the underscore",
+                        format!("{}{suffix}", &lit_snip[..maybe_last_sep_idx]),
+                        Applicability::MachineApplicable,
+                    );
+                },
             );
         } else {
-            span_lint_and_sugg(
+            #[expect(clippy::collapsible_span_lint_calls, reason = "rust-clippy#7797")]
+            span_lint_and_then(
                 cx,
                 UNSEPARATED_LITERAL_SUFFIX,
                 lit_span,
                 format!("{sugg_type} type suffix should be separated by an underscore"),
-                "add an underscore",
-                format!("{}_{suffix}", &lit_snip[..=maybe_last_sep_idx]),
-                Applicability::MachineApplicable,
+                |diag| {
+                    diag.span_suggestion(
+                        lit_span,
+                        "add an underscore",
+                        format!("{}_{suffix}", &lit_snip[..=maybe_last_sep_idx]),
+                        Applicability::MachineApplicable,
+                    );
+                },
             );
         }
     }
diff --git a/clippy_lints/src/question_mark_used.rs b/clippy_lints/src/question_mark_used.rs
index f5e6cb804da..0a974bf9d2f 100644
--- a/clippy_lints/src/question_mark_used.rs
+++ b/clippy_lints/src/question_mark_used.rs
@@ -1,4 +1,4 @@
-use clippy_utils::diagnostics::span_lint_and_help;
+use clippy_utils::diagnostics::span_lint_and_then;
 
 use clippy_utils::macros::span_is_local;
 use rustc_hir::{Expr, ExprKind, MatchSource};
@@ -39,13 +39,15 @@ impl<'tcx> LateLintPass<'tcx> for QuestionMarkUsed {
                 return;
             }
 
-            span_lint_and_help(
+            #[expect(clippy::collapsible_span_lint_calls, reason = "rust-clippy#7797")]
+            span_lint_and_then(
                 cx,
                 QUESTION_MARK_USED,
                 expr.span,
                 "question mark operator was used",
-                None,
-                "consider using a custom macro or match expression",
+                |diag| {
+                    diag.help("consider using a custom macro or match expression");
+                },
             );
         }
     }
diff --git a/clippy_lints/src/ref_patterns.rs b/clippy_lints/src/ref_patterns.rs
index 467038523b4..002c6c41d52 100644
--- a/clippy_lints/src/ref_patterns.rs
+++ b/clippy_lints/src/ref_patterns.rs
@@ -1,4 +1,4 @@
-use clippy_utils::diagnostics::span_lint_and_help;
+use clippy_utils::diagnostics::span_lint_and_then;
 use rustc_ast::ast::{BindingMode, Pat, PatKind};
 use rustc_lint::{EarlyContext, EarlyLintPass};
 use rustc_session::declare_lint_pass;
@@ -33,14 +33,10 @@ impl EarlyLintPass for RefPatterns {
         if let PatKind::Ident(BindingMode::REF, _, _) = pat.kind
             && !pat.span.from_expansion()
         {
-            span_lint_and_help(
-                cx,
-                REF_PATTERNS,
-                pat.span,
-                "usage of ref pattern",
-                None,
-                "consider using `&` for clarity instead",
-            );
+            #[expect(clippy::collapsible_span_lint_calls, reason = "rust-clippy#7797")]
+            span_lint_and_then(cx, REF_PATTERNS, pat.span, "usage of ref pattern", |diag| {
+                diag.help("consider using `&` for clarity instead");
+            });
         }
     }
 }
diff --git a/clippy_lints/src/shadow.rs b/clippy_lints/src/shadow.rs
index 80f5fd0b494..7ae0310b6d9 100644
--- a/clippy_lints/src/shadow.rs
+++ b/clippy_lints/src/shadow.rs
@@ -1,4 +1,4 @@
-use clippy_utils::diagnostics::span_lint_and_note;
+use clippy_utils::diagnostics::span_lint_and_then;
 use clippy_utils::source::snippet;
 use clippy_utils::visitors::is_local_used;
 use rustc_data_structures::fx::FxHashMap;
@@ -194,14 +194,9 @@ fn lint_shadow(cx: &LateContext<'_>, pat: &Pat<'_>, shadowed: HirId, span: Span)
             (SHADOW_UNRELATED, msg)
         },
     };
-    span_lint_and_note(
-        cx,
-        lint,
-        span,
-        msg,
-        Some(cx.tcx.hir().span(shadowed)),
-        "previous binding is here",
-    );
+    span_lint_and_then(cx, lint, span, msg, |diag| {
+        diag.span_note(cx.tcx.hir().span(shadowed), "previous binding is here");
+    });
 }
 
 /// Returns true if the expression is a simple transformation of a local binding such as `&x`
diff --git a/clippy_lints/src/single_char_lifetime_names.rs b/clippy_lints/src/single_char_lifetime_names.rs
index 72feb977c31..d92b890950a 100644
--- a/clippy_lints/src/single_char_lifetime_names.rs
+++ b/clippy_lints/src/single_char_lifetime_names.rs
@@ -1,4 +1,4 @@
-use clippy_utils::diagnostics::span_lint_and_help;
+use clippy_utils::diagnostics::span_lint_and_then;
 use rustc_ast::ast::{GenericParam, GenericParamKind};
 use rustc_lint::{EarlyContext, EarlyLintPass, LintContext};
 use rustc_middle::lint::in_external_macro;
@@ -48,13 +48,15 @@ impl EarlyLintPass for SingleCharLifetimeNames {
 
         if let GenericParamKind::Lifetime = param.kind {
             if !param.is_placeholder && param.ident.as_str().len() <= 2 {
-                span_lint_and_help(
+                #[expect(clippy::collapsible_span_lint_calls, reason = "rust-clippy#7797")]
+                span_lint_and_then(
                     ctx,
                     SINGLE_CHAR_LIFETIME_NAMES,
                     param.ident.span,
                     "single-character lifetime names are likely uninformative",
-                    None,
-                    "use a more informative name",
+                    |diag| {
+                        diag.help("use a more informative name");
+                    },
                 );
             }
         }
diff --git a/clippy_lints/src/std_instead_of_core.rs b/clippy_lints/src/std_instead_of_core.rs
index 84bf4e87672..974e21df817 100644
--- a/clippy_lints/src/std_instead_of_core.rs
+++ b/clippy_lints/src/std_instead_of_core.rs
@@ -1,6 +1,6 @@
 use clippy_config::msrvs::Msrv;
 use clippy_config::Conf;
-use clippy_utils::diagnostics::span_lint_and_sugg;
+use clippy_utils::diagnostics::span_lint_and_then;
 use clippy_utils::is_from_proc_macro;
 use rustc_attr::{StabilityLevel, StableSince};
 use rustc_errors::Applicability;
@@ -136,14 +136,20 @@ impl<'tcx> LateLintPass<'tcx> for StdReexports {
                 _ => return,
             };
             if first_segment.ident.span != self.prev_span {
-                span_lint_and_sugg(
+                #[expect(clippy::collapsible_span_lint_calls, reason = "rust-clippy#7797")]
+                span_lint_and_then(
                     cx,
                     lint,
                     first_segment.ident.span,
                     format!("used import from `{used_mod}` instead of `{replace_with}`"),
-                    format!("consider importing the item from `{replace_with}`"),
-                    replace_with.to_string(),
-                    Applicability::MachineApplicable,
+                    |diag| {
+                        diag.span_suggestion(
+                            first_segment.ident.span,
+                            format!("consider importing the item from `{replace_with}`"),
+                            replace_with.to_string(),
+                            Applicability::MachineApplicable,
+                        );
+                    },
                 );
                 self.prev_span = first_segment.ident.span;
             }
diff --git a/clippy_lints/src/strings.rs b/clippy_lints/src/strings.rs
index 7da661485ab..cfc387886dc 100644
--- a/clippy_lints/src/strings.rs
+++ b/clippy_lints/src/strings.rs
@@ -1,4 +1,4 @@
-use clippy_utils::diagnostics::{span_lint, span_lint_and_help, span_lint_and_sugg};
+use clippy_utils::diagnostics::{span_lint, span_lint_and_sugg, span_lint_and_then};
 use clippy_utils::source::{snippet, snippet_with_applicability};
 use clippy_utils::ty::is_type_lang_item;
 use clippy_utils::{
@@ -399,17 +399,16 @@ impl<'tcx> LateLintPass<'tcx> for StrToString {
             && let ty::Ref(_, ty, ..) = ty.kind()
             && ty.is_str()
         {
-            let mut applicability = Applicability::MachineApplicable;
-            let snippet = snippet_with_applicability(cx, self_arg.span, "..", &mut applicability);
-
-            span_lint_and_sugg(
+            span_lint_and_then(
                 cx,
                 STR_TO_STRING,
                 expr.span,
                 "`to_string()` called on a `&str`",
-                "try",
-                format!("{snippet}.to_owned()"),
-                applicability,
+                |diag| {
+                    let mut applicability = Applicability::MachineApplicable;
+                    let snippet = snippet_with_applicability(cx, self_arg.span, "..", &mut applicability);
+                    diag.span_suggestion(expr.span, "try", format!("{snippet}.to_owned()"), applicability);
+                },
             );
         }
     }
@@ -455,13 +454,15 @@ impl<'tcx> LateLintPass<'tcx> for StringToString {
             && let ty = cx.typeck_results().expr_ty(self_arg)
             && is_type_lang_item(cx, ty, LangItem::String)
         {
-            span_lint_and_help(
+            #[expect(clippy::collapsible_span_lint_calls, reason = "rust-clippy#7797")]
+            span_lint_and_then(
                 cx,
                 STRING_TO_STRING,
                 expr.span,
                 "`to_string()` called on a `String`",
-                None,
-                "consider using `.clone()`",
+                |diag| {
+                    diag.help("consider using `.clone()`");
+                },
             );
         }
     }
diff --git a/clippy_lints/src/suspicious_xor_used_as_pow.rs b/clippy_lints/src/suspicious_xor_used_as_pow.rs
index d150a5f858a..d1d822a5532 100644
--- a/clippy_lints/src/suspicious_xor_used_as_pow.rs
+++ b/clippy_lints/src/suspicious_xor_used_as_pow.rs
@@ -1,4 +1,4 @@
-use clippy_utils::diagnostics::span_lint_and_sugg;
+use clippy_utils::diagnostics::span_lint_and_then;
 use clippy_utils::numeric_literal::NumericLiteral;
 use clippy_utils::source::snippet;
 use rustc_ast::LitKind;
@@ -43,14 +43,19 @@ impl LateLintPass<'_> for ConfusingXorAndPow {
             && NumericLiteral::from_lit_kind(&snippet(cx, lit_right.span, ".."), &lit_right.node)
                 .is_some_and(|x| x.is_decimal())
         {
-            span_lint_and_sugg(
+            span_lint_and_then(
                 cx,
                 SUSPICIOUS_XOR_USED_AS_POW,
                 expr.span,
                 "`^` is not the exponentiation operator",
-                "did you mean to write",
-                format!("{}.pow({})", lit_left.node, lit_right.node),
-                Applicability::MaybeIncorrect,
+                |diag| {
+                    diag.span_suggestion_verbose(
+                        expr.span,
+                        "did you mean to write",
+                        format!("{}.pow({})", lit_left.node, lit_right.node),
+                        Applicability::MaybeIncorrect,
+                    );
+                },
             );
         }
     }
diff --git a/clippy_lints/src/types/rc_buffer.rs b/clippy_lints/src/types/rc_buffer.rs
index f6c2d8d5a5e..d691f1878b1 100644
--- a/clippy_lints/src/types/rc_buffer.rs
+++ b/clippy_lints/src/types/rc_buffer.rs
@@ -1,4 +1,4 @@
-use clippy_utils::diagnostics::span_lint_and_sugg;
+use clippy_utils::diagnostics::span_lint_and_then;
 use clippy_utils::source::snippet_with_applicability;
 use clippy_utils::{path_def_id, qpath_generic_tys};
 use rustc_errors::Applicability;
@@ -13,14 +13,15 @@ pub(super) fn check(cx: &LateContext<'_>, hir_ty: &hir::Ty<'_>, qpath: &QPath<'_
     let app = Applicability::Unspecified;
     if cx.tcx.is_diagnostic_item(sym::Rc, def_id) {
         if let Some(alternate) = match_buffer_type(cx, qpath) {
-            span_lint_and_sugg(
+            #[expect(clippy::collapsible_span_lint_calls, reason = "rust-clippy#7797")]
+            span_lint_and_then(
                 cx,
                 RC_BUFFER,
                 hir_ty.span,
                 "usage of `Rc<T>` when T is a buffer type",
-                "try",
-                format!("Rc<{alternate}>"),
-                app,
+                |diag| {
+                    diag.span_suggestion(hir_ty.span, "try", format!("Rc<{alternate}>"), app);
+                },
             );
         } else {
             let Some(ty) = qpath_generic_tys(qpath).next() else {
@@ -35,31 +36,37 @@ pub(super) fn check(cx: &LateContext<'_>, hir_ty: &hir::Ty<'_>, qpath: &QPath<'_
                 Some(ty) => ty.span,
                 None => return false,
             };
-            let mut applicability = app;
-            span_lint_and_sugg(
+            span_lint_and_then(
                 cx,
                 RC_BUFFER,
                 hir_ty.span,
                 "usage of `Rc<T>` when T is a buffer type",
-                "try",
-                format!(
-                    "Rc<[{}]>",
-                    snippet_with_applicability(cx, inner_span, "..", &mut applicability)
-                ),
-                app,
+                |diag| {
+                    let mut applicability = app;
+                    diag.span_suggestion(
+                        hir_ty.span,
+                        "try",
+                        format!(
+                            "Rc<[{}]>",
+                            snippet_with_applicability(cx, inner_span, "..", &mut applicability)
+                        ),
+                        app,
+                    );
+                },
             );
             return true;
         }
     } else if cx.tcx.is_diagnostic_item(sym::Arc, def_id) {
         if let Some(alternate) = match_buffer_type(cx, qpath) {
-            span_lint_and_sugg(
+            #[expect(clippy::collapsible_span_lint_calls, reason = "rust-clippy#7797")]
+            span_lint_and_then(
                 cx,
                 RC_BUFFER,
                 hir_ty.span,
                 "usage of `Arc<T>` when T is a buffer type",
-                "try",
-                format!("Arc<{alternate}>"),
-                app,
+                |diag| {
+                    diag.span_suggestion(hir_ty.span, "try", format!("Arc<{alternate}>"), app);
+                },
             );
         } else if let Some(ty) = qpath_generic_tys(qpath).next() {
             let Some(id) = path_def_id(cx, ty) else { return false };
@@ -71,18 +78,23 @@ pub(super) fn check(cx: &LateContext<'_>, hir_ty: &hir::Ty<'_>, qpath: &QPath<'_
                 Some(ty) => ty.span,
                 None => return false,
             };
-            let mut applicability = app;
-            span_lint_and_sugg(
+            span_lint_and_then(
                 cx,
                 RC_BUFFER,
                 hir_ty.span,
                 "usage of `Arc<T>` when T is a buffer type",
-                "try",
-                format!(
-                    "Arc<[{}]>",
-                    snippet_with_applicability(cx, inner_span, "..", &mut applicability)
-                ),
-                app,
+                |diag| {
+                    let mut applicability = app;
+                    diag.span_suggestion(
+                        hir_ty.span,
+                        "try",
+                        format!(
+                            "Arc<[{}]>",
+                            snippet_with_applicability(cx, inner_span, "..", &mut applicability)
+                        ),
+                        app,
+                    );
+                },
             );
             return true;
         }
diff --git a/clippy_lints/src/types/rc_mutex.rs b/clippy_lints/src/types/rc_mutex.rs
index afc31921704..7b13debc01e 100644
--- a/clippy_lints/src/types/rc_mutex.rs
+++ b/clippy_lints/src/types/rc_mutex.rs
@@ -1,4 +1,4 @@
-use clippy_utils::diagnostics::span_lint_and_help;
+use clippy_utils::diagnostics::span_lint_and_then;
 use clippy_utils::{path_def_id, qpath_generic_tys};
 use rustc_hir::def_id::DefId;
 use rustc_hir::{self as hir, QPath};
@@ -13,14 +13,10 @@ pub(super) fn check(cx: &LateContext<'_>, hir_ty: &hir::Ty<'_>, qpath: &QPath<'_
         && let Some(id) = path_def_id(cx, arg)
         && cx.tcx.is_diagnostic_item(sym::Mutex, id)
     {
-        span_lint_and_help(
-            cx,
-            RC_MUTEX,
-            hir_ty.span,
-            "usage of `Rc<Mutex<_>>`",
-            None,
-            "consider using `Rc<RefCell<_>>` or `Arc<Mutex<_>>` instead",
-        );
+        #[expect(clippy::collapsible_span_lint_calls, reason = "rust-clippy#7797")]
+        span_lint_and_then(cx, RC_MUTEX, hir_ty.span, "usage of `Rc<Mutex<_>>`", |diag| {
+            diag.help("consider using `Rc<RefCell<_>>` or `Arc<Mutex<_>>` instead");
+        });
         return true;
     }
 
diff --git a/tests/ui/suspicious_xor_used_as_pow.stderr b/tests/ui/suspicious_xor_used_as_pow.stderr
index 4faf0237c17..43b03676b1d 100644
--- a/tests/ui/suspicious_xor_used_as_pow.stderr
+++ b/tests/ui/suspicious_xor_used_as_pow.stderr
@@ -2,51 +2,84 @@ error: `^` is not the exponentiation operator
   --> tests/ui/suspicious_xor_used_as_pow.rs:19:13
    |
 LL |     let _ = 2 ^ 5;
-   |             ^^^^^ help: did you mean to write: `2.pow(5)`
+   |             ^^^^^
    |
    = note: `-D clippy::suspicious-xor-used-as-pow` implied by `-D warnings`
    = help: to override `-D warnings` add `#[allow(clippy::suspicious_xor_used_as_pow)]`
+help: did you mean to write
+   |
+LL |     let _ = 2.pow(5);
+   |             ~~~~~~~~
 
 error: `^` is not the exponentiation operator
   --> tests/ui/suspicious_xor_used_as_pow.rs:22:13
    |
 LL |     let _ = 2i32 ^ 9i32;
-   |             ^^^^^^^^^^^ help: did you mean to write: `2i32.pow(9i32)`
+   |             ^^^^^^^^^^^
+   |
+help: did you mean to write
+   |
+LL |     let _ = 2i32.pow(9i32);
+   |             ~~~~~~~~~~~~~~
 
 error: `^` is not the exponentiation operator
   --> tests/ui/suspicious_xor_used_as_pow.rs:24:13
    |
 LL |     let _ = 2i32 ^ 2i32;
-   |             ^^^^^^^^^^^ help: did you mean to write: `2i32.pow(2i32)`
+   |             ^^^^^^^^^^^
+   |
+help: did you mean to write
+   |
+LL |     let _ = 2i32.pow(2i32);
+   |             ~~~~~~~~~~~~~~
 
 error: `^` is not the exponentiation operator
   --> tests/ui/suspicious_xor_used_as_pow.rs:26:13
    |
 LL |     let _ = 50i32 ^ 3i32;
-   |             ^^^^^^^^^^^^ help: did you mean to write: `50i32.pow(3i32)`
+   |             ^^^^^^^^^^^^
+   |
+help: did you mean to write
+   |
+LL |     let _ = 50i32.pow(3i32);
+   |             ~~~~~~~~~~~~~~~
 
 error: `^` is not the exponentiation operator
   --> tests/ui/suspicious_xor_used_as_pow.rs:28:13
    |
 LL |     let _ = 5i32 ^ 8i32;
-   |             ^^^^^^^^^^^ help: did you mean to write: `5i32.pow(8i32)`
+   |             ^^^^^^^^^^^
+   |
+help: did you mean to write
+   |
+LL |     let _ = 5i32.pow(8i32);
+   |             ~~~~~~~~~~~~~~
 
 error: `^` is not the exponentiation operator
   --> tests/ui/suspicious_xor_used_as_pow.rs:30:13
    |
 LL |     let _ = 2i32 ^ 32i32;
-   |             ^^^^^^^^^^^^ help: did you mean to write: `2i32.pow(32i32)`
+   |             ^^^^^^^^^^^^
+   |
+help: did you mean to write
+   |
+LL |     let _ = 2i32.pow(32i32);
+   |             ~~~~~~~~~~~~~~~
 
 error: `^` is not the exponentiation operator
   --> tests/ui/suspicious_xor_used_as_pow.rs:13:9
    |
 LL |         1 ^ 2 // should warn even if inside macro
-   |         ^^^^^ help: did you mean to write: `1.pow(2)`
+   |         ^^^^^
 ...
 LL |     macro_test_inside!();
    |     -------------------- in this macro invocation
    |
    = note: this error originates in the macro `macro_test_inside` (in Nightly builds, run with -Z macro-backtrace for more info)
+help: did you mean to write
+   |
+LL |         1.pow(2) // should warn even if inside macro
+   |         ~~~~~~~~
 
 error: aborting due to 7 previous errors