From ff6ebd398d13ad718fb1d4738f32c0dad8f5354d Mon Sep 17 00:00:00 2001 From: ding-young Date: Sun, 17 Nov 2024 15:07:10 +0900 Subject: [PATCH 1/2] fix panic on failure to format generics in enum - related issues: #5738, #6137, #6318, #6378 - instead of calling unwrap(), restore original snippet when we fail to format generics in enum - we need to propagate this rewrite failure later --- src/items.rs | 10 +++++++--- tests/source/crash-on-enum-generics/issue_5738.rs | 13 +++++++++++++ tests/source/crash-on-enum-generics/issue_6137.rs | 3 +++ tests/source/crash-on-enum-generics/issue_6318.rs | 13 +++++++++++++ tests/target/crash-on-enum-generics/issue_5738.rs | 13 +++++++++++++ tests/target/crash-on-enum-generics/issue_6137.rs | 3 +++ tests/target/crash-on-enum-generics/issue_6318.rs | 12 ++++++++++++ 7 files changed, 64 insertions(+), 3 deletions(-) create mode 100644 tests/source/crash-on-enum-generics/issue_5738.rs create mode 100644 tests/source/crash-on-enum-generics/issue_6137.rs create mode 100644 tests/source/crash-on-enum-generics/issue_6318.rs create mode 100644 tests/target/crash-on-enum-generics/issue_5738.rs create mode 100644 tests/target/crash-on-enum-generics/issue_6137.rs create mode 100644 tests/target/crash-on-enum-generics/issue_6318.rs diff --git a/src/items.rs b/src/items.rs index 28dfb718af6..12cdbadfd94 100644 --- a/src/items.rs +++ b/src/items.rs @@ -550,9 +550,13 @@ impl<'a> FmtVisitor<'a> { // make a span that starts right after `enum Foo` mk_sp(ident.span.hi(), body_start), last_line_width(&enum_header), - ) - .unwrap(); - self.push_str(&generics_str); + ); + + if let Some(generics_str) = generics_str { + self.push_str(&generics_str); + } else { + self.push_str(self.snippet(mk_sp(ident.span.hi(), body_start))); + } self.last_pos = body_start; diff --git a/tests/source/crash-on-enum-generics/issue_5738.rs b/tests/source/crash-on-enum-generics/issue_5738.rs new file mode 100644 index 00000000000..bdba3b10944 --- /dev/null +++ b/tests/source/crash-on-enum-generics/issue_5738.rs @@ -0,0 +1,13 @@ +enum Node where P::>>>>>>>>>>>>>>>>>>>>>>>: { + Cons, +} + +enum En6 +where + T: Tr1>>>>>>>>>>>>>>>>>>>>>>>, +{ + V0, + V1, + V2, + V3, +} diff --git a/tests/source/crash-on-enum-generics/issue_6137.rs b/tests/source/crash-on-enum-generics/issue_6137.rs new file mode 100644 index 00000000000..a8c75f8e179 --- /dev/null +++ b/tests/source/crash-on-enum-generics/issue_6137.rs @@ -0,0 +1,3 @@ +enum MZReaderType< + D: DeconvolutedCentroidLike + Default + From + BuildFromArrayMap=DeconvolutedPeak +> {} diff --git a/tests/source/crash-on-enum-generics/issue_6318.rs b/tests/source/crash-on-enum-generics/issue_6318.rs new file mode 100644 index 00000000000..787225f4aae --- /dev/null +++ b/tests/source/crash-on-enum-generics/issue_6318.rs @@ -0,0 +1,13 @@ +// rustfmt-max_width: 80 +fn my_fn() { + enum MyEnum + where + SomeTypeA___: SomeTrait__< + _A, + Archived = , + >>::Archived, + >, + { + } +} diff --git a/tests/target/crash-on-enum-generics/issue_5738.rs b/tests/target/crash-on-enum-generics/issue_5738.rs new file mode 100644 index 00000000000..4a9dd0d8a1c --- /dev/null +++ b/tests/target/crash-on-enum-generics/issue_5738.rs @@ -0,0 +1,13 @@ +enum Node where P::>>>>>>>>>>>>>>>>>>>>>>>: { + Cons, +} + +enum En6 +where + T: Tr1>>>>>>>>>>>>>>>>>>>>>>>, +{ + V0, + V1, + V2, + V3, +} diff --git a/tests/target/crash-on-enum-generics/issue_6137.rs b/tests/target/crash-on-enum-generics/issue_6137.rs new file mode 100644 index 00000000000..a8c75f8e179 --- /dev/null +++ b/tests/target/crash-on-enum-generics/issue_6137.rs @@ -0,0 +1,3 @@ +enum MZReaderType< + D: DeconvolutedCentroidLike + Default + From + BuildFromArrayMap=DeconvolutedPeak +> {} diff --git a/tests/target/crash-on-enum-generics/issue_6318.rs b/tests/target/crash-on-enum-generics/issue_6318.rs new file mode 100644 index 00000000000..6f3b9275349 --- /dev/null +++ b/tests/target/crash-on-enum-generics/issue_6318.rs @@ -0,0 +1,12 @@ +// rustfmt-max_width: 80 +fn my_fn() { + enum MyEnum + where + SomeTypeA___: SomeTrait__< + _A, + Archived = , + >>::Archived, + >, + {} +} From af031690ce97765ac69ff62be0308197cfc7a552 Mon Sep 17 00:00:00 2001 From: ding-young Date: Fri, 29 Nov 2024 17:55:34 +0900 Subject: [PATCH 2/2] refactor visit_enum - introduce format_enum that returns Rewrite - early return when it fails to format the generics in enum --- src/items.rs | 42 ++++++++++++------- src/visitor.rs | 2 - .../crash-on-enum-generics/issue_5738.rs | 2 +- .../crash-on-enum-generics/issue_6318.rs | 1 + .../crash-on-enum-generics/issue_5738.rs | 2 +- .../crash-on-enum-generics/issue_6318.rs | 4 +- 6 files changed, 33 insertions(+), 20 deletions(-) diff --git a/src/items.rs b/src/items.rs index 12cdbadfd94..7c9b7a235fb 100644 --- a/src/items.rs +++ b/src/items.rs @@ -522,21 +522,22 @@ impl<'a> FmtVisitor<'a> { self.push_rewrite(struct_parts.span, rewrite); } - pub(crate) fn visit_enum( + // TODO(ding-young) do I need to make it a separate function instead of a method of FmtVisitor? + fn format_enum( &mut self, ident: symbol::Ident, vis: &ast::Visibility, enum_def: &ast::EnumDef, generics: &ast::Generics, span: Span, - ) { + ) -> Option { let enum_header = format_header(&self.get_context(), "enum ", ident, vis, self.block_indent); - self.push_str(&enum_header); let enum_snippet = self.snippet(span); let brace_pos = enum_snippet.find_uncommented("{").unwrap(); let body_start = span.lo() + BytePos(brace_pos as u32 + 1); + // TODO(ding-young) what if there is no generic? let generics_str = format_generics( &self.get_context(), generics, @@ -550,25 +551,36 @@ impl<'a> FmtVisitor<'a> { // make a span that starts right after `enum Foo` mk_sp(ident.span.hi(), body_start), last_line_width(&enum_header), - ); - - if let Some(generics_str) = generics_str { - self.push_str(&generics_str); - } else { - self.push_str(self.snippet(mk_sp(ident.span.hi(), body_start))); - } - - self.last_pos = body_start; + )?; match self.format_variant_list(enum_def, body_start, span.hi()) { - Some(ref s) if enum_def.variants.is_empty() => self.push_str(s), - rw => { - self.push_rewrite(mk_sp(body_start, span.hi()), rw); + Some(ref s) if enum_def.variants.is_empty() => { + Some(format!("{enum_header}{generics_str}{s}")) + } + Some(rw) => { + let indent = self.block_indent.to_string(self.config); + self.block_indent = self.block_indent.block_unindent(self.config); + Some(format!("{enum_header}{generics_str}\n{indent}{rw}")) + } + None => { self.block_indent = self.block_indent.block_unindent(self.config); + None } } } + pub(crate) fn visit_enum( + &mut self, + ident: symbol::Ident, + vis: &ast::Visibility, + enum_def: &ast::EnumDef, + generics: &ast::Generics, + span: Span, + ) { + let rewrite = self.format_enum(ident, vis, enum_def, generics, span); + self.push_rewrite(span, rewrite); + } + // Format the body of an enum definition fn format_variant_list( &mut self, diff --git a/src/visitor.rs b/src/visitor.rs index fb94819c56f..301cc088699 100644 --- a/src/visitor.rs +++ b/src/visitor.rs @@ -515,9 +515,7 @@ impl<'b, 'a: 'b> FmtVisitor<'a> { self.visit_struct(&StructParts::from_item(item)); } ast::ItemKind::Enum(ref def, ref generics) => { - self.format_missing_with_indent(source!(self, item.span).lo()); self.visit_enum(item.ident, &item.vis, def, generics, item.span); - self.last_pos = source!(self, item.span).hi(); } ast::ItemKind::Mod(safety, ref mod_kind) => { self.format_missing_with_indent(source!(self, item.span).lo()); diff --git a/tests/source/crash-on-enum-generics/issue_5738.rs b/tests/source/crash-on-enum-generics/issue_5738.rs index bdba3b10944..70d211f0e81 100644 --- a/tests/source/crash-on-enum-generics/issue_5738.rs +++ b/tests/source/crash-on-enum-generics/issue_5738.rs @@ -8,6 +8,6 @@ where { V0, V1, - V2, + V2, // left unformatted since formatting where clause fails V3, } diff --git a/tests/source/crash-on-enum-generics/issue_6318.rs b/tests/source/crash-on-enum-generics/issue_6318.rs index 787225f4aae..73471f3eee1 100644 --- a/tests/source/crash-on-enum-generics/issue_6318.rs +++ b/tests/source/crash-on-enum-generics/issue_6318.rs @@ -8,6 +8,7 @@ fn my_fn() { Option<[u8; 4]>, >>::Archived, >, + // left unformatted since formatting where clause fails { } } diff --git a/tests/target/crash-on-enum-generics/issue_5738.rs b/tests/target/crash-on-enum-generics/issue_5738.rs index 4a9dd0d8a1c..70d211f0e81 100644 --- a/tests/target/crash-on-enum-generics/issue_5738.rs +++ b/tests/target/crash-on-enum-generics/issue_5738.rs @@ -8,6 +8,6 @@ where { V0, V1, - V2, + V2, // left unformatted since formatting where clause fails V3, } diff --git a/tests/target/crash-on-enum-generics/issue_6318.rs b/tests/target/crash-on-enum-generics/issue_6318.rs index 6f3b9275349..73471f3eee1 100644 --- a/tests/target/crash-on-enum-generics/issue_6318.rs +++ b/tests/target/crash-on-enum-generics/issue_6318.rs @@ -8,5 +8,7 @@ fn my_fn() { Option<[u8; 4]>, >>::Archived, >, - {} + // left unformatted since formatting where clause fails + { + } }