From c8c64f001af613e051b8a2320cabe3bd77a92dae Mon Sep 17 00:00:00 2001 From: Samuel Moelius Date: Thu, 2 Mar 2023 10:14:11 -0500 Subject: [PATCH] Warn on line overflow when macro formatting fails --- src/macros.rs | 5 ---- tests/rustfmt/main.rs | 15 +++++++++++ tests/target/issue_5700.rs | 53 ++++++++++++++++++++++++++++++++++++++ 3 files changed, 68 insertions(+), 5 deletions(-) create mode 100644 tests/target/issue_5700.rs diff --git a/src/macros.rs b/src/macros.rs index d58f7547fef..d5383042418 100644 --- a/src/macros.rs +++ b/src/macros.rs @@ -135,11 +135,6 @@ fn return_macro_parse_failure_fallback( return trim_left_preserve_layout(context.snippet(span), indent, context.config); } - context.skipped_range.borrow_mut().push(( - context.parse_sess.line_of_byte_pos(span.lo()), - context.parse_sess.line_of_byte_pos(span.hi()), - )); - // Return the snippet unmodified if the macro is not block-like let mut snippet = context.snippet(span).to_owned(); if position == MacroPosition::Item { diff --git a/tests/rustfmt/main.rs b/tests/rustfmt/main.rs index 7ff301e8019..f7ad8128f0f 100644 --- a/tests/rustfmt/main.rs +++ b/tests/rustfmt/main.rs @@ -174,3 +174,18 @@ fn rustfmt_emits_error_on_line_overflow_true() { "line formatted, but exceeded maximum width (maximum: 100 (see `max_width` option)" )) } + +#[test] +fn rustfmt_emits_error_on_line_overflow_true_when_macro_formatting_fails() { + // See also https://github.com/rust-lang/rustfmt/issues/5700 + let args = [ + "--config", + "max_width=120,error_on_line_overflow=true", + "tests/target/issue_5700.rs", + ]; + + let (_stdout, stderr) = rustfmt(&args); + assert!(stderr.contains( + "line formatted, but exceeded maximum width (maximum: 120 (see `max_width` option)" + )) +} diff --git a/tests/target/issue_5700.rs b/tests/target/issue_5700.rs new file mode 100644 index 00000000000..9483750b8a0 --- /dev/null +++ b/tests/target/issue_5700.rs @@ -0,0 +1,53 @@ +// rustfmt-max_width: 120 + +fn check_copy_clone<'tcx>(cx: &LateContext<'tcx>, item: &Item<'_>, trait_ref: &hir::TraitRef<'_>, ty: Ty<'tcx>) { + let clone_id = match cx.tcx.lang_items().clone_trait() { + Some(id) if trait_ref.trait_def_id() == Some(id) => id, + _ => return, + }; + let Some(copy_id) = cx.tcx.lang_items().copy_trait() else { return }; + let (ty_adt, ty_subs) = match *ty.kind() { + // Unions can't derive clone. + ty::Adt(adt, subs) if !adt.is_union() => (adt, subs), + _ => return, + }; + // If the current self type doesn't implement Copy (due to generic constraints), search to see if + // there's a Copy impl for any instance of the adt. + if !is_copy(cx, ty) { + if ty_subs.non_erasable_generics().next().is_some() { + let has_copy_impl = cx.tcx.all_local_trait_impls(()).get(©_id).map_or(false, |impls| { + impls + .iter() + .any(|&id| matches!(cx.tcx.type_of(id).subst_identity().kind(), ty::Adt(adt, _) if ty_adt.did() == adt.did())) + }); + if !has_copy_impl { + return; + } + } else { + return; + } + } + // Derive constrains all generic types to requiring Clone. Check if any type is not constrained for + // this impl. + if ty_subs.types().any(|ty| !implements_trait(cx, ty, clone_id, &[])) { + return; + } + // `#[repr(packed)]` structs with type/const parameters can't derive `Clone`. + // https://github.com/rust-lang/rust-clippy/issues/10188 + if ty_adt.repr().packed() + && ty_subs + .iter() + .any(|arg| matches!(arg.unpack(), GenericArgKind::Type(_) | GenericArgKind::Const(_))) + { + return; + } + + span_lint_and_note( + cx, + EXPL_IMPL_CLONE_ON_COPY, + item.span, + "you are implementing `Clone` explicitly on a `Copy` type", + Some(item.span), + "consider deriving `Clone` or removing `Copy`", + ); +}