diff --git a/src/lists.rs b/src/lists.rs index 9d811e5d9b5..d0038a0cafb 100644 --- a/src/lists.rs +++ b/src/lists.rs @@ -780,7 +780,7 @@ where pre_comment, pre_comment_style, // leave_last is set to true only for rewrite_items - item: if self.inner.peek().is_none() && self.leave_last { + item: if is_last && self.leave_last { Err(RewriteError::SkipFormatting) } else { (self.get_item_string)(&item) diff --git a/src/overflow.rs b/src/overflow.rs index 19f7b06f8a3..6164a35a48a 100644 --- a/src/overflow.rs +++ b/src/overflow.rs @@ -634,7 +634,7 @@ impl<'a> Context<'a> { |item| item.rewrite_result(self.context, self.nested_shape), span.lo(), span.hi(), - true, + self.items.len() > 1, ); let mut list_items: Vec<_> = items.collect(); diff --git a/src/types.rs b/src/types.rs index 76f176c97c4..684c9588460 100644 --- a/src/types.rs +++ b/src/types.rs @@ -725,13 +725,46 @@ impl Rewrite for ast::GenericParam { TypeDensity::Compressed => "=", TypeDensity::Wide => " = ", }; - param.push_str(eq_str); - let budget = shape + // Need to allow the space required for the rewrite instead of bailing + // regardless of if the line overflows. If it doesn't overflow, it's split. + // If it still overflows, then the identifier is too long, + // which the user will have to deal with. + let rewrite = def.rewrite_result( + context, + Shape::legacy(usize::MAX, shape.indent + param.len()), + )?; + let can_fit_in_line = shape .width - .checked_sub(param.len()) - .max_width_error(shape.width, self.span())?; - let rewrite = - def.rewrite_result(context, Shape::legacy(budget, shape.indent + param.len()))?; + .saturating_sub(param.len()) + .saturating_sub(eq_str.len()) + .checked_sub(rewrite.len()) + .is_some(); + if can_fit_in_line { + param.push_str(eq_str); + } else { + // Begin a new line + param.push('\n'); + for _ in 0..shape.indent.block_indent { + param.push(' '); + } + let can_fit_in_line_with_eq_str = shape + .width + .saturating_sub(eq_str.len().min(2)) + .checked_sub(rewrite.len()) + .is_some(); + if can_fit_in_line_with_eq_str { + // Fits together with eq, remove leading whitespace + param.push_str(eq_str.trim_start()); + } else { + // Split into three lines, might fit, might not, remove all whitespace, + // eq goes on its own line + param.push_str(eq_str.trim()); + param.push('\n'); + for _ in 0..shape.indent.block_indent { + param.push(' '); + } + } + } param.push_str(&rewrite); } diff --git a/tests/source/issue-6052/repro.rs b/tests/source/issue-6052/repro.rs new file mode 100644 index 00000000000..7aafe7fed1a --- /dev/null +++ b/tests/source/issue-6052/repro.rs @@ -0,0 +1,17 @@ +pub enum ManagementFrameBody< + 'a, + RateIterator = SupportedRatesTLVReadRateIterator<'a>, + ExtendedRateIterator = ExtendedSupportedRatesTLVReadRateIterator<'a>, + TLVIterator: IntoIterator> = TLVReadIterator<'a>, + ActionFramePayload = &'a [u8], +> +{ + Action(ActionFrameBody), + ActionNoAck(ActionFrameBody), + Beacon(BeaconFrameBody<'a, RateIterator, ExtendedRateIterator, TLVIterator>), + ATIM, + Unknown { + sub_type: ManagementFrameSubtype, + body: &'a [u8], + }, +} diff --git a/tests/target/issue-6052/overflows.rs b/tests/target/issue-6052/overflows.rs new file mode 100644 index 00000000000..30ace73b9de --- /dev/null +++ b/tests/target/issue-6052/overflows.rs @@ -0,0 +1,21 @@ +// Passing the max-line boundary seems to be, combined with the other stuff, causing the panic +pub enum Dummy< + SomeVeryLongStructDeclarationAsItemMakingTheLineOverflowTheRightHandSideAssignmentIsImportant + = MyDefault, +> {} + +pub enum Dummy2< + SomeVeryLongStructDeclarationAsItemMakingTheLineOverflowTheRightHandSideAssignmentIsImport + = MyDefault, +> {} + +pub enum Dummy3< + SomeVeryLongStructDeclarationAsItemMakingTheLineOverflowTheRightHandSideAssignmentIsImport + = + MyDefaultThatIsAlsoTooLongToBeFitIntoTheNextLineCausingATripleSplitThisMayBeOverdoingItOrNotIdk, +> {} + +pub enum Dummy4< + SomeVeryLongStructDeclarationAsItemMakingTheLineOverflowTheRightHandSideAssignmentIsImport + = MyDefaultThatIsAlsoTooLongToBeFitIntoTheNextLineCausingATripleSplitThisMayBeOverdoingItOrNot, +> {} diff --git a/tests/target/issue-6052/repro.rs b/tests/target/issue-6052/repro.rs new file mode 100644 index 00000000000..3ef3586e38d --- /dev/null +++ b/tests/target/issue-6052/repro.rs @@ -0,0 +1,17 @@ +pub enum ManagementFrameBody< + 'a, + RateIterator = SupportedRatesTLVReadRateIterator<'a>, + ExtendedRateIterator = ExtendedSupportedRatesTLVReadRateIterator<'a>, + TLVIterator: IntoIterator> + = TLVReadIterator<'a>, + ActionFramePayload = &'a [u8], +> { + Action(ActionFrameBody), + ActionNoAck(ActionFrameBody), + Beacon(BeaconFrameBody<'a, RateIterator, ExtendedRateIterator, TLVIterator>), + ATIM, + Unknown { + sub_type: ManagementFrameSubtype, + body: &'a [u8], + }, +}