mirror of
https://github.com/rust-lang/rust.git
synced 2025-06-05 19:58:32 +00:00
Prefer new_v1_formatted instead of new_v1 with duplicates.
This commit is contained in:
parent
00074926bb
commit
ae238efe91
@ -164,18 +164,32 @@ pub fn expand_parsed_format_args(ecx: &mut ExtCtxt<'_>, fmt: FormatArgs) -> P<as
|
|||||||
.collect(),
|
.collect(),
|
||||||
);
|
);
|
||||||
|
|
||||||
let has_any_format_options = fmt.template.iter().any(|piece| {
|
// Whether we'll use the `Arguments::new_v1_formatted` form (true),
|
||||||
let FormatArgsPiece::Placeholder(placeholder) = piece else { return false };
|
// or the `Arguments::new_v1` form (false).
|
||||||
placeholder.format_options != Default::default()
|
let mut use_format_options = false;
|
||||||
});
|
|
||||||
|
|
||||||
let (args, format_options) = if has_any_format_options {
|
// Create a list of all _unique_ (argument, format trait) combinations.
|
||||||
// Create a list of all _unique_ (argument, format trait) combinations.
|
// E.g. "{0} {0:x} {0} {1}" -> [(0, Display), (0, LowerHex), (1, Display)]
|
||||||
// E.g. "{0} {0:x} {0} {1}" -> [(0, Display), (0, LowerHex), (1, Display)]
|
let mut argmap = FxIndexSet::default();
|
||||||
let mut argmap = FxIndexSet::default();
|
for piece in &fmt.template {
|
||||||
|
let FormatArgsPiece::Placeholder(placeholder) = piece else { continue };
|
||||||
|
if placeholder.format_options != Default::default() {
|
||||||
|
// Can't use basic form if there's any formatting options.
|
||||||
|
use_format_options = true;
|
||||||
|
}
|
||||||
|
if let Ok(index) = placeholder.argument.index {
|
||||||
|
if !argmap.insert((index, ArgumentType::Format(placeholder.format_trait))) {
|
||||||
|
// Duplicate (argument, format trait) combination,
|
||||||
|
// which we'll only put once in the args array.
|
||||||
|
use_format_options = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
let format_options = use_format_options.then(|| {
|
||||||
// Generate:
|
// Generate:
|
||||||
// &[format_spec_0, format_spec_1, format_spec_2]
|
// &[format_spec_0, format_spec_1, format_spec_2]
|
||||||
let format_options = ecx.expr_array_ref(
|
ecx.expr_array_ref(
|
||||||
macsp,
|
macsp,
|
||||||
fmt.template
|
fmt.template
|
||||||
.iter()
|
.iter()
|
||||||
@ -184,34 +198,18 @@ pub fn expand_parsed_format_args(ecx: &mut ExtCtxt<'_>, fmt: FormatArgs) -> P<as
|
|||||||
Some(make_format_spec(ecx, macsp, placeholder, &mut argmap))
|
Some(make_format_spec(ecx, macsp, placeholder, &mut argmap))
|
||||||
})
|
})
|
||||||
.collect(),
|
.collect(),
|
||||||
);
|
)
|
||||||
(Vec::from_iter(argmap), Some(format_options))
|
});
|
||||||
} else {
|
|
||||||
// Create a list of all (argument, format trait) pairs, one for each placeholder.
|
|
||||||
// E.g. "{0} {0:x} {0} {1}" -> [(0, Display), (0, LowerHex), (0, Display), (1, Display)]
|
|
||||||
let args = fmt
|
|
||||||
.template
|
|
||||||
.iter()
|
|
||||||
.filter_map(|piece| {
|
|
||||||
let FormatArgsPiece::Placeholder(placeholder) = piece else { return None };
|
|
||||||
Some((
|
|
||||||
placeholder.argument.index.ok()?,
|
|
||||||
ArgumentType::Format(placeholder.format_trait),
|
|
||||||
))
|
|
||||||
})
|
|
||||||
.collect();
|
|
||||||
(args, None)
|
|
||||||
};
|
|
||||||
|
|
||||||
// If the args array contains exactly all the original arguments once,
|
// If the args array contains exactly all the original arguments once,
|
||||||
// in order, we can use a simple array instead of a `match` construction.
|
// 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,
|
// However, if there's a yield point in any argument except the first one,
|
||||||
// we don't do this, because an ArgumentV1 cannot be kept across yield points.
|
// we don't do this, because an ArgumentV1 cannot be kept across yield points.
|
||||||
let use_simple_array = args.len() == fmt.arguments.len()
|
let use_simple_array = argmap.len() == fmt.arguments.len()
|
||||||
&& args.iter().enumerate().all(|(i, &(j, _))| i == j)
|
&& argmap.iter().enumerate().all(|(i, &(j, _))| i == j)
|
||||||
&& fmt.arguments.iter().skip(1).all(|(arg, _)| !may_contain_yield_point(arg));
|
&& fmt.arguments.iter().skip(1).all(|(arg, _)| !may_contain_yield_point(arg));
|
||||||
|
|
||||||
let args_expr = if use_simple_array {
|
let args = if use_simple_array {
|
||||||
// Generate:
|
// Generate:
|
||||||
// &[
|
// &[
|
||||||
// ::core::fmt::ArgumentV1::new_display(&arg0),
|
// ::core::fmt::ArgumentV1::new_display(&arg0),
|
||||||
@ -222,7 +220,7 @@ pub fn expand_parsed_format_args(ecx: &mut ExtCtxt<'_>, fmt: FormatArgs) -> P<as
|
|||||||
macsp,
|
macsp,
|
||||||
fmt.arguments
|
fmt.arguments
|
||||||
.into_iter()
|
.into_iter()
|
||||||
.zip(args)
|
.zip(argmap)
|
||||||
.map(|((arg, _), (_, ty))| {
|
.map(|((arg, _), (_, ty))| {
|
||||||
let sp = arg.span.with_ctxt(macsp.ctxt());
|
let sp = arg.span.with_ctxt(macsp.ctxt());
|
||||||
make_argument(ecx, sp, ecx.expr_addr_of(sp, arg), ty)
|
make_argument(ecx, sp, ecx.expr_addr_of(sp, arg), ty)
|
||||||
@ -239,7 +237,7 @@ pub fn expand_parsed_format_args(ecx: &mut ExtCtxt<'_>, fmt: FormatArgs) -> P<as
|
|||||||
// ]
|
// ]
|
||||||
// }
|
// }
|
||||||
let args_ident = Ident::new(sym::args, macsp);
|
let args_ident = Ident::new(sym::args, macsp);
|
||||||
let args = args
|
let args = argmap
|
||||||
.iter()
|
.iter()
|
||||||
.map(|&(arg_index, ty)| {
|
.map(|&(arg_index, ty)| {
|
||||||
if let Some((arg, _)) = fmt.arguments.get(arg_index) {
|
if let Some((arg, _)) = fmt.arguments.get(arg_index) {
|
||||||
@ -270,8 +268,7 @@ pub fn expand_parsed_format_args(ecx: &mut ExtCtxt<'_>, fmt: FormatArgs) -> P<as
|
|||||||
.map(|(arg, _)| ecx.expr_addr_of(arg.span.with_ctxt(macsp.ctxt()), arg))
|
.map(|(arg, _)| ecx.expr_addr_of(arg.span.with_ctxt(macsp.ctxt()), arg))
|
||||||
.collect(),
|
.collect(),
|
||||||
),
|
),
|
||||||
[ecx.arm(macsp, ecx.pat_ident(macsp, args_ident), ecx.expr_array(macsp, args))]
|
vec![ecx.arm(macsp, ecx.pat_ident(macsp, args_ident), ecx.expr_array(macsp, args))],
|
||||||
.into(),
|
|
||||||
),
|
),
|
||||||
)
|
)
|
||||||
};
|
};
|
||||||
@ -289,7 +286,7 @@ pub fn expand_parsed_format_args(ecx: &mut ExtCtxt<'_>, fmt: FormatArgs) -> P<as
|
|||||||
ecx.std_path(&[sym::fmt, sym::Arguments, sym::new_v1_formatted]),
|
ecx.std_path(&[sym::fmt, sym::Arguments, sym::new_v1_formatted]),
|
||||||
vec![
|
vec![
|
||||||
lit_pieces,
|
lit_pieces,
|
||||||
args_expr,
|
args,
|
||||||
format_options,
|
format_options,
|
||||||
ecx.expr_block(P(ast::Block {
|
ecx.expr_block(P(ast::Block {
|
||||||
stmts: vec![ecx.stmt_expr(ecx.expr_call_global(
|
stmts: vec![ecx.stmt_expr(ecx.expr_call_global(
|
||||||
@ -314,7 +311,7 @@ pub fn expand_parsed_format_args(ecx: &mut ExtCtxt<'_>, fmt: FormatArgs) -> P<as
|
|||||||
ecx.expr_call_global(
|
ecx.expr_call_global(
|
||||||
macsp,
|
macsp,
|
||||||
ecx.std_path(&[sym::fmt, sym::Arguments, sym::new_v1]),
|
ecx.std_path(&[sym::fmt, sym::Arguments, sym::new_v1]),
|
||||||
vec![lit_pieces, args_expr],
|
vec![lit_pieces, args],
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user