mirror of
https://github.com/rust-lang/rust.git
synced 2025-02-16 08:53:35 +00:00
Avoid panic_bounds_check in fmt::write.
Writing any fmt::Arguments would trigger the inclusion of usize formatting and padding code in the resulting binary, because indexing used in fmt::write would generate code using panic_bounds_check, which prints the index and length. These bounds checks are not necessary, as fmt::Arguments never contains any out-of-bounds indexes. This change replaces them with unsafe get_unchecked, to reduce the amount of generated code, which is especially important for embedded targets.
This commit is contained in:
parent
ad268bd638
commit
d80f127a75
@ -1082,7 +1082,9 @@ pub fn write(output: &mut dyn Write, args: Arguments<'_>) -> Result {
|
||||
// a string piece.
|
||||
for (arg, piece) in fmt.iter().zip(args.pieces.iter()) {
|
||||
formatter.buf.write_str(*piece)?;
|
||||
run(&mut formatter, arg, &args.args)?;
|
||||
// SAFETY: arg and args.args come from the same Arguments,
|
||||
// which guarantees the indexes are always within bounds.
|
||||
unsafe { run(&mut formatter, arg, &args.args) }?;
|
||||
idx += 1;
|
||||
}
|
||||
}
|
||||
@ -1096,25 +1098,36 @@ pub fn write(output: &mut dyn Write, args: Arguments<'_>) -> Result {
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn run(fmt: &mut Formatter<'_>, arg: &rt::v1::Argument, args: &[ArgumentV1<'_>]) -> Result {
|
||||
unsafe fn run(fmt: &mut Formatter<'_>, arg: &rt::v1::Argument, args: &[ArgumentV1<'_>]) -> Result {
|
||||
fmt.fill = arg.format.fill;
|
||||
fmt.align = arg.format.align;
|
||||
fmt.flags = arg.format.flags;
|
||||
fmt.width = getcount(args, &arg.format.width);
|
||||
fmt.precision = getcount(args, &arg.format.precision);
|
||||
// SAFETY: arg and args come from the same Arguments,
|
||||
// which guarantees the indexes are always within bounds.
|
||||
unsafe {
|
||||
fmt.width = getcount(args, &arg.format.width);
|
||||
fmt.precision = getcount(args, &arg.format.precision);
|
||||
}
|
||||
|
||||
// Extract the correct argument
|
||||
let value = args[arg.position];
|
||||
|
||||
// SAFETY: arg and args come from the same Arguments,
|
||||
// which guarantees its index is always within bounds.
|
||||
let value = unsafe { args.get_unchecked(arg.position) };
|
||||
|
||||
// Then actually do some printing
|
||||
(value.formatter)(value.value, fmt)
|
||||
}
|
||||
|
||||
fn getcount(args: &[ArgumentV1<'_>], cnt: &rt::v1::Count) -> Option<usize> {
|
||||
unsafe fn getcount(args: &[ArgumentV1<'_>], cnt: &rt::v1::Count) -> Option<usize> {
|
||||
match *cnt {
|
||||
rt::v1::Count::Is(n) => Some(n),
|
||||
rt::v1::Count::Implied => None,
|
||||
rt::v1::Count::Param(i) => args[i].as_usize(),
|
||||
rt::v1::Count::Param(i) => {
|
||||
// SAFETY: cnt and args come from the same Arguments,
|
||||
// which guarantees this index is always within bounds.
|
||||
unsafe { args.get_unchecked(i).as_usize() }
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user