Skip to content

printf: fix formatting for zero value when precision is zero #8351

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 1 commit into
base: main
Choose a base branch
from

Conversation

nickorlow
Copy link

Fixes issue #7509

According to the C/C++ reference, "if both the value and precision are 0, the conversion results in no characters. "

This PR also includes code to handle the following exceptions:

  • If width isn't zero, the result should still be padded, but empty
  • If the alternate octal output is selected, a 0 should be outputted
  • The positive sign should be printed if specified

@hz2
Copy link
Contributor

hz2 commented Jul 18, 2025

For clippy related issues, it may be helpful to run locally:

cargo clippy --all-targets --all-features -- -D warnings

@nickorlow
Copy link
Author

Ah, forgot to check lint. Thank you.

Copy link

GNU testsuite comparison:

GNU test failed: tests/printf/printf. tests/printf/printf is passing on 'main'. Maybe you have to rebase?
Skip an intermittent issue tests/misc/stdbuf (fails in this run but passes in the 'main' branch)
Skip an intermittent issue tests/misc/tee (fails in this run but passes in the 'main' branch)
Skip an intermittent issue tests/timeout/timeout (fails in this run but passes in the 'main' branch)

@nickorlow
Copy link
Author

nickorlow commented Jul 18, 2025

Will look into failing tests + other lints I didn't pick up earlier

@nickorlow
Copy link
Author

Reran lint and addressed issues there. The failing GNU test case was because I didn't switch the precision parser to return a None for a negative value instead of Some(0usize).

Should be good to run workflow again.

Copy link

GNU testsuite comparison:

Skip an intermittent issue tests/misc/tee (fails in this run but passes in the 'main' branch)
Skip an intermittent issue tests/timeout/timeout (fails in this run but passes in the 'main' branch)

@nickorlow
Copy link
Author

Updated the one test case. Not sure there's much I can do about the other one that's complaining about linting issues in the zerocopy crate.

Copy link

GNU testsuite comparison:

Skipping an intermittent issue tests/misc/tee (passes in this run but fails in the 'main' branch)
Skipping an intermittent issue tests/timeout/timeout (passes in this run but fails in the 'main' branch)
Congrats! The gnu test tests/du/files0-from is no longer failing!

Copy link

GNU testsuite comparison:

Skip an intermittent issue tests/timeout/timeout (fails in this run but passes in the 'main' branch)

@RenjiSann
Copy link
Collaborator

Can you squash your commits in a single one for better readability in the main branch ?
Thank you !

@nickorlow
Copy link
Author

@RenjiSann Done! Sorry it took so long to get back on that.

Copy link

GNU testsuite comparison:

Skipping an intermittent issue tests/misc/tee (passes in this run but fails in the 'main' branch)

@nickorlow nickorlow reopened this Aug 16, 2025
@nickorlow
Copy link
Author

Just rebased on top of main.

Copy link

GNU testsuite comparison:

Skipping an intermittent issue tests/misc/tee (passes in this run but fails in the 'main' branch)

@nickorlow nickorlow requested a review from hz2 August 16, 2025 17:18
@@ -1218,7 +1269,7 @@ mod test {
}

#[test]
#[ignore = "Need issues #7509 and #7510 to be fixed"]
#[ignore = "Needs issue #7510 to be fixed"]
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit: noticed #7510 was closed, do we think we can remove this ignore now?

s = format!("{prefix}{s:0>precision$}");
}
} else {
s = format!("{prefix}{s:0>width$}", width = 0);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Using width = 0 here seems unnecessary since you're not actually using width
padding when precision is None. Could be simplified to just s = format!("{prefix}{s}");
no ?

_ => "",
};

s = format!("{prefix}{s:0>width$}", width = self.precision);
if let Some(precision) = self.precision {
Copy link
Contributor

@sylvestre sylvestre Aug 18, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

what about something like ?


  s = match (self.precision, x) {
      (Some(0), 0) => match self.variant {
          UnsignedIntVariant::Octal(Prefix::Yes) => String::from("0"),
          _ => String::new(),
      },
      (Some(p), _) => format!("{prefix}{s:0>p$}"),
      (None, _) => format!("{prefix}{s}"),
  };

Comment on lines +85 to +92
let s = if let Some(precision) = self.precision {
if precision > 0 {
format!("{abs:0>precision$}")
} else if abs == 0 {
String::from("")
} else {
abs.to_string()
}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Same

  let s = match (self.precision, abs) {
      (Some(0), 0) => String::new(),
      (Some(p), _) if p > 0 => format!("{abs:0>p$}"),
      _ => abs.to_string(),
  };

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants