Skip to content

Commit 69ba97f

Browse files
authored
Rollup merge of rust-lang#67784 - Mark-Simulacrum:residual-pad-integral, r=dtolnay
Reset Formatter flags on exit from pad_integral This fixes a bug where after calling pad_integral with appropriate flags, the fill and alignment flags would be set to '0' and 'Right' and left as such even after exiting pad_integral, which meant that future calls on the same Formatter would get incorrect flags reported. This is quite difficult to observe in practice, as almost all formatting implementations in practice don't call `Display::fmt` directly, but rather use `write!` or a similar macro, which means that they cannot observe the effects of the wrong flags (as `write!` creates a fresh Formatter instance). However, we include a test case. A manual check leads me to believe this is the only case where we failed to reset the flags appropriately, but I could have missed something.
2 parents 4b172cc + 73996df commit 69ba97f

File tree

2 files changed

+21
-3
lines changed

2 files changed

+21
-3
lines changed

src/libcore/fmt/mod.rs

+6-3
Original file line numberDiff line numberDiff line change
@@ -1244,12 +1244,15 @@ impl<'a> Formatter<'a> {
12441244
// The sign and prefix goes before the padding if the fill character
12451245
// is zero
12461246
Some(min) if self.sign_aware_zero_pad() => {
1247-
self.fill = '0';
1248-
self.align = rt::v1::Alignment::Right;
1247+
let old_fill = crate::mem::replace(&mut self.fill, '0');
1248+
let old_align = crate::mem::replace(&mut self.align, rt::v1::Alignment::Right);
12491249
write_prefix(self, sign, prefix)?;
12501250
let post_padding = self.padding(min - width, rt::v1::Alignment::Right)?;
12511251
self.buf.write_str(buf)?;
1252-
post_padding.write(self.buf)
1252+
post_padding.write(self.buf)?;
1253+
self.fill = old_fill;
1254+
self.align = old_align;
1255+
Ok(())
12531256
}
12541257
// Otherwise, the sign and prefix goes after the padding
12551258
Some(min) => {

src/libcore/tests/fmt/mod.rs

+15
Original file line numberDiff line numberDiff line change
@@ -28,3 +28,18 @@ fn test_estimated_capacity() {
2828
assert_eq!(format_args!("{}, hello!", "World").estimated_capacity(), 0);
2929
assert_eq!(format_args!("{}. 16-bytes piece", "World").estimated_capacity(), 32);
3030
}
31+
32+
#[test]
33+
fn pad_integral_resets() {
34+
struct Bar;
35+
36+
impl core::fmt::Display for Bar {
37+
fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
38+
"1".fmt(f)?;
39+
f.pad_integral(true, "", "5")?;
40+
"1".fmt(f)
41+
}
42+
}
43+
44+
assert_eq!(format!("{:<03}", Bar), "1 0051 ");
45+
}

0 commit comments

Comments
 (0)