Skip to content

Commit df8c14c

Browse files
committed
Check all arg indexes before removing inlined format args.
1 parent 0554401 commit df8c14c

File tree

1 file changed

+15
-13
lines changed

1 file changed

+15
-13
lines changed

compiler/rustc_ast_lowering/src/format.rs

Lines changed: 15 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -103,10 +103,8 @@ fn flatten_format_args(mut fmt: Cow<'_, FormatArgs>) -> Cow<'_, FormatArgs> {
103103
///
104104
/// `format_args!("Hello, World! {}", 123)`.
105105
fn inline_literals(mut fmt: Cow<'_, FormatArgs>) -> Cow<'_, FormatArgs> {
106-
// None: Not sure yet.
107-
// Some(true): Remove, because it was inlined. (Might be set to false later if it is used in another way.)
108-
// Some(false): Do not remove, because some non-inlined placeholder uses it.
109-
let mut remove = vec![None; fmt.arguments.all_args().len()];
106+
let mut was_inlined = vec![false; fmt.arguments.all_args().len()];
107+
let mut inlined_anything = false;
110108

111109
for i in 0..fmt.template.len() {
112110
let FormatArgsPiece::Placeholder(placeholder) = &fmt.template[i] else { continue };
@@ -123,30 +121,34 @@ fn inline_literals(mut fmt: Cow<'_, FormatArgs>) -> Cow<'_, FormatArgs> {
123121
let fmt = fmt.to_mut();
124122
// Replace the placeholder with the literal.
125123
fmt.template[i] = FormatArgsPiece::Literal(s);
126-
// Only remove it wasn't set to 'do not remove'.
127-
remove[arg_index].get_or_insert(true);
128-
} else {
129-
// Never remove an argument that's used by a non-inlined placeholder,
130-
// even if this argument is inlined in another place.
131-
remove[arg_index] = Some(false);
124+
was_inlined[arg_index] = true;
125+
inlined_anything = true;
132126
}
133127
}
134128

135129
// Remove the arguments that were inlined.
136-
if remove.iter().any(|&x| x == Some(true)) {
130+
if inlined_anything {
137131
let fmt = fmt.to_mut();
132+
133+
let mut remove = was_inlined;
134+
135+
// Don't remove anything that's still used.
136+
for_all_argument_indexes(&mut fmt.template, |index| remove[*index] = false);
137+
138138
// Drop all the arguments that are marked for removal.
139139
let mut remove_it = remove.iter();
140-
fmt.arguments.all_args_mut().retain(|_| remove_it.next() != Some(&Some(true)));
140+
fmt.arguments.all_args_mut().retain(|_| remove_it.next() != Some(&true));
141+
141142
// Calculate the mapping of old to new indexes for the remaining arguments.
142143
let index_map: Vec<usize> = remove
143144
.into_iter()
144145
.scan(0, |i, remove| {
145146
let mapped = *i;
146-
*i += (remove != Some(true)) as usize;
147+
*i += !remove as usize;
147148
Some(mapped)
148149
})
149150
.collect();
151+
150152
// Correct the indexes that refer to arguments that have shifted position.
151153
for_all_argument_indexes(&mut fmt.template, |index| *index = index_map[*index]);
152154
}

0 commit comments

Comments
 (0)