Skip to content

Commit 1b3fda4

Browse files
committed
Use span of placeholders in format_args!() expansion.
1 parent 7a06007 commit 1b3fda4

File tree

1 file changed

+43
-23
lines changed

1 file changed

+43
-23
lines changed

compiler/rustc_ast_lowering/src/format.rs

+43-23
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ use super::LoweringContext;
22
use rustc_ast as ast;
33
use rustc_ast::visit::{self, Visitor};
44
use rustc_ast::*;
5-
use rustc_data_structures::fx::FxIndexSet;
5+
use rustc_data_structures::fx::FxIndexMap;
66
use rustc_hir as hir;
77
use rustc_span::{
88
sym,
@@ -238,7 +238,7 @@ fn make_count<'hir>(
238238
ctx: &mut LoweringContext<'_, 'hir>,
239239
sp: Span,
240240
count: &Option<FormatCount>,
241-
argmap: &mut FxIndexSet<(usize, ArgumentType)>,
241+
argmap: &mut FxIndexMap<(usize, ArgumentType), Option<Span>>,
242242
) -> hir::Expr<'hir> {
243243
match count {
244244
Some(FormatCount::Literal(n)) => {
@@ -252,7 +252,7 @@ fn make_count<'hir>(
252252
}
253253
Some(FormatCount::Argument(arg)) => {
254254
if let Ok(arg_index) = arg.index {
255-
let (i, _) = argmap.insert_full((arg_index, ArgumentType::Usize));
255+
let (i, _) = argmap.insert_full((arg_index, ArgumentType::Usize), arg.span);
256256
let count_param = ctx.arena.alloc(ctx.expr_lang_item_type_relative(
257257
sp,
258258
hir::LangItem::FormatCount,
@@ -291,12 +291,14 @@ fn make_format_spec<'hir>(
291291
ctx: &mut LoweringContext<'_, 'hir>,
292292
sp: Span,
293293
placeholder: &FormatPlaceholder,
294-
argmap: &mut FxIndexSet<(usize, ArgumentType)>,
294+
argmap: &mut FxIndexMap<(usize, ArgumentType), Option<Span>>,
295295
) -> hir::Expr<'hir> {
296296
let position = match placeholder.argument.index {
297297
Ok(arg_index) => {
298-
let (i, _) =
299-
argmap.insert_full((arg_index, ArgumentType::Format(placeholder.format_trait)));
298+
let (i, _) = argmap.insert_full(
299+
(arg_index, ArgumentType::Format(placeholder.format_trait)),
300+
placeholder.span,
301+
);
300302
ctx.expr_usize(sp, i)
301303
}
302304
Err(_) => ctx.expr(
@@ -386,15 +388,18 @@ fn expand_format_args<'hir>(
386388

387389
// Create a list of all _unique_ (argument, format trait) combinations.
388390
// E.g. "{0} {0:x} {0} {1}" -> [(0, Display), (0, LowerHex), (1, Display)]
389-
let mut argmap = FxIndexSet::default();
391+
let mut argmap = FxIndexMap::default();
390392
for piece in &fmt.template {
391393
let FormatArgsPiece::Placeholder(placeholder) = piece else { continue };
392394
if placeholder.format_options != Default::default() {
393395
// Can't use basic form if there's any formatting options.
394396
use_format_options = true;
395397
}
396398
if let Ok(index) = placeholder.argument.index {
397-
if !argmap.insert((index, ArgumentType::Format(placeholder.format_trait))) {
399+
if argmap
400+
.insert((index, ArgumentType::Format(placeholder.format_trait)), placeholder.span)
401+
.is_some()
402+
{
398403
// Duplicate (argument, format trait) combination,
399404
// which we'll only put once in the args array.
400405
use_format_options = true;
@@ -438,7 +443,7 @@ fn expand_format_args<'hir>(
438443
// This is an optimization, speeding up compilation about 1-2% in some cases.
439444
// See https://github.com/rust-lang/rust/pull/106770#issuecomment-1380790609
440445
let use_simple_array = argmap.len() == arguments.len()
441-
&& argmap.iter().enumerate().all(|(i, &(j, _))| i == j)
446+
&& argmap.iter().enumerate().all(|(i, (&(j, _), _))| i == j)
442447
&& arguments.iter().skip(1).all(|arg| !may_contain_yield_point(&arg.expr));
443448

444449
let args = if use_simple_array {
@@ -452,14 +457,19 @@ fn expand_format_args<'hir>(
452457
let elements: Vec<_> = arguments
453458
.iter()
454459
.zip(argmap)
455-
.map(|(arg, (_, ty))| {
456-
let sp = arg.expr.span.with_ctxt(macsp.ctxt());
460+
.map(|(arg, ((_, ty), placeholder_span))| {
461+
let placeholder_span =
462+
placeholder_span.unwrap_or(arg.expr.span).with_ctxt(macsp.ctxt());
463+
let arg_span = match arg.kind {
464+
FormatArgumentKind::Captured(_) => placeholder_span,
465+
_ => arg.expr.span.with_ctxt(macsp.ctxt()),
466+
};
457467
let arg = ctx.lower_expr(&arg.expr);
458468
let ref_arg = ctx.arena.alloc(ctx.expr(
459-
sp,
469+
arg_span,
460470
hir::ExprKind::AddrOf(hir::BorrowKind::Ref, hir::Mutability::Not, arg),
461471
));
462-
make_argument(ctx, sp, ref_arg, ty)
472+
make_argument(ctx, placeholder_span, ref_arg, ty)
463473
})
464474
.collect();
465475
ctx.expr_array_ref(macsp, ctx.arena.alloc_from_iter(elements))
@@ -475,16 +485,26 @@ fn expand_format_args<'hir>(
475485
// }
476486
let args_ident = Ident::new(sym::args, macsp);
477487
let (args_pat, args_hir_id) = ctx.pat_ident(macsp, args_ident);
478-
let args = ctx.arena.alloc_from_iter(argmap.iter().map(|&(arg_index, ty)| {
479-
let arg = &arguments[arg_index];
480-
let sp = arg.expr.span.with_ctxt(macsp.ctxt());
481-
let args_ident_expr = ctx.expr_ident(macsp, args_ident, args_hir_id);
482-
let arg = ctx.arena.alloc(ctx.expr(
483-
sp,
484-
hir::ExprKind::Field(args_ident_expr, Ident::new(sym::integer(arg_index), macsp)),
485-
));
486-
make_argument(ctx, sp, arg, ty)
487-
}));
488+
let args = ctx.arena.alloc_from_iter(argmap.iter().map(
489+
|(&(arg_index, ty), &placeholder_span)| {
490+
let arg = &arguments[arg_index];
491+
let placeholder_span =
492+
placeholder_span.unwrap_or(arg.expr.span).with_ctxt(macsp.ctxt());
493+
let arg_span = match arg.kind {
494+
FormatArgumentKind::Captured(_) => placeholder_span,
495+
_ => arg.expr.span.with_ctxt(macsp.ctxt()),
496+
};
497+
let args_ident_expr = ctx.expr_ident(macsp, args_ident, args_hir_id);
498+
let arg = ctx.arena.alloc(ctx.expr(
499+
arg_span,
500+
hir::ExprKind::Field(
501+
args_ident_expr,
502+
Ident::new(sym::integer(arg_index), macsp),
503+
),
504+
));
505+
make_argument(ctx, placeholder_span, arg, ty)
506+
},
507+
));
488508
let elements: Vec<_> = arguments
489509
.iter()
490510
.map(|arg| {

0 commit comments

Comments
 (0)