Skip to content

Commit cd67194

Browse files
committed
Warn on line overflow when macro formatting fails
1 parent 34f9ca2 commit cd67194

File tree

4 files changed

+77
-5
lines changed

4 files changed

+77
-5
lines changed

src/macros.rs

Lines changed: 0 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -135,11 +135,6 @@ fn return_macro_parse_failure_fallback(
135135
return trim_left_preserve_layout(context.snippet(span), indent, context.config);
136136
}
137137

138-
context.skipped_range.borrow_mut().push((
139-
context.parse_sess.line_of_byte_pos(span.lo()),
140-
context.parse_sess.line_of_byte_pos(span.hi()),
141-
));
142-
143138
// Return the snippet unmodified if the macro is not block-like
144139
let mut snippet = context.snippet(span).to_owned();
145140
if position == MacroPosition::Item {

tests/config/issue_5700.toml

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
max_width = 120
2+
comment_width = 100
3+
match_block_trailing_comma = true
4+
wrap_comments = true
5+
edition = "2021"
6+
# error_on_line_overflow = true
7+
version = "Two"

tests/rustfmt/main.rs

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -174,3 +174,20 @@ fn rustfmt_emits_error_on_line_overflow_true() {
174174
"line formatted, but exceeded maximum width (maximum: 100 (see `max_width` option)"
175175
))
176176
}
177+
178+
#[test]
179+
fn rustfmt_emits_error_on_line_overflow_true_when_macro_formatting_fails() {
180+
// See also https://github.com/rust-lang/rustfmt/issues/5700
181+
let args = [
182+
"--config-path",
183+
"tests/config/issue_5700.toml",
184+
"--config",
185+
"error_on_line_overflow=true",
186+
"tests/target/issue_5700.rs",
187+
];
188+
189+
let (_stdout, stderr) = rustfmt(&args);
190+
assert!(stderr.contains(
191+
"line formatted, but exceeded maximum width (maximum: 120 (see `max_width` option)"
192+
))
193+
}

tests/target/issue_5700.rs

Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,53 @@
1+
// rustfmt-config: issue-5700.toml
2+
3+
fn check_copy_clone<'tcx>(cx: &LateContext<'tcx>, item: &Item<'_>, trait_ref: &hir::TraitRef<'_>, ty: Ty<'tcx>) {
4+
let clone_id = match cx.tcx.lang_items().clone_trait() {
5+
Some(id) if trait_ref.trait_def_id() == Some(id) => id,
6+
_ => return,
7+
};
8+
let Some(copy_id) = cx.tcx.lang_items().copy_trait() else { return };
9+
let (ty_adt, ty_subs) = match *ty.kind() {
10+
// Unions can't derive clone.
11+
ty::Adt(adt, subs) if !adt.is_union() => (adt, subs),
12+
_ => return,
13+
};
14+
// If the current self type doesn't implement Copy (due to generic constraints), search to see if
15+
// there's a Copy impl for any instance of the adt.
16+
if !is_copy(cx, ty) {
17+
if ty_subs.non_erasable_generics().next().is_some() {
18+
let has_copy_impl = cx.tcx.all_local_trait_impls(()).get(&copy_id).map_or(false, |impls| {
19+
impls
20+
.iter()
21+
.any(|&id| matches!(cx.tcx.type_of(id).subst_identity().kind(), ty::Adt(adt, _) if ty_adt.did() == adt.did()))
22+
});
23+
if !has_copy_impl {
24+
return;
25+
}
26+
} else {
27+
return;
28+
}
29+
}
30+
// Derive constrains all generic types to requiring Clone. Check if any type is not constrained for
31+
// this impl.
32+
if ty_subs.types().any(|ty| !implements_trait(cx, ty, clone_id, &[])) {
33+
return;
34+
}
35+
// `#[repr(packed)]` structs with type/const parameters can't derive `Clone`.
36+
// https://github.com/rust-lang/rust-clippy/issues/10188
37+
if ty_adt.repr().packed()
38+
&& ty_subs
39+
.iter()
40+
.any(|arg| matches!(arg.unpack(), GenericArgKind::Type(_) | GenericArgKind::Const(_)))
41+
{
42+
return;
43+
}
44+
45+
span_lint_and_note(
46+
cx,
47+
EXPL_IMPL_CLONE_ON_COPY,
48+
item.span,
49+
"you are implementing `Clone` explicitly on a `Copy` type",
50+
Some(item.span),
51+
"consider deriving `Clone` or removing `Copy`",
52+
);
53+
}

0 commit comments

Comments
 (0)