Skip to content

Commit cf92f86

Browse files
committed
Auto merge of rust-lang#115129 - m-ou-se:fmt-args-new-repr, r=<try>
New fmt::Arguments representation. This changes the internal representation of `fmt::Arguments` to reduce it in size and make it possible to convert a `&'static str` to a `fmt::Arguments` without additional indirection. Part of rust-lang#99012 fmt::Arguments stores three slices: 1. The slice of string literals between the placeholders. 2. The details of the placeholders (format options, which argument to display there, etc.). 3. The arguments. 2 is omitted when it's just all arguments once in order without additional options. Before this change, fmt::Arguments stores each of these as a &[] (or Option of that), resulting in a total size of six words/pointers. However, we don't need to store the length of each of these slices separately, as we may (unsafely) assume that the indexes of the fmt::Arguments generated by format_args!() are never out of bounds, and the number of placeholders and number of strings between them must be nearly equal. This PR changes the struct to store three pointers without length, and a single 'number of parts' counter that is the sum of the number of placeholders and string pieces. Additionally, this PR adds a special case for 1 part (that is, one string piece and no placeholders) to store the string pointer directly instead of through a slice of length 1. This makes it possible for `fmt::Arguments::new_str(&'static str)` to exist, which unlike before (`new_const(&[&'static str])`) doesn't need to borrow anything other than the string itself.
2 parents e7f9f48 + 453eba0 commit cf92f86

File tree

10 files changed

+200
-145
lines changed

10 files changed

+200
-145
lines changed

Diff for: compiler/rustc_ast_lowering/src/format.rs

+20-15
Original file line numberDiff line numberDiff line change
@@ -380,7 +380,6 @@ fn expand_format_args<'hir>(
380380
}
381381
}
382382
}));
383-
let lit_pieces = ctx.expr_array_ref(fmt.span, lit_pieces);
384383

385384
// Whether we'll use the `Arguments::new_v1_formatted` form (true),
386385
// or the `Arguments::new_v1` form (false).
@@ -407,6 +406,24 @@ fn expand_format_args<'hir>(
407406
}
408407
}
409408

409+
let arguments = fmt.arguments.all_args();
410+
411+
if allow_const && lit_pieces.len() <= 1 && arguments.is_empty() && argmap.is_empty() {
412+
// Generate:
413+
// <core::fmt::Arguments>::new_str(literal)
414+
let new = ctx.arena.alloc(ctx.expr_lang_item_type_relative(
415+
macsp,
416+
hir::LangItem::FormatArguments,
417+
sym::new_str,
418+
));
419+
let args = if lit_pieces.is_empty() {
420+
ctx.arena.alloc_from_iter([ctx.expr_str(fmt.span, kw::Empty)]) // Empty string.
421+
} else {
422+
lit_pieces // Just one single literal string piece.
423+
};
424+
return hir::ExprKind::Call(new, args);
425+
}
426+
410427
let format_options = use_format_options.then(|| {
411428
// Generate:
412429
// &[format_spec_0, format_spec_1, format_spec_2]
@@ -421,20 +438,6 @@ fn expand_format_args<'hir>(
421438
ctx.expr_array_ref(macsp, ctx.arena.alloc_from_iter(elements))
422439
});
423440

424-
let arguments = fmt.arguments.all_args();
425-
426-
if allow_const && arguments.is_empty() && argmap.is_empty() {
427-
// Generate:
428-
// <core::fmt::Arguments>::new_const(lit_pieces)
429-
let new = ctx.arena.alloc(ctx.expr_lang_item_type_relative(
430-
macsp,
431-
hir::LangItem::FormatArguments,
432-
sym::new_const,
433-
));
434-
let new_args = ctx.arena.alloc_from_iter([lit_pieces]);
435-
return hir::ExprKind::Call(new, new_args);
436-
}
437-
438441
// If the args array contains exactly all the original arguments once,
439442
// in order, we can use a simple array instead of a `match` construction.
440443
// However, if there's a yield point in any argument except the first one,
@@ -555,6 +558,8 @@ fn expand_format_args<'hir>(
555558
)
556559
};
557560

561+
let lit_pieces = ctx.expr_array_ref(fmt.span, lit_pieces);
562+
558563
if let Some(format_options) = format_options {
559564
// Generate:
560565
// <core::fmt::Arguments>::new_v1_formatted(

Diff for: compiler/rustc_span/src/symbol.rs

+1
Original file line numberDiff line numberDiff line change
@@ -1030,6 +1030,7 @@ symbols! {
10301030
new_lower_hex,
10311031
new_octal,
10321032
new_pointer,
1033+
new_str,
10331034
new_unchecked,
10341035
new_upper_exp,
10351036
new_upper_hex,

0 commit comments

Comments
 (0)