diff --git a/Cargo.toml b/Cargo.toml index eda20531e40..321424880d1 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "clippy" -version = "0.1.77" +version = "0.1.78" description = "A bunch of helpful lints to avoid common pitfalls in Rust" repository = "https://github.com/rust-lang/rust-clippy" readme = "README.md" diff --git a/clippy_config/Cargo.toml b/clippy_config/Cargo.toml index 74b8e5eaa1c..2edc5ed592c 100644 --- a/clippy_config/Cargo.toml +++ b/clippy_config/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "clippy_config" -version = "0.1.77" +version = "0.1.78" edition = "2021" # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html diff --git a/clippy_dev/src/update_lints.rs b/clippy_dev/src/update_lints.rs index 9a357466923..2222abff7ad 100644 --- a/clippy_dev/src/update_lints.rs +++ b/clippy_dev/src/update_lints.rs @@ -927,7 +927,7 @@ fn remove_line_splices(s: &str) -> String { .and_then(|s| s.strip_suffix('"')) .unwrap_or_else(|| panic!("expected quoted string, found `{s}`")); let mut res = String::with_capacity(s.len()); - unescape::unescape_literal(s, unescape::Mode::Str, &mut |range, ch| { + unescape::unescape_unicode(s, unescape::Mode::Str, &mut |range, ch| { if ch.is_ok() { res.push_str(&s[range]); } diff --git a/clippy_lints/Cargo.toml b/clippy_lints/Cargo.toml index 416e9a680dd..6e6e315bb65 100644 --- a/clippy_lints/Cargo.toml +++ b/clippy_lints/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "clippy_lints" -version = "0.1.77" +version = "0.1.78" description = "A bunch of helpful lints to avoid common pitfalls in Rust" repository = "https://github.com/rust-lang/rust-clippy" readme = "README.md" diff --git a/clippy_lints/src/dereference.rs b/clippy_lints/src/dereference.rs index 8ff54dfcfa0..194cf69ea7e 100644 --- a/clippy_lints/src/dereference.rs +++ b/clippy_lints/src/dereference.rs @@ -881,6 +881,7 @@ impl TyCoercionStability { | ty::Coroutine(..) | ty::CoroutineWitness(..) | ty::Closure(..) + | ty::CoroutineClosure(..) | ty::Never | ty::Tuple(_) | ty::Alias(ty::Projection, _) => Self::Deref, diff --git a/clippy_lints/src/methods/iter_nth_zero.rs b/clippy_lints/src/methods/iter_nth_zero.rs index e1f950d5a4a..262a57ab591 100644 --- a/clippy_lints/src/methods/iter_nth_zero.rs +++ b/clippy_lints/src/methods/iter_nth_zero.rs @@ -11,7 +11,7 @@ use rustc_span::sym; use super::ITER_NTH_ZERO; pub(super) fn check(cx: &LateContext<'_>, expr: &hir::Expr<'_>, recv: &hir::Expr<'_>, arg: &hir::Expr<'_>) { - if let OwnerNode::Item(item) = cx.tcx.hir().owner(cx.tcx.hir().get_parent_item(expr.hir_id)) + if let OwnerNode::Item(item) = cx.tcx.hir_owner_node(cx.tcx.hir().get_parent_item(expr.hir_id)) && let def_id = item.owner_id.to_def_id() && is_trait_method(cx, expr, sym::Iterator) && let Some(Constant::Int(0)) = constant(cx, cx.typeck_results(), arg) diff --git a/clippy_lints/src/min_ident_chars.rs b/clippy_lints/src/min_ident_chars.rs index 34b8e0dbe6a..41168230752 100644 --- a/clippy_lints/src/min_ident_chars.rs +++ b/clippy_lints/src/min_ident_chars.rs @@ -93,9 +93,7 @@ impl Visitor<'_> for IdentVisitor<'_, '_> { // reimplement it even if we wanted to cx.tcx.opt_hir_node(hir_id) } else { - let Some(owner) = cx.tcx.hir_owner_nodes(hir_id.owner).as_owner() else { - return; - }; + let owner = cx.tcx.hir_owner_nodes(hir_id.owner); owner.nodes.get(hir_id.local_id).copied().flatten().map(|p| p.node) }; let Some(node) = node else { diff --git a/clippy_lints/src/operators/arithmetic_side_effects.rs b/clippy_lints/src/operators/arithmetic_side_effects.rs index 929efb6c574..96ea063aa74 100644 --- a/clippy_lints/src/operators/arithmetic_side_effects.rs +++ b/clippy_lints/src/operators/arithmetic_side_effects.rs @@ -1,11 +1,11 @@ use super::ARITHMETIC_SIDE_EFFECTS; use clippy_utils::consts::{constant, constant_simple, Constant}; use clippy_utils::diagnostics::span_lint; -use clippy_utils::ty::type_diagnostic_name; +use clippy_utils::ty::is_type_diagnostic_item; use clippy_utils::{expr_or_init, is_from_proc_macro, is_lint_allowed, peel_hir_expr_refs, peel_hir_expr_unary}; use rustc_data_structures::fx::{FxHashMap, FxHashSet}; use rustc_lint::{LateContext, LateLintPass}; -use rustc_middle::ty::Ty; +use rustc_middle::ty::{self, Ty}; use rustc_session::impl_lint_pass; use rustc_span::source_map::Spanned; use rustc_span::symbol::sym; @@ -88,37 +88,44 @@ impl ArithmeticSideEffects { } /// Verifies built-in types that have specific allowed operations - fn has_specific_allowed_type_and_operation( - cx: &LateContext<'_>, - lhs_ty: Ty<'_>, + fn has_specific_allowed_type_and_operation<'tcx>( + cx: &LateContext<'tcx>, + lhs_ty: Ty<'tcx>, op: &Spanned, - rhs_ty: Ty<'_>, + rhs_ty: Ty<'tcx>, ) -> bool { let is_div_or_rem = matches!(op.node, hir::BinOpKind::Div | hir::BinOpKind::Rem); - let is_non_zero_u = |symbol: Option| { - matches!( - symbol, - Some( - sym::NonZeroU128 - | sym::NonZeroU16 - | sym::NonZeroU32 - | sym::NonZeroU64 - | sym::NonZeroU8 - | sym::NonZeroUsize - ) - ) + let is_non_zero_u = |cx: &LateContext<'tcx>, ty: Ty<'tcx>| { + let tcx = cx.tcx; + + let ty::Adt(adt, substs) = ty.kind() else { return false }; + + if !tcx.is_diagnostic_item(sym::NonZero, adt.did()) { + return false; + }; + + let int_type = substs.type_at(0); + let unsigned_int_types = [ + tcx.types.u8, + tcx.types.u16, + tcx.types.u32, + tcx.types.u64, + tcx.types.u128, + tcx.types.usize, + ]; + + unsigned_int_types.contains(&int_type) }; let is_sat_or_wrap = |ty: Ty<'_>| { - let is_sat = type_diagnostic_name(cx, ty) == Some(sym::Saturating); - let is_wrap = type_diagnostic_name(cx, ty) == Some(sym::Wrapping); - is_sat || is_wrap + is_type_diagnostic_item(cx, ty, sym::Saturating) || is_type_diagnostic_item(cx, ty, sym::Wrapping) }; - // If the RHS is NonZeroU*, then division or module by zero will never occur - if is_non_zero_u(type_diagnostic_name(cx, rhs_ty)) && is_div_or_rem { + // If the RHS is `NonZero`, then division or module by zero will never occur. + if is_non_zero_u(cx, rhs_ty) && is_div_or_rem { return true; } - // `Saturation` and `Wrapping` can overflow if the RHS is zero in a division or module + + // `Saturation` and `Wrapping` can overflow if the RHS is zero in a division or module. if is_sat_or_wrap(lhs_ty) { return !is_div_or_rem; } diff --git a/clippy_lints/src/returns.rs b/clippy_lints/src/returns.rs index 6c522048b5c..2af466d3f51 100644 --- a/clippy_lints/src/returns.rs +++ b/clippy_lints/src/returns.rs @@ -196,7 +196,7 @@ impl<'tcx> LateLintPass<'tcx> for Return { && is_res_lang_ctor(cx, path_res(cx, maybe_constr), ResultErr) // Ensure this is not the final stmt, otherwise removing it would cause a compile error - && let OwnerNode::Item(item) = cx.tcx.hir().owner(cx.tcx.hir().get_parent_item(expr.hir_id)) + && let OwnerNode::Item(item) = cx.tcx.hir_owner_node(cx.tcx.hir().get_parent_item(expr.hir_id)) && let ItemKind::Fn(_, _, body) = item.kind && let block = cx.tcx.hir().body(body).value && let ExprKind::Block(block, _) = block.kind diff --git a/clippy_lints/src/transmute/transmute_int_to_non_zero.rs b/clippy_lints/src/transmute/transmute_int_to_non_zero.rs index 5df645491ff..97068efd43c 100644 --- a/clippy_lints/src/transmute/transmute_int_to_non_zero.rs +++ b/clippy_lints/src/transmute/transmute_int_to_non_zero.rs @@ -16,40 +16,55 @@ pub(super) fn check<'tcx>( to_ty: Ty<'tcx>, arg: &'tcx Expr<'_>, ) -> bool { - let (ty::Int(_) | ty::Uint(_), Some(to_ty_adt)) = (&from_ty.kind(), to_ty.ty_adt_def()) else { - return false; - }; - let Some(to_type_sym) = cx.tcx.get_diagnostic_name(to_ty_adt.did()) else { + let tcx = cx.tcx; + + let (ty::Int(_) | ty::Uint(_), ty::Adt(adt, substs)) = (&from_ty.kind(), to_ty.kind()) else { return false; }; - if !matches!( - to_type_sym, - sym::NonZeroU8 - | sym::NonZeroU16 - | sym::NonZeroU32 - | sym::NonZeroU64 - | sym::NonZeroU128 - | sym::NonZeroI8 - | sym::NonZeroI16 - | sym::NonZeroI32 - | sym::NonZeroI64 - | sym::NonZeroI128 - ) { + if !tcx.is_diagnostic_item(sym::NonZero, adt.did()) { return false; - } + }; + + // FIXME: This can be simplified once `NonZero` is stable. + let coercable_types = [ + ("NonZeroU8", tcx.types.u8), + ("NonZeroU16", tcx.types.u16), + ("NonZeroU32", tcx.types.u32), + ("NonZeroU64", tcx.types.u64), + ("NonZeroU128", tcx.types.u128), + ("NonZeroUsize", tcx.types.usize), + ("NonZeroI8", tcx.types.i8), + ("NonZeroI16", tcx.types.i16), + ("NonZeroI32", tcx.types.i32), + ("NonZeroI64", tcx.types.i64), + ("NonZeroI128", tcx.types.i128), + ("NonZeroIsize", tcx.types.isize), + ]; + + let int_type = substs.type_at(0); + + let Some(nonzero_alias) = coercable_types.iter().find_map(|(nonzero_alias, t)| { + if *t == int_type && *t == from_ty { + Some(nonzero_alias) + } else { + None + } + }) else { + return false; + }; span_lint_and_then( cx, TRANSMUTE_INT_TO_NON_ZERO, e.span, - &format!("transmute from a `{from_ty}` to a `{to_type_sym}`"), + &format!("transmute from a `{from_ty}` to a `{nonzero_alias}`"), |diag| { let arg = sugg::Sugg::hir(cx, arg, ".."); diag.span_suggestion( e.span, "consider using", - format!("{to_type_sym}::{}({arg})", sym::new_unchecked), + format!("{nonzero_alias}::{}({arg})", sym::new_unchecked), Applicability::Unspecified, ); }, diff --git a/clippy_lints/src/transmute/utils.rs b/clippy_lints/src/transmute/utils.rs index 1cf6cf8548a..7a7bb9f9c94 100644 --- a/clippy_lints/src/transmute/utils.rs +++ b/clippy_lints/src/transmute/utils.rs @@ -37,12 +37,6 @@ pub(super) fn check_cast<'tcx>( let inherited = Inherited::new(cx.tcx, local_def_id); let fn_ctxt = FnCtxt::new(&inherited, cx.param_env, local_def_id); - // If we already have errors, we can't be sure we can pointer cast. - assert!( - !fn_ctxt.errors_reported_since_creation(), - "Newly created FnCtxt contained errors" - ); - if let Ok(check) = cast::CastCheck::new( &fn_ctxt, e, @@ -53,17 +47,7 @@ pub(super) fn check_cast<'tcx>( DUMMY_SP, hir::Constness::NotConst, ) { - let res = check.do_check(&fn_ctxt); - - // do_check's documentation says that it might return Ok and create - // errors in the fcx instead of returning Err in some cases. Those cases - // should be filtered out before getting here. - assert!( - !fn_ctxt.errors_reported_since_creation(), - "`fn_ctxt` contained errors after cast check!" - ); - - res.ok() + check.do_check(&fn_ctxt).ok() } else { None } diff --git a/clippy_lints/src/utils/author.rs b/clippy_lints/src/utils/author.rs index b26ebe5cee3..29c67341a46 100644 --- a/clippy_lints/src/utils/author.rs +++ b/clippy_lints/src/utils/author.rs @@ -490,6 +490,9 @@ impl<'a, 'tcx> PrintVisitor<'a, 'tcx> { format!("ClosureKind::Coroutine(CoroutineKind::Coroutine(Movability::{movability:?})") }, }, + ClosureKind::CoroutineClosure(desugaring) => { + format!("ClosureKind::CoroutineClosure(CoroutineDesugaring::{desugaring:?})") + }, }; let ret_ty = match fn_decl.output { diff --git a/clippy_utils/Cargo.toml b/clippy_utils/Cargo.toml index b8869eedf52..c7454fa3328 100644 --- a/clippy_utils/Cargo.toml +++ b/clippy_utils/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "clippy_utils" -version = "0.1.77" +version = "0.1.78" edition = "2021" publish = false diff --git a/declare_clippy_lint/Cargo.toml b/declare_clippy_lint/Cargo.toml index 5aaafb41721..0f90cef5cdd 100644 --- a/declare_clippy_lint/Cargo.toml +++ b/declare_clippy_lint/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "declare_clippy_lint" -version = "0.1.77" +version = "0.1.78" edition = "2021" publish = false diff --git a/rust-toolchain b/rust-toolchain index d2d56e59ee3..fcf5c456270 100644 --- a/rust-toolchain +++ b/rust-toolchain @@ -1,3 +1,3 @@ [toolchain] -channel = "nightly-2024-01-25" +channel = "nightly-2024-02-08" components = ["cargo", "llvm-tools", "rust-src", "rust-std", "rustc", "rustc-dev", "rustfmt"] diff --git a/tests/ui/author/blocks.stdout b/tests/ui/author/blocks.stdout index 8c4d71e68f8..579f137f861 100644 --- a/tests/ui/author/blocks.stdout +++ b/tests/ui/author/blocks.stdout @@ -40,10 +40,10 @@ if let ExprKind::Block(block, None) = expr.kind { // report your lint here } -if let ExprKind::Closure { capture_clause: CaptureBy::Value { .. }, fn_decl: fn_decl, body: body_id, closure_kind: ClosureKind::Closure, .. } = expr.kind +if let ExprKind::Closure { capture_clause: CaptureBy::Value { .. }, fn_decl: fn_decl, body: body_id, closure_kind: ClosureKind::CoroutineClosure(CoroutineDesugaring::Async), .. } = expr.kind && let FnRetTy::DefaultReturn(_) = fn_decl.output && expr1 = &cx.tcx.hir().body(body_id).value - && let ExprKind::Closure { capture_clause: CaptureBy::Value { .. }, fn_decl: fn_decl1, body: body_id1, closure_kind: ClosureKind::Coroutine(CoroutineKind::Desugared(CoroutineDesugaring::Async, CoroutineSource::Closure)), .. } = expr1.kind + && let ExprKind::Closure { capture_clause: CaptureBy::Ref, fn_decl: fn_decl1, body: body_id1, closure_kind: ClosureKind::Coroutine(CoroutineKind::Desugared(CoroutineDesugaring::Async, CoroutineSource::Closure)), .. } = expr1.kind && let FnRetTy::DefaultReturn(_) = fn_decl1.output && expr2 = &cx.tcx.hir().body(body_id1).value && let ExprKind::Block(block, None) = expr2.kind diff --git a/tests/ui/crashes/ice-6254.rs b/tests/ui/crashes/ice-6254.rs index 2ae426cf789..8af60890390 100644 --- a/tests/ui/crashes/ice-6254.rs +++ b/tests/ui/crashes/ice-6254.rs @@ -11,8 +11,6 @@ fn main() { // This used to cause an ICE (https://github.com/rust-lang/rust/issues/78071) match FOO_REF_REF { FOO_REF_REF => {}, - //~^ ERROR: to use a constant of type `Foo` in a pattern, `Foo` must be annotated - //~| NOTE: for more information, see issue #62411 {}, } } diff --git a/tests/ui/crashes/ice-6254.stderr b/tests/ui/crashes/ice-6254.stderr deleted file mode 100644 index 7a34e6cceee..00000000000 --- a/tests/ui/crashes/ice-6254.stderr +++ /dev/null @@ -1,15 +0,0 @@ -error: to use a constant of type `Foo` in a pattern, `Foo` must be annotated with `#[derive(PartialEq, Eq)]` - --> $DIR/ice-6254.rs:13:9 - | -LL | FOO_REF_REF => {}, - | ^^^^^^^^^^^ - | - = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! - = note: for more information, see issue #62411 - = note: the traits must be derived, manual `impl`s are not sufficient - = note: see https://doc.rust-lang.org/stable/std/marker/trait.StructuralEq.html for details - = note: `-D indirect-structural-match` implied by `-D warnings` - = help: to override `-D warnings` add `#[allow(indirect_structural_match)]` - -error: aborting due to 1 previous error - diff --git a/tests/ui/expect_tool_lint_rfc_2383.rs b/tests/ui/expect_tool_lint_rfc_2383.rs index 5fab9ceb679..72097bfabd7 100644 --- a/tests/ui/expect_tool_lint_rfc_2383.rs +++ b/tests/ui/expect_tool_lint_rfc_2383.rs @@ -20,12 +20,8 @@ mod rustc_ok { pub fn rustc_lints() { let x = 42.0; - #[expect(illegal_floating_point_literal_pattern)] - match x { - 5.0 => {}, - 6.0 => {}, - _ => {}, - } + #[expect(invalid_nan_comparisons)] + let _b = x == f32::NAN; } } @@ -38,13 +34,9 @@ mod rustc_warn { pub fn rustc_lints() { let x = 42; - #[expect(illegal_floating_point_literal_pattern)] + #[expect(invalid_nan_comparisons)] //~^ ERROR: this lint expectation is unfulfilled - match x { - 5 => {}, - 6 => {}, - _ => {}, - } + let _b = x == 5; } } diff --git a/tests/ui/expect_tool_lint_rfc_2383.stderr b/tests/ui/expect_tool_lint_rfc_2383.stderr index 3f8d0b72436..2a418d84566 100644 --- a/tests/ui/expect_tool_lint_rfc_2383.stderr +++ b/tests/ui/expect_tool_lint_rfc_2383.stderr @@ -1,5 +1,5 @@ error: this lint expectation is unfulfilled - --> $DIR/expect_tool_lint_rfc_2383.rs:35:14 + --> $DIR/expect_tool_lint_rfc_2383.rs:31:14 | LL | #[expect(dead_code)] | ^^^^^^^^^ @@ -8,31 +8,31 @@ LL | #[expect(dead_code)] = help: to override `-D warnings` add `#[allow(unfulfilled_lint_expectations)]` error: this lint expectation is unfulfilled - --> $DIR/expect_tool_lint_rfc_2383.rs:41:18 + --> $DIR/expect_tool_lint_rfc_2383.rs:37:18 | -LL | #[expect(illegal_floating_point_literal_pattern)] - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +LL | #[expect(invalid_nan_comparisons)] + | ^^^^^^^^^^^^^^^^^^^^^^^ error: this lint expectation is unfulfilled - --> $DIR/expect_tool_lint_rfc_2383.rs:116:14 + --> $DIR/expect_tool_lint_rfc_2383.rs:108:14 | LL | #[expect(clippy::almost_swapped)] | ^^^^^^^^^^^^^^^^^^^^^^ error: this lint expectation is unfulfilled - --> $DIR/expect_tool_lint_rfc_2383.rs:124:14 + --> $DIR/expect_tool_lint_rfc_2383.rs:116:14 | LL | #[expect(clippy::bytes_nth)] | ^^^^^^^^^^^^^^^^^ error: this lint expectation is unfulfilled - --> $DIR/expect_tool_lint_rfc_2383.rs:130:14 + --> $DIR/expect_tool_lint_rfc_2383.rs:122:14 | LL | #[expect(clippy::if_same_then_else)] | ^^^^^^^^^^^^^^^^^^^^^^^^^ error: this lint expectation is unfulfilled - --> $DIR/expect_tool_lint_rfc_2383.rs:136:14 + --> $DIR/expect_tool_lint_rfc_2383.rs:128:14 | LL | #[expect(clippy::overly_complex_bool_expr)] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ diff --git a/tests/ui/modulo_one.rs b/tests/ui/modulo_one.rs index c1dbe9d9a87..c332a15f157 100644 --- a/tests/ui/modulo_one.rs +++ b/tests/ui/modulo_one.rs @@ -33,7 +33,6 @@ fn main() { INT_MIN % NEG_ONE; //~^ ERROR: this operation will panic at runtime //~| ERROR: any number modulo -1 will panic/overflow or result in 0 - // ONLY caught by rustc + // Not caught by lint, we don't look into static items, even if entirely immutable. INT_MIN % STATIC_NEG_ONE; - //~^ ERROR: this operation will panic at runtime } diff --git a/tests/ui/modulo_one.stderr b/tests/ui/modulo_one.stderr index cc211ab6cd3..06bbb0f5d9a 100644 --- a/tests/ui/modulo_one.stderr +++ b/tests/ui/modulo_one.stderr @@ -12,12 +12,6 @@ error: this operation will panic at runtime LL | INT_MIN % NEG_ONE; | ^^^^^^^^^^^^^^^^^ attempt to compute `i64::MIN % -1_i64`, which would overflow -error: this operation will panic at runtime - --> $DIR/modulo_one.rs:37:5 - | -LL | INT_MIN % STATIC_NEG_ONE; - | ^^^^^^^^^^^^^^^^^^^^^^^^ attempt to compute `i64::MIN % -1_i64`, which would overflow - error: any number modulo 1 will be 0 --> $DIR/modulo_one.rs:8:5 | @@ -57,5 +51,5 @@ error: any number modulo -1 will panic/overflow or result in 0 LL | INT_MIN % NEG_ONE; | ^^^^^^^^^^^^^^^^^ -error: aborting due to 9 previous errors +error: aborting due to 8 previous errors diff --git a/tests/ui/same_name_method.rs b/tests/ui/same_name_method.rs index 1c166a19b0a..26b1a299ba1 100644 --- a/tests/ui/same_name_method.rs +++ b/tests/ui/same_name_method.rs @@ -74,6 +74,7 @@ mod should_lint { impl S { fn foo() {} //~^ ERROR: method's name is the same as an existing method in a trait + //~| ERROR: method's name is the same as an existing method in a trait } impl T1 for S {} diff --git a/tests/ui/same_name_method.stderr b/tests/ui/same_name_method.stderr index 3c5c4a53ad1..82f5ef6a9e8 100644 --- a/tests/ui/same_name_method.stderr +++ b/tests/ui/same_name_method.stderr @@ -56,10 +56,22 @@ LL | fn foo() {} | ^^^^^^^^^^^ | note: existing `foo` defined here - --> $DIR/same_name_method.rs:79:9 + --> $DIR/same_name_method.rs:80:9 | LL | impl T1 for S {} | ^^^^^^^^^^^^^^^^ -error: aborting due to 5 previous errors +error: method's name is the same as an existing method in a trait + --> $DIR/same_name_method.rs:75:13 + | +LL | fn foo() {} + | ^^^^^^^^^^^ + | +note: existing `foo` defined here + --> $DIR/same_name_method.rs:82:9 + | +LL | impl T2 for S {} + | ^^^^^^^^^^^^^^^^ + +error: aborting due to 6 previous errors