Skip to content

Commit

Permalink
Auto merge of #115129 - m-ou-se:fmt-args-new-repr, r=<try>
Browse files Browse the repository at this point in the history
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 #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.
  • Loading branch information
bors committed Sep 15, 2023
2 parents e7f9f48 + 453eba0 commit cf92f86
Show file tree
Hide file tree
Showing 10 changed files with 200 additions and 145 deletions.
35 changes: 20 additions & 15 deletions compiler/rustc_ast_lowering/src/format.rs
Original file line number Diff line number Diff line change
Expand Up @@ -380,7 +380,6 @@ fn expand_format_args<'hir>(
}
}
}));
let lit_pieces = ctx.expr_array_ref(fmt.span, lit_pieces);

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

let arguments = fmt.arguments.all_args();

if allow_const && lit_pieces.len() <= 1 && arguments.is_empty() && argmap.is_empty() {
// Generate:
// <core::fmt::Arguments>::new_str(literal)
let new = ctx.arena.alloc(ctx.expr_lang_item_type_relative(
macsp,
hir::LangItem::FormatArguments,
sym::new_str,
));
let args = if lit_pieces.is_empty() {
ctx.arena.alloc_from_iter([ctx.expr_str(fmt.span, kw::Empty)]) // Empty string.
} else {
lit_pieces // Just one single literal string piece.
};
return hir::ExprKind::Call(new, args);
}

let format_options = use_format_options.then(|| {
// Generate:
// &[format_spec_0, format_spec_1, format_spec_2]
Expand All @@ -421,20 +438,6 @@ fn expand_format_args<'hir>(
ctx.expr_array_ref(macsp, ctx.arena.alloc_from_iter(elements))
});

let arguments = fmt.arguments.all_args();

if allow_const && arguments.is_empty() && argmap.is_empty() {
// Generate:
// <core::fmt::Arguments>::new_const(lit_pieces)
let new = ctx.arena.alloc(ctx.expr_lang_item_type_relative(
macsp,
hir::LangItem::FormatArguments,
sym::new_const,
));
let new_args = ctx.arena.alloc_from_iter([lit_pieces]);
return hir::ExprKind::Call(new, new_args);
}

// If the args array contains exactly all the original arguments once,
// in order, we can use a simple array instead of a `match` construction.
// However, if there's a yield point in any argument except the first one,
Expand Down Expand Up @@ -555,6 +558,8 @@ fn expand_format_args<'hir>(
)
};

let lit_pieces = ctx.expr_array_ref(fmt.span, lit_pieces);

if let Some(format_options) = format_options {
// Generate:
// <core::fmt::Arguments>::new_v1_formatted(
Expand Down
1 change: 1 addition & 0 deletions compiler/rustc_span/src/symbol.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1030,6 +1030,7 @@ symbols! {
new_lower_hex,
new_octal,
new_pointer,
new_str,
new_unchecked,
new_upper_exp,
new_upper_hex,
Expand Down
Loading

0 comments on commit cf92f86

Please sign in to comment.