Auto merge of #100996 - m-ou-se:format-args-2, r=estebank
Rewrite and refactor format_args!() builtin macro.
This is a near complete rewrite of `compiler/rustc_builtin_macros/src/format.rs`.
This gets rid of the massive unmaintanable [`Context` struct](76531befc4/compiler/rustc_builtin_macros/src/format.rs (L176-L263)
), and splits the macro expansion into three parts:
1. First, `parse_args` will parse the `(literal, arg, arg, name=arg, name=arg)` syntax, but doesn't parse the template (the literal) itself.
2. Second, `make_format_args` will parse the template, the format options, resolve argument references, produce diagnostics, and turn the whole thing into a `FormatArgs` structure.
3. Finally, `expand_parsed_format_args` will turn that `FormatArgs` structure into the expression that the macro expands to.
In other words, the `format_args` builtin macro used to be a hard-to-maintain 'single pass compiler', which I've split into a three phase compiler with a parser/tokenizer (step 1), semantic analysis (step 2), and backend (step 3). (It's compilers all the way down. ^^)
This can serve as a great starting point for https://github.com/rust-lang/rust/issues/99012, which will only need to change the implementation of 3, while leaving step 1 and 2 unchanged.
It also makes https://github.com/rust-lang/compiler-team/issues/541 easier, which could then upgrade the new `FormatArgs` struct to an `ast` node and remove step 3, moving that step to later in the compilation process.
It also fixes a few diagnostics bugs.
This also [significantly reduces](https://gist.github.com/m-ou-se/b67b2d54172c4837a5ab1b26fa3e5284) the amount of generated code for cases with arguments in non-default order without formatting options, like `"{1} {0}"` or `"{a} {}"`, etc.
This commit is contained in:
commit
d6734be398
16 changed files with 1533 additions and 1624 deletions
File diff suppressed because it is too large
Load diff
240
compiler/rustc_builtin_macros/src/format/ast.rs
Normal file
240
compiler/rustc_builtin_macros/src/format/ast.rs
Normal file
|
@ -0,0 +1,240 @@
|
|||
use rustc_ast::ptr::P;
|
||||
use rustc_ast::Expr;
|
||||
use rustc_data_structures::fx::FxHashMap;
|
||||
use rustc_span::symbol::{Ident, Symbol};
|
||||
use rustc_span::Span;
|
||||
|
||||
// Definitions:
|
||||
//
|
||||
// format_args!("hello {abc:.xyz$}!!", abc="world");
|
||||
// └──────────────────────────────────────────────┘
|
||||
// FormatArgs
|
||||
//
|
||||
// format_args!("hello {abc:.xyz$}!!", abc="world");
|
||||
// └─────────┘
|
||||
// argument
|
||||
//
|
||||
// format_args!("hello {abc:.xyz$}!!", abc="world");
|
||||
// └───────────────────┘
|
||||
// template
|
||||
//
|
||||
// format_args!("hello {abc:.xyz$}!!", abc="world");
|
||||
// └────┘└─────────┘└┘
|
||||
// pieces
|
||||
//
|
||||
// format_args!("hello {abc:.xyz$}!!", abc="world");
|
||||
// └────┘ └┘
|
||||
// literal pieces
|
||||
//
|
||||
// format_args!("hello {abc:.xyz$}!!", abc="world");
|
||||
// └─────────┘
|
||||
// placeholder
|
||||
//
|
||||
// format_args!("hello {abc:.xyz$}!!", abc="world");
|
||||
// └─┘ └─┘
|
||||
// positions (could be names, numbers, empty, or `*`)
|
||||
|
||||
/// (Parsed) format args.
|
||||
///
|
||||
/// Basically the "AST" for a complete `format_args!()`.
|
||||
///
|
||||
/// E.g., `format_args!("hello {name}");`.
|
||||
#[derive(Clone, Debug)]
|
||||
pub struct FormatArgs {
|
||||
pub span: Span,
|
||||
pub template: Vec<FormatArgsPiece>,
|
||||
pub arguments: FormatArguments,
|
||||
}
|
||||
|
||||
/// A piece of a format template string.
|
||||
///
|
||||
/// E.g. "hello" or "{name}".
|
||||
#[derive(Clone, Debug)]
|
||||
pub enum FormatArgsPiece {
|
||||
Literal(Symbol),
|
||||
Placeholder(FormatPlaceholder),
|
||||
}
|
||||
|
||||
/// The arguments to format_args!().
|
||||
///
|
||||
/// E.g. `1, 2, name="ferris", n=3`,
|
||||
/// but also implicit captured arguments like `x` in `format_args!("{x}")`.
|
||||
#[derive(Clone, Debug)]
|
||||
pub struct FormatArguments {
|
||||
arguments: Vec<FormatArgument>,
|
||||
num_unnamed_args: usize,
|
||||
num_explicit_args: usize,
|
||||
names: FxHashMap<Symbol, usize>,
|
||||
}
|
||||
|
||||
impl FormatArguments {
|
||||
pub fn new() -> Self {
|
||||
Self {
|
||||
arguments: Vec::new(),
|
||||
names: FxHashMap::default(),
|
||||
num_unnamed_args: 0,
|
||||
num_explicit_args: 0,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn add(&mut self, arg: FormatArgument) -> usize {
|
||||
let index = self.arguments.len();
|
||||
if let Some(name) = arg.kind.ident() {
|
||||
self.names.insert(name.name, index);
|
||||
} else if self.names.is_empty() {
|
||||
// Only count the unnamed args before the first named arg.
|
||||
// (Any later ones are errors.)
|
||||
self.num_unnamed_args += 1;
|
||||
}
|
||||
if !matches!(arg.kind, FormatArgumentKind::Captured(..)) {
|
||||
// This is an explicit argument.
|
||||
// Make sure that all arguments so far are explcit.
|
||||
assert_eq!(
|
||||
self.num_explicit_args,
|
||||
self.arguments.len(),
|
||||
"captured arguments must be added last"
|
||||
);
|
||||
self.num_explicit_args += 1;
|
||||
}
|
||||
self.arguments.push(arg);
|
||||
index
|
||||
}
|
||||
|
||||
pub fn by_name(&self, name: Symbol) -> Option<(usize, &FormatArgument)> {
|
||||
let i = *self.names.get(&name)?;
|
||||
Some((i, &self.arguments[i]))
|
||||
}
|
||||
|
||||
pub fn by_index(&self, i: usize) -> Option<&FormatArgument> {
|
||||
(i < self.num_explicit_args).then(|| &self.arguments[i])
|
||||
}
|
||||
|
||||
pub fn unnamed_args(&self) -> &[FormatArgument] {
|
||||
&self.arguments[..self.num_unnamed_args]
|
||||
}
|
||||
|
||||
pub fn named_args(&self) -> &[FormatArgument] {
|
||||
&self.arguments[self.num_unnamed_args..self.num_explicit_args]
|
||||
}
|
||||
|
||||
pub fn explicit_args(&self) -> &[FormatArgument] {
|
||||
&self.arguments[..self.num_explicit_args]
|
||||
}
|
||||
|
||||
pub fn into_vec(self) -> Vec<FormatArgument> {
|
||||
self.arguments
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug)]
|
||||
pub struct FormatArgument {
|
||||
pub kind: FormatArgumentKind,
|
||||
pub expr: P<Expr>,
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug)]
|
||||
pub enum FormatArgumentKind {
|
||||
/// `format_args(…, arg)`
|
||||
Normal,
|
||||
/// `format_args(…, arg = 1)`
|
||||
Named(Ident),
|
||||
/// `format_args("… {arg} …")`
|
||||
Captured(Ident),
|
||||
}
|
||||
|
||||
impl FormatArgumentKind {
|
||||
pub fn ident(&self) -> Option<Ident> {
|
||||
match self {
|
||||
&Self::Normal => None,
|
||||
&Self::Named(id) => Some(id),
|
||||
&Self::Captured(id) => Some(id),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, PartialEq, Eq)]
|
||||
pub struct FormatPlaceholder {
|
||||
/// Index into [`FormatArgs::arguments`].
|
||||
pub argument: FormatArgPosition,
|
||||
/// The span inside the format string for the full `{…}` placeholder.
|
||||
pub span: Option<Span>,
|
||||
/// `{}`, `{:?}`, or `{:x}`, etc.
|
||||
pub format_trait: FormatTrait,
|
||||
/// `{}` or `{:.5}` or `{:-^20}`, etc.
|
||||
pub format_options: FormatOptions,
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, PartialEq, Eq)]
|
||||
pub struct FormatArgPosition {
|
||||
/// Which argument this position refers to (Ok),
|
||||
/// or would've referred to if it existed (Err).
|
||||
pub index: Result<usize, usize>,
|
||||
/// What kind of position this is. See [`FormatArgPositionKind`].
|
||||
pub kind: FormatArgPositionKind,
|
||||
/// The span of the name or number.
|
||||
pub span: Option<Span>,
|
||||
}
|
||||
|
||||
#[derive(Copy, Clone, Debug, PartialEq, Eq)]
|
||||
pub enum FormatArgPositionKind {
|
||||
/// `{}` or `{:.*}`
|
||||
Implicit,
|
||||
/// `{1}` or `{:1$}` or `{:.1$}`
|
||||
Number,
|
||||
/// `{a}` or `{:a$}` or `{:.a$}`
|
||||
Named,
|
||||
}
|
||||
|
||||
#[derive(Copy, Clone, Debug, Hash, PartialEq, Eq)]
|
||||
pub enum FormatTrait {
|
||||
/// `{}`
|
||||
Display,
|
||||
/// `{:?}`
|
||||
Debug,
|
||||
/// `{:e}`
|
||||
LowerExp,
|
||||
/// `{:E}`
|
||||
UpperExp,
|
||||
/// `{:o}`
|
||||
Octal,
|
||||
/// `{:p}`
|
||||
Pointer,
|
||||
/// `{:b}`
|
||||
Binary,
|
||||
/// `{:x}`
|
||||
LowerHex,
|
||||
/// `{:X}`
|
||||
UpperHex,
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, Default, PartialEq, Eq)]
|
||||
pub struct FormatOptions {
|
||||
/// The width. E.g. `{:5}` or `{:width$}`.
|
||||
pub width: Option<FormatCount>,
|
||||
/// The precision. E.g. `{:.5}` or `{:.precision$}`.
|
||||
pub precision: Option<FormatCount>,
|
||||
/// The alignment. E.g. `{:>}` or `{:<}` or `{:^}`.
|
||||
pub alignment: Option<FormatAlignment>,
|
||||
/// The fill character. E.g. the `.` in `{:.>10}`.
|
||||
pub fill: Option<char>,
|
||||
/// The `+`, `-`, `0`, `#`, `x?` and `X?` flags.
|
||||
pub flags: u32,
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, PartialEq, Eq)]
|
||||
pub enum FormatAlignment {
|
||||
/// `{:<}`
|
||||
Left,
|
||||
/// `{:>}`
|
||||
Right,
|
||||
/// `{:^}`
|
||||
Center,
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, PartialEq, Eq)]
|
||||
pub enum FormatCount {
|
||||
/// `{:5}` or `{:.5}`
|
||||
Literal(usize),
|
||||
/// `{:.*}`, `{:.5$}`, or `{:a$}`, etc.
|
||||
Argument(FormatArgPosition),
|
||||
}
|
353
compiler/rustc_builtin_macros/src/format/expand.rs
Normal file
353
compiler/rustc_builtin_macros/src/format/expand.rs
Normal file
|
@ -0,0 +1,353 @@
|
|||
use super::*;
|
||||
use rustc_ast as ast;
|
||||
use rustc_ast::visit::{self, Visitor};
|
||||
use rustc_ast::{BlockCheckMode, UnsafeSource};
|
||||
use rustc_data_structures::fx::FxIndexSet;
|
||||
use rustc_span::{sym, symbol::kw};
|
||||
|
||||
#[derive(Copy, Clone, Debug, Hash, PartialEq, Eq)]
|
||||
enum ArgumentType {
|
||||
Format(FormatTrait),
|
||||
Usize,
|
||||
}
|
||||
|
||||
fn make_argument(ecx: &ExtCtxt<'_>, sp: Span, arg: P<ast::Expr>, ty: ArgumentType) -> P<ast::Expr> {
|
||||
// Generate:
|
||||
// ::core::fmt::ArgumentV1::new_…(arg)
|
||||
use ArgumentType::*;
|
||||
use FormatTrait::*;
|
||||
ecx.expr_call_global(
|
||||
sp,
|
||||
ecx.std_path(&[
|
||||
sym::fmt,
|
||||
sym::ArgumentV1,
|
||||
match ty {
|
||||
Format(Display) => sym::new_display,
|
||||
Format(Debug) => sym::new_debug,
|
||||
Format(LowerExp) => sym::new_lower_exp,
|
||||
Format(UpperExp) => sym::new_upper_exp,
|
||||
Format(Octal) => sym::new_octal,
|
||||
Format(Pointer) => sym::new_pointer,
|
||||
Format(Binary) => sym::new_binary,
|
||||
Format(LowerHex) => sym::new_lower_hex,
|
||||
Format(UpperHex) => sym::new_upper_hex,
|
||||
Usize => sym::from_usize,
|
||||
},
|
||||
]),
|
||||
vec![arg],
|
||||
)
|
||||
}
|
||||
|
||||
fn make_count(
|
||||
ecx: &ExtCtxt<'_>,
|
||||
sp: Span,
|
||||
count: &Option<FormatCount>,
|
||||
argmap: &mut FxIndexSet<(usize, ArgumentType)>,
|
||||
) -> P<ast::Expr> {
|
||||
// Generate:
|
||||
// ::core::fmt::rt::v1::Count::…(…)
|
||||
match count {
|
||||
Some(FormatCount::Literal(n)) => ecx.expr_call_global(
|
||||
sp,
|
||||
ecx.std_path(&[sym::fmt, sym::rt, sym::v1, sym::Count, sym::Is]),
|
||||
vec![ecx.expr_usize(sp, *n)],
|
||||
),
|
||||
Some(FormatCount::Argument(arg)) => {
|
||||
if let Ok(arg_index) = arg.index {
|
||||
let (i, _) = argmap.insert_full((arg_index, ArgumentType::Usize));
|
||||
ecx.expr_call_global(
|
||||
sp,
|
||||
ecx.std_path(&[sym::fmt, sym::rt, sym::v1, sym::Count, sym::Param]),
|
||||
vec![ecx.expr_usize(sp, i)],
|
||||
)
|
||||
} else {
|
||||
DummyResult::raw_expr(sp, true)
|
||||
}
|
||||
}
|
||||
None => ecx.expr_path(ecx.path_global(
|
||||
sp,
|
||||
ecx.std_path(&[sym::fmt, sym::rt, sym::v1, sym::Count, sym::Implied]),
|
||||
)),
|
||||
}
|
||||
}
|
||||
|
||||
fn make_format_spec(
|
||||
ecx: &ExtCtxt<'_>,
|
||||
sp: Span,
|
||||
placeholder: &FormatPlaceholder,
|
||||
argmap: &mut FxIndexSet<(usize, ArgumentType)>,
|
||||
) -> P<ast::Expr> {
|
||||
// Generate:
|
||||
// ::core::fmt::rt::v1::Argument {
|
||||
// position: 0usize,
|
||||
// format: ::core::fmt::rt::v1::FormatSpec {
|
||||
// fill: ' ',
|
||||
// align: ::core::fmt::rt::v1::Alignment::Unknown,
|
||||
// flags: 0u32,
|
||||
// precision: ::core::fmt::rt::v1::Count::Implied,
|
||||
// width: ::core::fmt::rt::v1::Count::Implied,
|
||||
// },
|
||||
// }
|
||||
let position = match placeholder.argument.index {
|
||||
Ok(arg_index) => {
|
||||
let (i, _) =
|
||||
argmap.insert_full((arg_index, ArgumentType::Format(placeholder.format_trait)));
|
||||
ecx.expr_usize(sp, i)
|
||||
}
|
||||
Err(_) => DummyResult::raw_expr(sp, true),
|
||||
};
|
||||
let fill = ecx.expr_char(sp, placeholder.format_options.fill.unwrap_or(' '));
|
||||
let align = ecx.expr_path(ecx.path_global(
|
||||
sp,
|
||||
ecx.std_path(&[
|
||||
sym::fmt,
|
||||
sym::rt,
|
||||
sym::v1,
|
||||
sym::Alignment,
|
||||
match placeholder.format_options.alignment {
|
||||
Some(FormatAlignment::Left) => sym::Left,
|
||||
Some(FormatAlignment::Right) => sym::Right,
|
||||
Some(FormatAlignment::Center) => sym::Center,
|
||||
None => sym::Unknown,
|
||||
},
|
||||
]),
|
||||
));
|
||||
let flags = ecx.expr_u32(sp, placeholder.format_options.flags);
|
||||
let prec = make_count(ecx, sp, &placeholder.format_options.precision, argmap);
|
||||
let width = make_count(ecx, sp, &placeholder.format_options.width, argmap);
|
||||
ecx.expr_struct(
|
||||
sp,
|
||||
ecx.path_global(sp, ecx.std_path(&[sym::fmt, sym::rt, sym::v1, sym::Argument])),
|
||||
vec![
|
||||
ecx.field_imm(sp, Ident::new(sym::position, sp), position),
|
||||
ecx.field_imm(
|
||||
sp,
|
||||
Ident::new(sym::format, sp),
|
||||
ecx.expr_struct(
|
||||
sp,
|
||||
ecx.path_global(
|
||||
sp,
|
||||
ecx.std_path(&[sym::fmt, sym::rt, sym::v1, sym::FormatSpec]),
|
||||
),
|
||||
vec![
|
||||
ecx.field_imm(sp, Ident::new(sym::fill, sp), fill),
|
||||
ecx.field_imm(sp, Ident::new(sym::align, sp), align),
|
||||
ecx.field_imm(sp, Ident::new(sym::flags, sp), flags),
|
||||
ecx.field_imm(sp, Ident::new(sym::precision, sp), prec),
|
||||
ecx.field_imm(sp, Ident::new(sym::width, sp), width),
|
||||
],
|
||||
),
|
||||
),
|
||||
],
|
||||
)
|
||||
}
|
||||
|
||||
pub fn expand_parsed_format_args(ecx: &mut ExtCtxt<'_>, fmt: FormatArgs) -> P<ast::Expr> {
|
||||
let macsp = ecx.with_def_site_ctxt(ecx.call_site());
|
||||
|
||||
let lit_pieces = ecx.expr_array_ref(
|
||||
fmt.span,
|
||||
fmt.template
|
||||
.iter()
|
||||
.enumerate()
|
||||
.filter_map(|(i, piece)| match piece {
|
||||
&FormatArgsPiece::Literal(s) => Some(ecx.expr_str(fmt.span, s)),
|
||||
&FormatArgsPiece::Placeholder(_) => {
|
||||
// Inject empty string before placeholders when not already preceded by a literal piece.
|
||||
if i == 0 || matches!(fmt.template[i - 1], FormatArgsPiece::Placeholder(_)) {
|
||||
Some(ecx.expr_str(fmt.span, kw::Empty))
|
||||
} else {
|
||||
None
|
||||
}
|
||||
}
|
||||
})
|
||||
.collect(),
|
||||
);
|
||||
|
||||
// Whether we'll use the `Arguments::new_v1_formatted` form (true),
|
||||
// or the `Arguments::new_v1` form (false).
|
||||
let mut use_format_options = false;
|
||||
|
||||
// Create a list of all _unique_ (argument, format trait) combinations.
|
||||
// E.g. "{0} {0:x} {0} {1}" -> [(0, Display), (0, LowerHex), (1, Display)]
|
||||
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:
|
||||
// &[format_spec_0, format_spec_1, format_spec_2]
|
||||
ecx.expr_array_ref(
|
||||
macsp,
|
||||
fmt.template
|
||||
.iter()
|
||||
.filter_map(|piece| {
|
||||
let FormatArgsPiece::Placeholder(placeholder) = piece else { return None };
|
||||
Some(make_format_spec(ecx, macsp, placeholder, &mut argmap))
|
||||
})
|
||||
.collect(),
|
||||
)
|
||||
});
|
||||
|
||||
let arguments = fmt.arguments.into_vec();
|
||||
|
||||
// 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,
|
||||
// we don't do this, because an ArgumentV1 cannot be kept across yield points.
|
||||
let use_simple_array = argmap.len() == arguments.len()
|
||||
&& argmap.iter().enumerate().all(|(i, &(j, _))| i == j)
|
||||
&& arguments.iter().skip(1).all(|arg| !may_contain_yield_point(&arg.expr));
|
||||
|
||||
let args = if use_simple_array {
|
||||
// Generate:
|
||||
// &[
|
||||
// ::core::fmt::ArgumentV1::new_display(&arg0),
|
||||
// ::core::fmt::ArgumentV1::new_lower_hex(&arg1),
|
||||
// ::core::fmt::ArgumentV1::new_debug(&arg2),
|
||||
// ]
|
||||
ecx.expr_array_ref(
|
||||
macsp,
|
||||
arguments
|
||||
.into_iter()
|
||||
.zip(argmap)
|
||||
.map(|(arg, (_, ty))| {
|
||||
let sp = arg.expr.span.with_ctxt(macsp.ctxt());
|
||||
make_argument(ecx, sp, ecx.expr_addr_of(sp, arg.expr), ty)
|
||||
})
|
||||
.collect(),
|
||||
)
|
||||
} else {
|
||||
// Generate:
|
||||
// match (&arg0, &arg1, &arg2) {
|
||||
// args => &[
|
||||
// ::core::fmt::ArgumentV1::new_display(args.0),
|
||||
// ::core::fmt::ArgumentV1::new_lower_hex(args.1),
|
||||
// ::core::fmt::ArgumentV1::new_debug(args.0),
|
||||
// ]
|
||||
// }
|
||||
let args_ident = Ident::new(sym::args, macsp);
|
||||
let args = argmap
|
||||
.iter()
|
||||
.map(|&(arg_index, ty)| {
|
||||
if let Some(arg) = arguments.get(arg_index) {
|
||||
let sp = arg.expr.span.with_ctxt(macsp.ctxt());
|
||||
make_argument(
|
||||
ecx,
|
||||
sp,
|
||||
ecx.expr_field(
|
||||
sp,
|
||||
ecx.expr_ident(macsp, args_ident),
|
||||
Ident::new(sym::integer(arg_index), macsp),
|
||||
),
|
||||
ty,
|
||||
)
|
||||
} else {
|
||||
DummyResult::raw_expr(macsp, true)
|
||||
}
|
||||
})
|
||||
.collect();
|
||||
ecx.expr_addr_of(
|
||||
macsp,
|
||||
ecx.expr_match(
|
||||
macsp,
|
||||
ecx.expr_tuple(
|
||||
macsp,
|
||||
arguments
|
||||
.into_iter()
|
||||
.map(|arg| {
|
||||
ecx.expr_addr_of(arg.expr.span.with_ctxt(macsp.ctxt()), arg.expr)
|
||||
})
|
||||
.collect(),
|
||||
),
|
||||
vec![ecx.arm(macsp, ecx.pat_ident(macsp, args_ident), ecx.expr_array(macsp, args))],
|
||||
),
|
||||
)
|
||||
};
|
||||
|
||||
if let Some(format_options) = format_options {
|
||||
// Generate:
|
||||
// ::core::fmt::Arguments::new_v1_formatted(
|
||||
// lit_pieces,
|
||||
// args,
|
||||
// format_options,
|
||||
// unsafe { ::core::fmt::UnsafeArg::new() }
|
||||
// )
|
||||
ecx.expr_call_global(
|
||||
macsp,
|
||||
ecx.std_path(&[sym::fmt, sym::Arguments, sym::new_v1_formatted]),
|
||||
vec![
|
||||
lit_pieces,
|
||||
args,
|
||||
format_options,
|
||||
ecx.expr_block(P(ast::Block {
|
||||
stmts: vec![ecx.stmt_expr(ecx.expr_call_global(
|
||||
macsp,
|
||||
ecx.std_path(&[sym::fmt, sym::UnsafeArg, sym::new]),
|
||||
Vec::new(),
|
||||
))],
|
||||
id: ast::DUMMY_NODE_ID,
|
||||
rules: BlockCheckMode::Unsafe(UnsafeSource::CompilerGenerated),
|
||||
span: macsp,
|
||||
tokens: None,
|
||||
could_be_bare_literal: false,
|
||||
})),
|
||||
],
|
||||
)
|
||||
} else {
|
||||
// Generate:
|
||||
// ::core::fmt::Arguments::new_v1(
|
||||
// lit_pieces,
|
||||
// args,
|
||||
// )
|
||||
ecx.expr_call_global(
|
||||
macsp,
|
||||
ecx.std_path(&[sym::fmt, sym::Arguments, sym::new_v1]),
|
||||
vec![lit_pieces, args],
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
fn may_contain_yield_point(e: &ast::Expr) -> bool {
|
||||
struct MayContainYieldPoint(bool);
|
||||
|
||||
impl Visitor<'_> for MayContainYieldPoint {
|
||||
fn visit_expr(&mut self, e: &ast::Expr) {
|
||||
if let ast::ExprKind::Await(_) | ast::ExprKind::Yield(_) = e.kind {
|
||||
self.0 = true;
|
||||
} else {
|
||||
visit::walk_expr(self, e);
|
||||
}
|
||||
}
|
||||
|
||||
fn visit_mac_call(&mut self, _: &ast::MacCall) {
|
||||
self.0 = true;
|
||||
}
|
||||
|
||||
fn visit_attribute(&mut self, _: &ast::Attribute) {
|
||||
// Conservatively assume this may be a proc macro attribute in
|
||||
// expression position.
|
||||
self.0 = true;
|
||||
}
|
||||
|
||||
fn visit_item(&mut self, _: &ast::Item) {
|
||||
// Do not recurse into nested items.
|
||||
}
|
||||
}
|
||||
|
||||
let mut visitor = MayContainYieldPoint(false);
|
||||
visitor.visit_expr(e);
|
||||
visitor.0
|
||||
}
|
|
@ -7,6 +7,7 @@
|
|||
#![feature(box_patterns)]
|
||||
#![feature(decl_macro)]
|
||||
#![feature(if_let_guard)]
|
||||
#![feature(is_some_with)]
|
||||
#![feature(is_sorted)]
|
||||
#![feature(let_chains)]
|
||||
#![feature(proc_macro_internals)]
|
||||
|
|
|
@ -252,6 +252,10 @@ impl<'a> ExtCtxt<'a> {
|
|||
self.expr_ident(span, Ident::with_dummy_span(kw::SelfLower))
|
||||
}
|
||||
|
||||
pub fn expr_field(&self, span: Span, expr: P<Expr>, field: Ident) -> P<ast::Expr> {
|
||||
self.expr(span, ast::ExprKind::Field(expr, field))
|
||||
}
|
||||
|
||||
pub fn expr_binary(
|
||||
&self,
|
||||
sp: Span,
|
||||
|
|
|
@ -991,7 +991,18 @@ symbols! {
|
|||
never_type,
|
||||
never_type_fallback,
|
||||
new,
|
||||
new_binary,
|
||||
new_debug,
|
||||
new_display,
|
||||
new_lower_exp,
|
||||
new_lower_hex,
|
||||
new_octal,
|
||||
new_pointer,
|
||||
new_unchecked,
|
||||
new_upper_exp,
|
||||
new_upper_hex,
|
||||
new_v1,
|
||||
new_v1_formatted,
|
||||
next,
|
||||
nll,
|
||||
no,
|
||||
|
|
|
@ -237,21 +237,19 @@ LL | #[suggestion(typeck::suggestion, code = "{name}")]
|
|||
| ^^^^^^^^
|
||||
|
||||
error: invalid format string: expected `'}'` but string was terminated
|
||||
--> $DIR/diagnostic-derive.rs:175:16
|
||||
--> $DIR/diagnostic-derive.rs:175:10
|
||||
|
|
||||
LL | #[derive(Diagnostic)]
|
||||
| - ^ expected `'}'` in format string
|
||||
| |
|
||||
| because of this opening brace
|
||||
| ^^^^^^^^^^ expected `'}'` in format string
|
||||
|
|
||||
= note: if you intended to print `{`, you can escape it using `{{`
|
||||
= note: this error originates in the derive macro `Diagnostic` (in Nightly builds, run with -Z macro-backtrace for more info)
|
||||
|
||||
error: invalid format string: unmatched `}` found
|
||||
--> $DIR/diagnostic-derive.rs:185:15
|
||||
--> $DIR/diagnostic-derive.rs:185:10
|
||||
|
|
||||
LL | #[derive(Diagnostic)]
|
||||
| ^ unmatched `}` in format string
|
||||
| ^^^^^^^^^^ unmatched `}` in format string
|
||||
|
|
||||
= note: if you intended to print `}`, you can escape it using `}}`
|
||||
= note: this error originates in the derive macro `Diagnostic` (in Nightly builds, run with -Z macro-backtrace for more info)
|
||||
|
|
|
@ -3,9 +3,9 @@ fn main() {
|
|||
let b = "b";
|
||||
|
||||
println!("{a} {b} {} {} {c} {}", c = "c");
|
||||
//~^ ERROR: invalid reference to positional arguments 1 and 2 (there is 1 argument)
|
||||
//~^ ERROR: 3 positional arguments in format string, but there is 1 argument
|
||||
|
||||
let n = 1;
|
||||
println!("{a:.n$} {b:.*}");
|
||||
//~^ ERROR: invalid reference to positional argument 0 (no arguments were given)
|
||||
//~^ ERROR: 1 positional argument in format string, but no arguments were given
|
||||
}
|
||||
|
|
|
@ -1,19 +1,14 @@
|
|||
error: invalid reference to positional arguments 1 and 2 (there is 1 argument)
|
||||
--> $DIR/format-args-capture-issue-93378.rs:5:26
|
||||
error: 3 positional arguments in format string, but there is 1 argument
|
||||
--> $DIR/format-args-capture-issue-93378.rs:5:23
|
||||
|
|
||||
LL | println!("{a} {b} {} {} {c} {}", c = "c");
|
||||
| ^^ ^^
|
||||
|
|
||||
= note: positional arguments are zero-based
|
||||
| ^^ ^^ ^^ ---
|
||||
|
||||
error: invalid reference to positional argument 0 (no arguments were given)
|
||||
--> $DIR/format-args-capture-issue-93378.rs:9:23
|
||||
error: 1 positional argument in format string, but no arguments were given
|
||||
--> $DIR/format-args-capture-issue-93378.rs:9:26
|
||||
|
|
||||
LL | println!("{a:.n$} {b:.*}");
|
||||
| - ^^^--^
|
||||
| | |
|
||||
| | this precision flag adds an extra required argument at position 0, which is why there are 3 arguments expected
|
||||
| this parameter corresponds to the precision flag
|
||||
| ^^ this precision flag adds an extra required argument at position 0, which is why there is 1 argument expected
|
||||
|
|
||||
= note: positional arguments are zero-based
|
||||
= note: for information about formatting flags, visit https://doc.rust-lang.org/std/fmt/index.html
|
||||
|
|
|
@ -20,9 +20,9 @@ fn main() {
|
|||
//~^ ERROR: invalid reference to positional argument 2 (there are 2 arguments)
|
||||
|
||||
format!("{} {value} {} {}", 1, value=2);
|
||||
//~^ ERROR: invalid reference to positional argument 2 (there are 2 arguments)
|
||||
//~^ ERROR: 3 positional arguments in format string, but there are 2 arguments
|
||||
format!("{name} {value} {} {} {} {} {} {}", 0, name=1, value=2);
|
||||
//~^ ERROR: invalid reference to positional arguments 3, 4 and 5 (there are 3 arguments)
|
||||
//~^ ERROR: 6 positional arguments in format string, but there are 3 arguments
|
||||
|
||||
format!("{} {foo} {} {bar} {}", 1, 2, 3);
|
||||
//~^ ERROR: cannot find value `foo` in this scope
|
||||
|
@ -79,7 +79,7 @@ tenth number: {}",
|
|||
//~^ ERROR 4 positional arguments in format string, but there are 3 arguments
|
||||
//~| ERROR mismatched types
|
||||
println!("{} {:07$.*} {}", 1, 3.2, 4);
|
||||
//~^ ERROR 4 positional arguments in format string, but there are 3 arguments
|
||||
//~^ ERROR invalid reference to positional arguments 3 and 7 (there are 3 arguments)
|
||||
//~| ERROR mismatched types
|
||||
println!("{} {:07$} {}", 1, 3.2, 4);
|
||||
//~^ ERROR invalid reference to positional argument 7 (there are 3 arguments)
|
||||
|
@ -95,5 +95,5 @@ tenth number: {}",
|
|||
println!("{:.*}");
|
||||
//~^ ERROR 2 positional arguments in format string, but no arguments were given
|
||||
println!("{:.0$}");
|
||||
//~^ ERROR 1 positional argument in format string, but no arguments were given
|
||||
//~^ ERROR invalid reference to positional argument 0 (no arguments were given)
|
||||
}
|
||||
|
|
|
@ -5,10 +5,10 @@ LL | format!("{}");
|
|||
| ^^
|
||||
|
||||
error: invalid reference to positional argument 1 (there is 1 argument)
|
||||
--> $DIR/ifmt-bad-arg.rs:9:14
|
||||
--> $DIR/ifmt-bad-arg.rs:9:15
|
||||
|
|
||||
LL | format!("{1}", 1);
|
||||
| ^^^
|
||||
| ^
|
||||
|
|
||||
= note: positional arguments are zero-based
|
||||
|
||||
|
@ -27,36 +27,32 @@ LL | format!("{} {}");
|
|||
| ^^ ^^
|
||||
|
||||
error: invalid reference to positional argument 1 (there is 1 argument)
|
||||
--> $DIR/ifmt-bad-arg.rs:16:18
|
||||
--> $DIR/ifmt-bad-arg.rs:16:19
|
||||
|
|
||||
LL | format!("{0} {1}", 1);
|
||||
| ^^^
|
||||
| ^
|
||||
|
|
||||
= note: positional arguments are zero-based
|
||||
|
||||
error: invalid reference to positional argument 2 (there are 2 arguments)
|
||||
--> $DIR/ifmt-bad-arg.rs:19:22
|
||||
--> $DIR/ifmt-bad-arg.rs:19:23
|
||||
|
|
||||
LL | format!("{0} {1} {2}", 1, 2);
|
||||
| ^^^
|
||||
| ^
|
||||
|
|
||||
= note: positional arguments are zero-based
|
||||
|
||||
error: invalid reference to positional argument 2 (there are 2 arguments)
|
||||
--> $DIR/ifmt-bad-arg.rs:22:28
|
||||
error: 3 positional arguments in format string, but there are 2 arguments
|
||||
--> $DIR/ifmt-bad-arg.rs:22:14
|
||||
|
|
||||
LL | format!("{} {value} {} {}", 1, value=2);
|
||||
| ^^
|
||||
|
|
||||
= note: positional arguments are zero-based
|
||||
| ^^ ^^ ^^ - -
|
||||
|
||||
error: invalid reference to positional arguments 3, 4 and 5 (there are 3 arguments)
|
||||
--> $DIR/ifmt-bad-arg.rs:24:38
|
||||
error: 6 positional arguments in format string, but there are 3 arguments
|
||||
--> $DIR/ifmt-bad-arg.rs:24:29
|
||||
|
|
||||
LL | format!("{name} {value} {} {} {} {} {} {}", 0, name=1, value=2);
|
||||
| ^^ ^^ ^^
|
||||
|
|
||||
= note: positional arguments are zero-based
|
||||
| ^^ ^^ ^^ ^^ ^^ ^^ - - -
|
||||
|
||||
error: multiple unused formatting arguments
|
||||
--> $DIR/ifmt-bad-arg.rs:32:17
|
||||
|
@ -117,20 +113,20 @@ LL | format!("{} {}", 1, 2, foo=1, bar=2);
|
|||
| multiple missing formatting specifiers
|
||||
|
||||
error: duplicate argument named `foo`
|
||||
--> $DIR/ifmt-bad-arg.rs:40:33
|
||||
--> $DIR/ifmt-bad-arg.rs:40:29
|
||||
|
|
||||
LL | format!("{foo}", foo=1, foo=2);
|
||||
| - ^ duplicate argument
|
||||
| |
|
||||
| previously here
|
||||
| --- ^^^ duplicate argument
|
||||
| |
|
||||
| previously here
|
||||
|
||||
error: positional arguments cannot follow named arguments
|
||||
--> $DIR/ifmt-bad-arg.rs:41:35
|
||||
|
|
||||
LL | format!("{foo} {} {}", foo=1, 2);
|
||||
| - ^ positional arguments must be before named arguments
|
||||
| |
|
||||
| named argument
|
||||
| ----- ^ positional arguments must be before named arguments
|
||||
| |
|
||||
| named argument
|
||||
|
||||
error: named argument never used
|
||||
--> $DIR/ifmt-bad-arg.rs:45:51
|
||||
|
@ -191,33 +187,26 @@ error: 4 positional arguments in format string, but there are 3 arguments
|
|||
|
|
||||
LL | println!("{} {:.*} {}", 1, 3.2, 4);
|
||||
| ^^ ^^--^ ^^ - --- -
|
||||
| | |
|
||||
| | this parameter corresponds to the precision flag
|
||||
| |
|
||||
| this precision flag adds an extra required argument at position 1, which is why there are 4 arguments expected
|
||||
|
|
||||
= note: positional arguments are zero-based
|
||||
= note: for information about formatting flags, visit https://doc.rust-lang.org/std/fmt/index.html
|
||||
|
||||
error: 4 positional arguments in format string, but there are 3 arguments
|
||||
--> $DIR/ifmt-bad-arg.rs:81:15
|
||||
error: invalid reference to positional arguments 3 and 7 (there are 3 arguments)
|
||||
--> $DIR/ifmt-bad-arg.rs:81:21
|
||||
|
|
||||
LL | println!("{} {:07$.*} {}", 1, 3.2, 4);
|
||||
| ^^ ^^^----^ ^^ - --- -
|
||||
| | | |
|
||||
| | | this parameter corresponds to the precision flag
|
||||
| | this precision flag adds an extra required argument at position 1, which is why there are 4 arguments expected
|
||||
| this width flag expects an `usize` argument at position 7, but there are 3 arguments
|
||||
| ^^ ^
|
||||
|
|
||||
= note: positional arguments are zero-based
|
||||
= note: for information about formatting flags, visit https://doc.rust-lang.org/std/fmt/index.html
|
||||
|
||||
error: invalid reference to positional argument 7 (there are 3 arguments)
|
||||
--> $DIR/ifmt-bad-arg.rs:84:18
|
||||
--> $DIR/ifmt-bad-arg.rs:84:21
|
||||
|
|
||||
LL | println!("{} {:07$} {}", 1, 3.2, 4);
|
||||
| ^^^--^
|
||||
| |
|
||||
| this width flag expects an `usize` argument at position 7, but there are 3 arguments
|
||||
| ^^
|
||||
|
|
||||
= note: positional arguments are zero-based
|
||||
= note: for information about formatting flags, visit https://doc.rust-lang.org/std/fmt/index.html
|
||||
|
@ -240,24 +229,19 @@ LL | println!("{:foo}", 1);
|
|||
- `X`, which uses the `UpperHex` trait
|
||||
|
||||
error: invalid reference to positional arguments 4, 5, 6 and 7 (there is 1 argument)
|
||||
--> $DIR/ifmt-bad-arg.rs:87:15
|
||||
--> $DIR/ifmt-bad-arg.rs:87:16
|
||||
|
|
||||
LL | println!("{5} {:4$} {6:7$}", 1);
|
||||
| ^^^ ^^--^ ^^^--^
|
||||
| | |
|
||||
| | this width flag expects an `usize` argument at position 7, but there is 1 argument
|
||||
| this width flag expects an `usize` argument at position 4, but there is 1 argument
|
||||
| ^ ^^ ^ ^^
|
||||
|
|
||||
= note: positional arguments are zero-based
|
||||
= note: for information about formatting flags, visit https://doc.rust-lang.org/std/fmt/index.html
|
||||
|
||||
error: invalid reference to positional argument 0 (no arguments were given)
|
||||
--> $DIR/ifmt-bad-arg.rs:90:15
|
||||
--> $DIR/ifmt-bad-arg.rs:90:20
|
||||
|
|
||||
LL | println!("{foo:0$}");
|
||||
| ^^^^^--^
|
||||
| |
|
||||
| this width flag expects an `usize` argument at position 0, but no arguments were given
|
||||
| ^^
|
||||
|
|
||||
= note: positional arguments are zero-based
|
||||
= note: for information about formatting flags, visit https://doc.rust-lang.org/std/fmt/index.html
|
||||
|
@ -273,13 +257,11 @@ LL | println!("{:.*}");
|
|||
= note: positional arguments are zero-based
|
||||
= note: for information about formatting flags, visit https://doc.rust-lang.org/std/fmt/index.html
|
||||
|
||||
error: 1 positional argument in format string, but no arguments were given
|
||||
--> $DIR/ifmt-bad-arg.rs:97:15
|
||||
error: invalid reference to positional argument 0 (no arguments were given)
|
||||
--> $DIR/ifmt-bad-arg.rs:97:16
|
||||
|
|
||||
LL | println!("{:.0$}");
|
||||
| ^^---^
|
||||
| |
|
||||
| this precision flag expects an `usize` argument at position 0, but no arguments were given
|
||||
| ^^^^
|
||||
|
|
||||
= note: positional arguments are zero-based
|
||||
= note: for information about formatting flags, visit https://doc.rust-lang.org/std/fmt/index.html
|
||||
|
@ -318,10 +300,10 @@ error[E0308]: mismatched types
|
|||
--> $DIR/ifmt-bad-arg.rs:78:32
|
||||
|
|
||||
LL | println!("{} {:.*} {}", 1, 3.2, 4);
|
||||
| ---------------------------^^^----
|
||||
| | |
|
||||
| | expected `usize`, found floating-point number
|
||||
| arguments to this function are incorrect
|
||||
| ^^^
|
||||
| |
|
||||
| expected `usize`, found floating-point number
|
||||
| arguments to this function are incorrect
|
||||
|
|
||||
= note: expected reference `&usize`
|
||||
found reference `&{float}`
|
||||
|
@ -336,10 +318,10 @@ error[E0308]: mismatched types
|
|||
--> $DIR/ifmt-bad-arg.rs:81:35
|
||||
|
|
||||
LL | println!("{} {:07$.*} {}", 1, 3.2, 4);
|
||||
| ------------------------------^^^----
|
||||
| | |
|
||||
| | expected `usize`, found floating-point number
|
||||
| arguments to this function are incorrect
|
||||
| ^^^
|
||||
| |
|
||||
| expected `usize`, found floating-point number
|
||||
| arguments to this function are incorrect
|
||||
|
|
||||
= note: expected reference `&usize`
|
||||
found reference `&{float}`
|
||||
|
|
|
@ -1,3 +1,3 @@
|
|||
fn main() {
|
||||
format!(r"{}{}{}", named_arg=1); //~ ERROR invalid reference to positional arguments 1 and 2
|
||||
format!(r"{}{}{}", named_arg=1); //~ ERROR 3 positional arguments in format string, but there is 1 argument
|
||||
}
|
||||
|
|
|
@ -1,10 +1,8 @@
|
|||
error: invalid reference to positional arguments 1 and 2 (there is 1 argument)
|
||||
--> $DIR/issue-75307.rs:2:17
|
||||
error: 3 positional arguments in format string, but there is 1 argument
|
||||
--> $DIR/issue-75307.rs:2:15
|
||||
|
|
||||
LL | format!(r"{}{}{}", named_arg=1);
|
||||
| ^^^^
|
||||
|
|
||||
= note: positional arguments are zero-based
|
||||
| ^^^^^^ -
|
||||
|
||||
error: aborting due to previous error
|
||||
|
||||
|
|
|
@ -22,7 +22,7 @@ error: positional arguments cannot follow named arguments
|
|||
--> $DIR/format-parse-errors.rs:10:9
|
||||
|
|
||||
LL | foo = foo,
|
||||
| --- named argument
|
||||
| --------- named argument
|
||||
LL | bar,
|
||||
| ^^^ positional arguments must be before named arguments
|
||||
|
||||
|
|
|
@ -77,18 +77,18 @@ help: use the named argument by name to avoid ambiguity
|
|||
LL | println!("Hello {:width$}!", "x", width = 5);
|
||||
| ~~~~~~
|
||||
|
||||
warning: named argument `width` is not used by name
|
||||
--> $DIR/issue-99265.rs:23:46
|
||||
warning: named argument `f` is not used by name
|
||||
--> $DIR/issue-99265.rs:23:33
|
||||
|
|
||||
LL | println!("Hello {:1$.2$}!", f = 0.02f32, width = 5, precision = 2);
|
||||
| -- ^^^^^ this named argument is referred to by position in formatting string
|
||||
| |
|
||||
| this formatting argument uses named argument `width` by position
|
||||
| -------- ^ this named argument is referred to by position in formatting string
|
||||
| |
|
||||
| this formatting argument uses named argument `f` by position
|
||||
|
|
||||
help: use the named argument by name to avoid ambiguity
|
||||
|
|
||||
LL | println!("Hello {:width$.2$}!", f = 0.02f32, width = 5, precision = 2);
|
||||
| ~~~~~~
|
||||
LL | println!("Hello {f:1$.2$}!", f = 0.02f32, width = 5, precision = 2);
|
||||
| +
|
||||
|
||||
warning: named argument `precision` is not used by name
|
||||
--> $DIR/issue-99265.rs:23:57
|
||||
|
@ -103,31 +103,31 @@ help: use the named argument by name to avoid ambiguity
|
|||
LL | println!("Hello {:1$.precision$}!", f = 0.02f32, width = 5, precision = 2);
|
||||
| ~~~~~~~~~~
|
||||
|
||||
warning: named argument `f` is not used by name
|
||||
--> $DIR/issue-99265.rs:23:33
|
||||
warning: named argument `width` is not used by name
|
||||
--> $DIR/issue-99265.rs:23:46
|
||||
|
|
||||
LL | println!("Hello {:1$.2$}!", f = 0.02f32, width = 5, precision = 2);
|
||||
| -- ^ this named argument is referred to by position in formatting string
|
||||
| -- ^^^^^ this named argument is referred to by position in formatting string
|
||||
| |
|
||||
| this formatting argument uses named argument `width` by position
|
||||
|
|
||||
help: use the named argument by name to avoid ambiguity
|
||||
|
|
||||
LL | println!("Hello {:width$.2$}!", f = 0.02f32, width = 5, precision = 2);
|
||||
| ~~~~~~
|
||||
|
||||
warning: named argument `f` is not used by name
|
||||
--> $DIR/issue-99265.rs:31:34
|
||||
|
|
||||
LL | println!("Hello {0:1$.2$}!", f = 0.02f32, width = 5, precision = 2);
|
||||
| --------- ^ this named argument is referred to by position in formatting string
|
||||
| |
|
||||
| this formatting argument uses named argument `f` by position
|
||||
|
|
||||
help: use the named argument by name to avoid ambiguity
|
||||
|
|
||||
LL | println!("Hello {f:1$.2$}!", f = 0.02f32, width = 5, precision = 2);
|
||||
| +
|
||||
|
||||
warning: named argument `width` is not used by name
|
||||
--> $DIR/issue-99265.rs:31:47
|
||||
|
|
||||
LL | println!("Hello {0:1$.2$}!", f = 0.02f32, width = 5, precision = 2);
|
||||
| -- ^^^^^ this named argument is referred to by position in formatting string
|
||||
| |
|
||||
| this formatting argument uses named argument `width` by position
|
||||
|
|
||||
help: use the named argument by name to avoid ambiguity
|
||||
|
|
||||
LL | println!("Hello {0:width$.2$}!", f = 0.02f32, width = 5, precision = 2);
|
||||
| ~~~~~~
|
||||
| ~
|
||||
|
||||
warning: named argument `precision` is not used by name
|
||||
--> $DIR/issue-99265.rs:31:58
|
||||
|
@ -142,32 +142,32 @@ help: use the named argument by name to avoid ambiguity
|
|||
LL | println!("Hello {0:1$.precision$}!", f = 0.02f32, width = 5, precision = 2);
|
||||
| ~~~~~~~~~~
|
||||
|
||||
warning: named argument `f` is not used by name
|
||||
--> $DIR/issue-99265.rs:31:34
|
||||
warning: named argument `width` is not used by name
|
||||
--> $DIR/issue-99265.rs:31:47
|
||||
|
|
||||
LL | println!("Hello {0:1$.2$}!", f = 0.02f32, width = 5, precision = 2);
|
||||
| - ^ this named argument is referred to by position in formatting string
|
||||
| |
|
||||
| this formatting argument uses named argument `f` by position
|
||||
| -- ^^^^^ this named argument is referred to by position in formatting string
|
||||
| |
|
||||
| this formatting argument uses named argument `width` by position
|
||||
|
|
||||
help: use the named argument by name to avoid ambiguity
|
||||
|
|
||||
LL | println!("Hello {f:1$.2$}!", f = 0.02f32, width = 5, precision = 2);
|
||||
| ~
|
||||
LL | println!("Hello {0:width$.2$}!", f = 0.02f32, width = 5, precision = 2);
|
||||
| ~~~~~~
|
||||
|
||||
warning: named argument `width` is not used by name
|
||||
--> $DIR/issue-99265.rs:52:9
|
||||
warning: named argument `f` is not used by name
|
||||
--> $DIR/issue-99265.rs:49:9
|
||||
|
|
||||
LL | "{}, Hello {1:2$.3$} {4:5$.6$}! {1}",
|
||||
| -- this formatting argument uses named argument `width` by position
|
||||
| --------- this formatting argument uses named argument `f` by position
|
||||
...
|
||||
LL | width = 5,
|
||||
| ^^^^^ this named argument is referred to by position in formatting string
|
||||
LL | f = 0.02f32,
|
||||
| ^ this named argument is referred to by position in formatting string
|
||||
|
|
||||
help: use the named argument by name to avoid ambiguity
|
||||
|
|
||||
LL | "{}, Hello {1:width$.3$} {4:5$.6$}! {1}",
|
||||
| ~~~~~~
|
||||
LL | "{}, Hello {f:2$.3$} {4:5$.6$}! {1}",
|
||||
| ~
|
||||
|
||||
warning: named argument `precision` is not used by name
|
||||
--> $DIR/issue-99265.rs:54:9
|
||||
|
@ -183,33 +183,33 @@ help: use the named argument by name to avoid ambiguity
|
|||
LL | "{}, Hello {1:2$.precision$} {4:5$.6$}! {1}",
|
||||
| ~~~~~~~~~~
|
||||
|
||||
warning: named argument `f` is not used by name
|
||||
--> $DIR/issue-99265.rs:49:9
|
||||
warning: named argument `width` is not used by name
|
||||
--> $DIR/issue-99265.rs:52:9
|
||||
|
|
||||
LL | "{}, Hello {1:2$.3$} {4:5$.6$}! {1}",
|
||||
| - this formatting argument uses named argument `f` by position
|
||||
| -- this formatting argument uses named argument `width` by position
|
||||
...
|
||||
LL | f = 0.02f32,
|
||||
LL | width = 5,
|
||||
| ^^^^^ this named argument is referred to by position in formatting string
|
||||
|
|
||||
help: use the named argument by name to avoid ambiguity
|
||||
|
|
||||
LL | "{}, Hello {1:width$.3$} {4:5$.6$}! {1}",
|
||||
| ~~~~~~
|
||||
|
||||
warning: named argument `g` is not used by name
|
||||
--> $DIR/issue-99265.rs:56:9
|
||||
|
|
||||
LL | "{}, Hello {1:2$.3$} {4:5$.6$}! {1}",
|
||||
| --------- this formatting argument uses named argument `g` by position
|
||||
...
|
||||
LL | g = 0.02f32,
|
||||
| ^ this named argument is referred to by position in formatting string
|
||||
|
|
||||
help: use the named argument by name to avoid ambiguity
|
||||
|
|
||||
LL | "{}, Hello {f:2$.3$} {4:5$.6$}! {1}",
|
||||
| ~
|
||||
|
||||
warning: named argument `width2` is not used by name
|
||||
--> $DIR/issue-99265.rs:58:9
|
||||
|
|
||||
LL | "{}, Hello {1:2$.3$} {4:5$.6$}! {1}",
|
||||
| -- this formatting argument uses named argument `width2` by position
|
||||
...
|
||||
LL | width2 = 5,
|
||||
| ^^^^^^ this named argument is referred to by position in formatting string
|
||||
|
|
||||
help: use the named argument by name to avoid ambiguity
|
||||
|
|
||||
LL | "{}, Hello {1:2$.3$} {4:width2$.6$}! {1}",
|
||||
| ~~~~~~~
|
||||
LL | "{}, Hello {1:2$.3$} {g:5$.6$}! {1}",
|
||||
| ~
|
||||
|
||||
warning: named argument `precision2` is not used by name
|
||||
--> $DIR/issue-99265.rs:60:9
|
||||
|
@ -225,25 +225,25 @@ help: use the named argument by name to avoid ambiguity
|
|||
LL | "{}, Hello {1:2$.3$} {4:5$.precision2$}! {1}",
|
||||
| ~~~~~~~~~~~
|
||||
|
||||
warning: named argument `g` is not used by name
|
||||
--> $DIR/issue-99265.rs:56:9
|
||||
warning: named argument `width2` is not used by name
|
||||
--> $DIR/issue-99265.rs:58:9
|
||||
|
|
||||
LL | "{}, Hello {1:2$.3$} {4:5$.6$}! {1}",
|
||||
| - this formatting argument uses named argument `g` by position
|
||||
| -- this formatting argument uses named argument `width2` by position
|
||||
...
|
||||
LL | g = 0.02f32,
|
||||
| ^ this named argument is referred to by position in formatting string
|
||||
LL | width2 = 5,
|
||||
| ^^^^^^ this named argument is referred to by position in formatting string
|
||||
|
|
||||
help: use the named argument by name to avoid ambiguity
|
||||
|
|
||||
LL | "{}, Hello {1:2$.3$} {g:5$.6$}! {1}",
|
||||
| ~
|
||||
LL | "{}, Hello {1:2$.3$} {4:width2$.6$}! {1}",
|
||||
| ~~~~~~~
|
||||
|
||||
warning: named argument `f` is not used by name
|
||||
--> $DIR/issue-99265.rs:49:9
|
||||
|
|
||||
LL | "{}, Hello {1:2$.3$} {4:5$.6$}! {1}",
|
||||
| - this formatting argument uses named argument `f` by position
|
||||
| --- this formatting argument uses named argument `f` by position
|
||||
...
|
||||
LL | f = 0.02f32,
|
||||
| ^ this named argument is referred to by position in formatting string
|
||||
|
@ -257,7 +257,7 @@ warning: named argument `f` is not used by name
|
|||
--> $DIR/issue-99265.rs:64:31
|
||||
|
|
||||
LL | println!("Hello {:0.1}!", f = 0.02f32);
|
||||
| -- ^ this named argument is referred to by position in formatting string
|
||||
| ------ ^ this named argument is referred to by position in formatting string
|
||||
| |
|
||||
| this formatting argument uses named argument `f` by position
|
||||
|
|
||||
|
@ -270,15 +270,28 @@ warning: named argument `f` is not used by name
|
|||
--> $DIR/issue-99265.rs:68:32
|
||||
|
|
||||
LL | println!("Hello {0:0.1}!", f = 0.02f32);
|
||||
| - ^ this named argument is referred to by position in formatting string
|
||||
| |
|
||||
| this formatting argument uses named argument `f` by position
|
||||
| ------- ^ this named argument is referred to by position in formatting string
|
||||
| |
|
||||
| this formatting argument uses named argument `f` by position
|
||||
|
|
||||
help: use the named argument by name to avoid ambiguity
|
||||
|
|
||||
LL | println!("Hello {f:0.1}!", f = 0.02f32);
|
||||
| ~
|
||||
|
||||
warning: named argument `v` is not used by name
|
||||
--> $DIR/issue-99265.rs:79:23
|
||||
|
|
||||
LL | println!("{:0$}", v = val);
|
||||
| ----- ^ this named argument is referred to by position in formatting string
|
||||
| |
|
||||
| this formatting argument uses named argument `v` by position
|
||||
|
|
||||
help: use the named argument by name to avoid ambiguity
|
||||
|
|
||||
LL | println!("{v:0$}", v = val);
|
||||
| +
|
||||
|
||||
warning: named argument `v` is not used by name
|
||||
--> $DIR/issue-99265.rs:79:23
|
||||
|
|
||||
|
@ -293,17 +306,17 @@ LL | println!("{:v$}", v = val);
|
|||
| ~~
|
||||
|
||||
warning: named argument `v` is not used by name
|
||||
--> $DIR/issue-99265.rs:79:23
|
||||
--> $DIR/issue-99265.rs:84:24
|
||||
|
|
||||
LL | println!("{:0$}", v = val);
|
||||
| -- ^ this named argument is referred to by position in formatting string
|
||||
LL | println!("{0:0$}", v = val);
|
||||
| ------ ^ this named argument is referred to by position in formatting string
|
||||
| |
|
||||
| this formatting argument uses named argument `v` by position
|
||||
|
|
||||
help: use the named argument by name to avoid ambiguity
|
||||
|
|
||||
LL | println!("{v:0$}", v = val);
|
||||
| +
|
||||
| ~
|
||||
|
||||
warning: named argument `v` is not used by name
|
||||
--> $DIR/issue-99265.rs:84:24
|
||||
|
@ -318,31 +331,18 @@ help: use the named argument by name to avoid ambiguity
|
|||
LL | println!("{0:v$}", v = val);
|
||||
| ~~
|
||||
|
||||
warning: named argument `v` is not used by name
|
||||
--> $DIR/issue-99265.rs:84:24
|
||||
|
|
||||
LL | println!("{0:0$}", v = val);
|
||||
| - ^ this named argument is referred to by position in formatting string
|
||||
| |
|
||||
| this formatting argument uses named argument `v` by position
|
||||
|
|
||||
help: use the named argument by name to avoid ambiguity
|
||||
|
|
||||
LL | println!("{v:0$}", v = val);
|
||||
| ~
|
||||
|
||||
warning: named argument `v` is not used by name
|
||||
--> $DIR/issue-99265.rs:89:26
|
||||
|
|
||||
LL | println!("{:0$.0$}", v = val);
|
||||
| -- ^ this named argument is referred to by position in formatting string
|
||||
| |
|
||||
| this formatting argument uses named argument `v` by position
|
||||
| -------- ^ this named argument is referred to by position in formatting string
|
||||
| |
|
||||
| this formatting argument uses named argument `v` by position
|
||||
|
|
||||
help: use the named argument by name to avoid ambiguity
|
||||
|
|
||||
LL | println!("{:v$.0$}", v = val);
|
||||
| ~~
|
||||
LL | println!("{v:0$.0$}", v = val);
|
||||
| +
|
||||
|
||||
warning: named argument `v` is not used by name
|
||||
--> $DIR/issue-99265.rs:89:26
|
||||
|
@ -361,27 +361,27 @@ warning: named argument `v` is not used by name
|
|||
--> $DIR/issue-99265.rs:89:26
|
||||
|
|
||||
LL | println!("{:0$.0$}", v = val);
|
||||
| -- ^ this named argument is referred to by position in formatting string
|
||||
| -- ^ this named argument is referred to by position in formatting string
|
||||
| |
|
||||
| this formatting argument uses named argument `v` by position
|
||||
|
|
||||
help: use the named argument by name to avoid ambiguity
|
||||
|
|
||||
LL | println!("{:v$.0$}", v = val);
|
||||
| ~~
|
||||
|
||||
warning: named argument `v` is not used by name
|
||||
--> $DIR/issue-99265.rs:96:27
|
||||
|
|
||||
LL | println!("{0:0$.0$}", v = val);
|
||||
| --------- ^ this named argument is referred to by position in formatting string
|
||||
| |
|
||||
| this formatting argument uses named argument `v` by position
|
||||
|
|
||||
help: use the named argument by name to avoid ambiguity
|
||||
|
|
||||
LL | println!("{v:0$.0$}", v = val);
|
||||
| +
|
||||
|
||||
warning: named argument `v` is not used by name
|
||||
--> $DIR/issue-99265.rs:96:27
|
||||
|
|
||||
LL | println!("{0:0$.0$}", v = val);
|
||||
| -- ^ this named argument is referred to by position in formatting string
|
||||
| |
|
||||
| this formatting argument uses named argument `v` by position
|
||||
|
|
||||
help: use the named argument by name to avoid ambiguity
|
||||
|
|
||||
LL | println!("{0:v$.0$}", v = val);
|
||||
| ~~
|
||||
| ~
|
||||
|
||||
warning: named argument `v` is not used by name
|
||||
--> $DIR/issue-99265.rs:96:27
|
||||
|
@ -400,14 +400,14 @@ warning: named argument `v` is not used by name
|
|||
--> $DIR/issue-99265.rs:96:27
|
||||
|
|
||||
LL | println!("{0:0$.0$}", v = val);
|
||||
| - ^ this named argument is referred to by position in formatting string
|
||||
| |
|
||||
| this formatting argument uses named argument `v` by position
|
||||
| -- ^ this named argument is referred to by position in formatting string
|
||||
| |
|
||||
| this formatting argument uses named argument `v` by position
|
||||
|
|
||||
help: use the named argument by name to avoid ambiguity
|
||||
|
|
||||
LL | println!("{v:0$.0$}", v = val);
|
||||
| ~
|
||||
LL | println!("{0:v$.0$}", v = val);
|
||||
| ~~
|
||||
|
||||
warning: named argument `a` is not used by name
|
||||
--> $DIR/issue-99265.rs:104:28
|
||||
|
@ -426,28 +426,28 @@ warning: named argument `a` is not used by name
|
|||
--> $DIR/issue-99265.rs:104:28
|
||||
|
|
||||
LL | println!("{} {a} {0}", a = 1);
|
||||
| - ^ this named argument is referred to by position in formatting string
|
||||
| |
|
||||
| this formatting argument uses named argument `a` by position
|
||||
| --- ^ this named argument is referred to by position in formatting string
|
||||
| |
|
||||
| this formatting argument uses named argument `a` by position
|
||||
|
|
||||
help: use the named argument by name to avoid ambiguity
|
||||
|
|
||||
LL | println!("{} {a} {a}", a = 1);
|
||||
| ~
|
||||
|
||||
warning: named argument `b` is not used by name
|
||||
--> $DIR/issue-99265.rs:115:23
|
||||
warning: named argument `a` is not used by name
|
||||
--> $DIR/issue-99265.rs:115:14
|
||||
|
|
||||
LL | {:1$.2$}",
|
||||
| -- this formatting argument uses named argument `b` by position
|
||||
| -------- this formatting argument uses named argument `a` by position
|
||||
...
|
||||
LL | a = 1.0, b = 1, c = 2,
|
||||
| ^ this named argument is referred to by position in formatting string
|
||||
| ^ this named argument is referred to by position in formatting string
|
||||
|
|
||||
help: use the named argument by name to avoid ambiguity
|
||||
|
|
||||
LL | {:b$.2$}",
|
||||
| ~~
|
||||
LL | {a:1$.2$}",
|
||||
| +
|
||||
|
||||
warning: named argument `c` is not used by name
|
||||
--> $DIR/issue-99265.rs:115:30
|
||||
|
@ -463,11 +463,25 @@ help: use the named argument by name to avoid ambiguity
|
|||
LL | {:1$.c$}",
|
||||
| ~~
|
||||
|
||||
warning: named argument `a` is not used by name
|
||||
--> $DIR/issue-99265.rs:115:14
|
||||
warning: named argument `b` is not used by name
|
||||
--> $DIR/issue-99265.rs:115:23
|
||||
|
|
||||
LL | {:1$.2$}",
|
||||
| -- this formatting argument uses named argument `a` by position
|
||||
| -- this formatting argument uses named argument `b` by position
|
||||
...
|
||||
LL | a = 1.0, b = 1, c = 2,
|
||||
| ^ this named argument is referred to by position in formatting string
|
||||
|
|
||||
help: use the named argument by name to avoid ambiguity
|
||||
|
|
||||
LL | {:b$.2$}",
|
||||
| ~~
|
||||
|
||||
warning: named argument `a` is not used by name
|
||||
--> $DIR/issue-99265.rs:126:14
|
||||
|
|
||||
LL | {0:1$.2$}",
|
||||
| --------- this formatting argument uses named argument `a` by position
|
||||
...
|
||||
LL | a = 1.0, b = 1, c = 2,
|
||||
| ^ this named argument is referred to by position in formatting string
|
||||
|
@ -475,21 +489,7 @@ LL | a = 1.0, b = 1, c = 2,
|
|||
help: use the named argument by name to avoid ambiguity
|
||||
|
|
||||
LL | {a:1$.2$}",
|
||||
| +
|
||||
|
||||
warning: named argument `b` is not used by name
|
||||
--> $DIR/issue-99265.rs:126:23
|
||||
|
|
||||
LL | {0:1$.2$}",
|
||||
| -- this formatting argument uses named argument `b` by position
|
||||
...
|
||||
LL | a = 1.0, b = 1, c = 2,
|
||||
| ^ this named argument is referred to by position in formatting string
|
||||
|
|
||||
help: use the named argument by name to avoid ambiguity
|
||||
|
|
||||
LL | {0:b$.2$}",
|
||||
| ~~
|
||||
| ~
|
||||
|
||||
warning: named argument `c` is not used by name
|
||||
--> $DIR/issue-99265.rs:126:30
|
||||
|
@ -505,32 +505,32 @@ help: use the named argument by name to avoid ambiguity
|
|||
LL | {0:1$.c$}",
|
||||
| ~~
|
||||
|
||||
warning: named argument `a` is not used by name
|
||||
--> $DIR/issue-99265.rs:126:14
|
||||
warning: named argument `b` is not used by name
|
||||
--> $DIR/issue-99265.rs:126:23
|
||||
|
|
||||
LL | {0:1$.2$}",
|
||||
| - this formatting argument uses named argument `a` by position
|
||||
| -- this formatting argument uses named argument `b` by position
|
||||
...
|
||||
LL | a = 1.0, b = 1, c = 2,
|
||||
| ^ this named argument is referred to by position in formatting string
|
||||
| ^ this named argument is referred to by position in formatting string
|
||||
|
|
||||
help: use the named argument by name to avoid ambiguity
|
||||
|
|
||||
LL | {a:1$.2$}",
|
||||
| ~
|
||||
LL | {0:b$.2$}",
|
||||
| ~~
|
||||
|
||||
warning: named argument `width` is not used by name
|
||||
--> $DIR/issue-99265.rs:132:39
|
||||
warning: named argument `x` is not used by name
|
||||
--> $DIR/issue-99265.rs:132:30
|
||||
|
|
||||
LL | println!("{{{:1$.2$}}}", x = 1.0, width = 3, precision = 2);
|
||||
| -- ^^^^^ this named argument is referred to by position in formatting string
|
||||
| |
|
||||
| this formatting argument uses named argument `width` by position
|
||||
| -------- ^ this named argument is referred to by position in formatting string
|
||||
| |
|
||||
| this formatting argument uses named argument `x` by position
|
||||
|
|
||||
help: use the named argument by name to avoid ambiguity
|
||||
|
|
||||
LL | println!("{{{:width$.2$}}}", x = 1.0, width = 3, precision = 2);
|
||||
| ~~~~~~
|
||||
LL | println!("{{{x:1$.2$}}}", x = 1.0, width = 3, precision = 2);
|
||||
| +
|
||||
|
||||
warning: named argument `precision` is not used by name
|
||||
--> $DIR/issue-99265.rs:132:50
|
||||
|
@ -545,18 +545,18 @@ help: use the named argument by name to avoid ambiguity
|
|||
LL | println!("{{{:1$.precision$}}}", x = 1.0, width = 3, precision = 2);
|
||||
| ~~~~~~~~~~
|
||||
|
||||
warning: named argument `x` is not used by name
|
||||
--> $DIR/issue-99265.rs:132:30
|
||||
warning: named argument `width` is not used by name
|
||||
--> $DIR/issue-99265.rs:132:39
|
||||
|
|
||||
LL | println!("{{{:1$.2$}}}", x = 1.0, width = 3, precision = 2);
|
||||
| -- ^ this named argument is referred to by position in formatting string
|
||||
| |
|
||||
| this formatting argument uses named argument `x` by position
|
||||
| -- ^^^^^ this named argument is referred to by position in formatting string
|
||||
| |
|
||||
| this formatting argument uses named argument `width` by position
|
||||
|
|
||||
help: use the named argument by name to avoid ambiguity
|
||||
|
|
||||
LL | println!("{{{x:1$.2$}}}", x = 1.0, width = 3, precision = 2);
|
||||
| +
|
||||
LL | println!("{{{:width$.2$}}}", x = 1.0, width = 3, precision = 2);
|
||||
| ~~~~~~
|
||||
|
||||
warning: 42 warnings emitted
|
||||
|
||||
|
|
|
@ -2,7 +2,7 @@ warning: named argument `f` is not used by name
|
|||
--> $DIR/issue-99907.rs:5:30
|
||||
|
|
||||
LL | println!("Hello {:.1}!", f = 0.02f32);
|
||||
| -- ^ this named argument is referred to by position in formatting string
|
||||
| ----- ^ this named argument is referred to by position in formatting string
|
||||
| |
|
||||
| this formatting argument uses named argument `f` by position
|
||||
|
|
||||
|
@ -16,7 +16,7 @@ warning: named argument `f` is not used by name
|
|||
--> $DIR/issue-99907.rs:9:31
|
||||
|
|
||||
LL | println!("Hello {:1.1}!", f = 0.02f32);
|
||||
| -- ^ this named argument is referred to by position in formatting string
|
||||
| ------ ^ this named argument is referred to by position in formatting string
|
||||
| |
|
||||
| this formatting argument uses named argument `f` by position
|
||||
|
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue