diff --git a/compiler/rustc_builtin_macros/src/asm.rs b/compiler/rustc_builtin_macros/src/asm.rs index 829eaa305e8c0..a2205c3613d92 100644 --- a/compiler/rustc_builtin_macros/src/asm.rs +++ b/compiler/rustc_builtin_macros/src/asm.rs @@ -656,7 +656,7 @@ fn expand_preparsed_asm(ecx: &mut ExtCtxt<'_>, args: AsmArgs) -> Option { + parse::ArgumentIs(idx, _) | parse::ArgumentImplicitlyIs(idx) => { if idx >= args.operands.len() || named_pos.contains_key(&idx) || args.reg_args.contains(&idx) diff --git a/compiler/rustc_builtin_macros/src/format.rs b/compiler/rustc_builtin_macros/src/format.rs index ce897abb766e5..082c78934262b 100644 --- a/compiler/rustc_builtin_macros/src/format.rs +++ b/compiler/rustc_builtin_macros/src/format.rs @@ -11,12 +11,11 @@ use rustc_errors::{pluralize, Applicability, MultiSpan, PResult}; use rustc_expand::base::{self, *}; use rustc_parse_format as parse; use rustc_span::symbol::{sym, Ident, Symbol}; -use rustc_span::{InnerSpan, Span}; +use rustc_span::{BytePos, InnerSpan, Span}; use smallvec::SmallVec; use rustc_lint_defs::builtin::NAMED_ARGUMENTS_USED_POSITIONALLY; use rustc_lint_defs::{BufferedEarlyLint, BuiltinLintDiagnostics, LintId}; -use rustc_parse_format::Count; use std::borrow::Cow; use std::collections::hash_map::Entry; @@ -32,6 +31,136 @@ enum Position { Named(Symbol, InnerSpan), } +/// Indicates how positional named argument (i.e. an named argument which is used by position +/// instead of by name) is used in format string +/// * `Arg` is the actual argument to print +/// * `Width` is width format argument +/// * `Precision` is precion format argument +/// Example: `{Arg:Width$.Precision$} +#[derive(Debug, Eq, PartialEq)] +enum PositionalNamedArgType { + Arg, + Width, + Precision, +} + +/// Contains information necessary to create a lint for a positional named argument +#[derive(Debug)] +struct PositionalNamedArg { + ty: PositionalNamedArgType, + /// The piece of the using this argument (multiple pieces can use the same argument) + cur_piece: usize, + /// The InnerSpan for in the string to be replaced with the named argument + /// This will be None when the position is implicit + inner_span_to_replace: Option, + /// The name to use instead of the position + replacement: Symbol, + /// The span for the positional named argument (so the lint can point a message to it) + positional_named_arg_span: Span, +} + +impl PositionalNamedArg { + /// Determines what span to replace with the name of the named argument + fn get_span_to_replace(&self, cx: &Context<'_, '_>) -> Option { + if let Some(inner_span) = &self.inner_span_to_replace { + return Some( + cx.fmtsp.from_inner(InnerSpan { start: inner_span.start, end: inner_span.end }), + ); + } else if self.ty == PositionalNamedArgType::Arg { + // In the case of a named argument whose position is implicit, there will not be a span + // to replace. Instead, we insert the name after the `{`, which is the first character + // of arg_span. + return cx + .arg_spans + .get(self.cur_piece) + .map(|arg_span| arg_span.with_lo(arg_span.lo() + BytePos(1)).shrink_to_lo()); + } + + None + } +} + +/// Encapsulates all the named arguments that have been used positionally +#[derive(Debug)] +struct PositionalNamedArgsLint { + positional_named_args: Vec, +} + +impl PositionalNamedArgsLint { + /// For a given positional argument, check if the index is for a named argument. + /// + /// Since positional arguments are required to come before named arguments, if the positional + /// index is greater than or equal to the start of named arguments, we know it's a named + /// argument used positionally. + /// + /// Example: + /// println!("{} {} {2}", 0, a=1, b=2); + /// + /// In this case, the first piece (`{}`) would be ArgumentImplicitlyIs with an index of 0. The + /// total number of arguments is 3 and the number of named arguments is 2, so the start of named + /// arguments is index 1. Therefore, the index of 0 is okay. + /// + /// The second piece (`{}`) would be ArgumentImplicitlyIs with an index of 1, which is the start + /// of named arguments, and so we should add a lint to use the named argument `a`. + /// + /// The third piece (`{2}`) would be ArgumentIs with an index of 2, which is greater than the + /// start of named arguments, and so we should add a lint to use the named argument `b`. + /// + /// This same check also works for width and precision formatting when either or both are + /// CountIsParam, which contains an index into the arguments. + fn maybe_add_positional_named_arg( + &mut self, + current_positional_arg: usize, + total_args_length: usize, + format_argument_index: usize, + ty: PositionalNamedArgType, + cur_piece: usize, + inner_span_to_replace: Option, + names: &FxHashMap, + ) { + let start_of_named_args = total_args_length - names.len(); + if current_positional_arg >= start_of_named_args { + self.maybe_push(format_argument_index, ty, cur_piece, inner_span_to_replace, names) + } + } + + /// Try constructing a PositionalNamedArg struct and pushing it into the vec of positional + /// named arguments. If a named arg associated with `format_argument_index` cannot be found, + /// a new item will not be added as the lint cannot be emitted in this case. + fn maybe_push( + &mut self, + format_argument_index: usize, + ty: PositionalNamedArgType, + cur_piece: usize, + inner_span_to_replace: Option, + names: &FxHashMap, + ) { + let named_arg = names + .iter() + .find(|&(_, &(index, _))| index == format_argument_index) + .map(|found| found.clone()); + + if let Some((&replacement, &(_, positional_named_arg_span))) = named_arg { + // In FormatSpec, `precision_span` starts at the leading `.`, which we want to keep in + // the lint suggestion, so increment `start` by 1 when `PositionalArgumentType` is + // `Precision`. + let inner_span_to_replace = if ty == PositionalNamedArgType::Precision { + inner_span_to_replace + .map(|is| rustc_parse_format::InnerSpan { start: is.start + 1, end: is.end }) + } else { + inner_span_to_replace + }; + self.positional_named_args.push(PositionalNamedArg { + ty, + cur_piece, + inner_span_to_replace, + replacement, + positional_named_arg_span, + }); + } + } +} + struct Context<'a, 'b> { ecx: &'a mut ExtCtxt<'b>, /// The macro's call site. References to unstable formatting internals must @@ -118,6 +247,7 @@ struct Context<'a, 'b> { /// Whether this format string came from a string literal, as opposed to a macro. is_literal: bool, + unused_names_lint: PositionalNamedArgsLint, } /// Parses the arguments from the given list of tokens, returning the diagnostic @@ -242,7 +372,7 @@ impl<'a, 'b> Context<'a, 'b> { self.args.len() - self.num_captured_args } - fn resolve_name_inplace(&self, p: &mut parse::Piece<'_>) { + fn resolve_name_inplace(&mut self, p: &mut parse::Piece<'_>) { // NOTE: the `unwrap_or` branch is needed in case of invalid format // arguments, e.g., `format_args!("{foo}")`. let lookup = @@ -252,7 +382,7 @@ impl<'a, 'b> Context<'a, 'b> { parse::String(_) => {} parse::NextArgument(ref mut arg) => { if let parse::ArgumentNamed(s, _) = arg.position { - arg.position = parse::ArgumentIs(lookup(s)); + arg.position = parse::ArgumentIs(lookup(s), None); } if let parse::CountIsName(s, _) = arg.format.width { arg.format.width = parse::CountIsParam(lookup(s)); @@ -273,15 +403,48 @@ impl<'a, 'b> Context<'a, 'b> { parse::NextArgument(ref arg) => { // width/precision first, if they have implicit positional // parameters it makes more sense to consume them first. - self.verify_count(arg.format.width); - self.verify_count(arg.format.precision); + self.verify_count( + arg.format.width, + &arg.format.width_span, + PositionalNamedArgType::Width, + ); + self.verify_count( + arg.format.precision, + &arg.format.precision_span, + PositionalNamedArgType::Precision, + ); // argument second, if it's an implicit positional parameter // it's written second, so it should come after width/precision. let pos = match arg.position { - parse::ArgumentIs(i) | parse::ArgumentImplicitlyIs(i) => Exact(i), + parse::ArgumentIs(i, arg_end) => { + self.unused_names_lint.maybe_add_positional_named_arg( + i, + self.args.len(), + i, + PositionalNamedArgType::Arg, + self.curpiece, + arg_end, + &self.names, + ); + + Exact(i) + } + parse::ArgumentImplicitlyIs(i) => { + self.unused_names_lint.maybe_add_positional_named_arg( + i, + self.args.len(), + i, + PositionalNamedArgType::Arg, + self.curpiece, + None, + &self.names, + ); + Exact(i) + } parse::ArgumentNamed(s, span) => { - Named(Symbol::intern(s), InnerSpan::new(span.start, span.end)) + let symbol = Symbol::intern(s); + Named(symbol, InnerSpan::new(span.start, span.end)) } }; @@ -349,10 +512,24 @@ impl<'a, 'b> Context<'a, 'b> { } } - fn verify_count(&mut self, c: parse::Count<'_>) { + fn verify_count( + &mut self, + c: parse::Count<'_>, + inner_span: &Option, + named_arg_type: PositionalNamedArgType, + ) { match c { parse::CountImplied | parse::CountIs(..) => {} parse::CountIsParam(i) => { + self.unused_names_lint.maybe_add_positional_named_arg( + i, + self.args.len(), + i, + named_arg_type, + self.curpiece, + *inner_span, + &self.names, + ); self.verify_arg_type(Exact(i), Count); } parse::CountIsName(s, span) => { @@ -673,7 +850,7 @@ impl<'a, 'b> Context<'a, 'b> { // Build the position let pos = { match arg.position { - parse::ArgumentIs(i) | parse::ArgumentImplicitlyIs(i) => { + parse::ArgumentIs(i, ..) | parse::ArgumentImplicitlyIs(i) => { // Map to index in final generated argument array // in case of multiple types specified let arg_idx = match arg_index_consumed.get_mut(i) { @@ -701,7 +878,7 @@ impl<'a, 'b> Context<'a, 'b> { // track the current argument ourselves. let i = self.curarg; self.curarg += 1; - parse::ArgumentIs(i) + parse::ArgumentIs(i, None) }, format: parse::FormatSpec { fill: arg.format.fill, @@ -971,43 +1148,27 @@ pub fn expand_format_args_nl<'cx>( expand_format_args_impl(ecx, sp, tts, true) } -fn lint_named_arguments_used_positionally( - names: FxHashMap, - cx: &mut Context<'_, '_>, - unverified_pieces: Vec>, -) { - let mut used_argument_names = FxHashSet::<&str>::default(); - for piece in unverified_pieces { - if let rustc_parse_format::Piece::NextArgument(a) = piece { - match a.position { - rustc_parse_format::Position::ArgumentNamed(arg_name, _) => { - used_argument_names.insert(arg_name); - } - _ => {} - }; - if let Count::CountIsName(s, _) = a.format.width { - used_argument_names.insert(s); - } - if let Count::CountIsName(s, _) = a.format.precision { - used_argument_names.insert(s); - } - } - } +fn create_lints_for_named_arguments_used_positionally(cx: &mut Context<'_, '_>) { + for named_arg in &cx.unused_names_lint.positional_named_args { + let arg_span = named_arg.get_span_to_replace(cx); - for (symbol, (index, span)) in names { - if !used_argument_names.contains(symbol.as_str()) { - let msg = format!("named argument `{}` is not used by name", symbol.as_str()); - let arg_span = cx.arg_spans.get(index).copied(); - cx.ecx.buffered_early_lint.push(BufferedEarlyLint { - span: MultiSpan::from_span(span), - msg: msg.clone(), - node_id: ast::CRATE_NODE_ID, - lint_id: LintId::of(&NAMED_ARGUMENTS_USED_POSITIONALLY), - diagnostic: BuiltinLintDiagnostics::NamedArgumentUsedPositionally( - arg_span, span, symbol, - ), - }); - } + let msg = format!("named argument `{}` is not used by name", named_arg.replacement); + let replacement = match named_arg.ty { + PositionalNamedArgType::Arg => named_arg.replacement.to_string(), + _ => named_arg.replacement.to_string() + "$", + }; + + cx.ecx.buffered_early_lint.push(BufferedEarlyLint { + span: MultiSpan::from_span(named_arg.positional_named_arg_span), + msg: msg.clone(), + node_id: ast::CRATE_NODE_ID, + lint_id: LintId::of(&NAMED_ARGUMENTS_USED_POSITIONALLY), + diagnostic: BuiltinLintDiagnostics::NamedArgumentUsedPositionally( + arg_span, + named_arg.positional_named_arg_span, + replacement, + ), + }); } } @@ -1119,11 +1280,6 @@ pub fn expand_preparsed_format_args( let named_pos: FxHashSet = names.values().cloned().map(|(i, _)| i).collect(); - // Clone `names` because `names` in Context get updated by verify_piece, which includes usages - // of the names of named arguments, resulting in incorrect errors if a name argument is used - // but not declared, such as: `println!("x = {x}");` - let named_arguments = names.clone(); - let mut cx = Context { ecx, args, @@ -1148,13 +1304,12 @@ pub fn expand_preparsed_format_args( arg_spans, arg_with_formatting: Vec::new(), is_literal: parser.is_literal, + unused_names_lint: PositionalNamedArgsLint { positional_named_args: vec![] }, }; - // This needs to happen *after* the Parser has consumed all pieces to create all the spans. - // unverified_pieces is used later to check named argument names are used, so clone each piece. + // This needs to happen *after* the Parser has consumed all pieces to create all the spans let pieces = unverified_pieces - .iter() - .cloned() + .into_iter() .map(|mut piece| { cx.verify_piece(&piece); cx.resolve_name_inplace(&mut piece); @@ -1164,7 +1319,7 @@ pub fn expand_preparsed_format_args( let numbered_position_args = pieces.iter().any(|arg: &parse::Piece<'_>| match *arg { parse::String(_) => false, - parse::NextArgument(arg) => matches!(arg.position, parse::Position::ArgumentIs(_)), + parse::NextArgument(arg) => matches!(arg.position, parse::Position::ArgumentIs(..)), }); cx.build_index_map(); @@ -1316,11 +1471,10 @@ pub fn expand_preparsed_format_args( } diag.emit(); - } else if cx.invalid_refs.is_empty() && !named_arguments.is_empty() { + } else if cx.invalid_refs.is_empty() && cx.ecx.sess.err_count() == 0 { // Only check for unused named argument names if there are no other errors to avoid causing // too much noise in output errors, such as when a named argument is entirely unused. - // We also only need to perform this check if there are actually named arguments. - lint_named_arguments_used_positionally(named_arguments, &mut cx, unverified_pieces); + create_lints_for_named_arguments_used_positionally(&mut cx); } cx.into_expr() diff --git a/compiler/rustc_lint/src/context.rs b/compiler/rustc_lint/src/context.rs index b4b472fe2df78..04ac50f1d4806 100644 --- a/compiler/rustc_lint/src/context.rs +++ b/compiler/rustc_lint/src/context.rs @@ -861,10 +861,10 @@ pub trait LintContext: Sized { if let Some(positional_arg) = positional_arg { let msg = format!("this formatting argument uses named argument `{}` by position", name); db.span_label(positional_arg, msg); - db.span_suggestion_verbose( + db.span_suggestion_verbose( positional_arg, "use the named argument by name to avoid ambiguity", - format!("{{{}}}", name), + name, Applicability::MaybeIncorrect, ); } diff --git a/compiler/rustc_lint_defs/src/lib.rs b/compiler/rustc_lint_defs/src/lib.rs index 3872d866dee86..4fd57ed853379 100644 --- a/compiler/rustc_lint_defs/src/lib.rs +++ b/compiler/rustc_lint_defs/src/lib.rs @@ -467,7 +467,7 @@ pub enum BuiltinLintDiagnostics { /// If true, the lifetime will be fully elided. use_span: Option<(Span, bool)>, }, - NamedArgumentUsedPositionally(Option, Span, Symbol), + NamedArgumentUsedPositionally(Option, Span, String), } /// Lints that are buffered up early on in the `Session` before the diff --git a/compiler/rustc_parse_format/src/lib.rs b/compiler/rustc_parse_format/src/lib.rs index 6e7553f5e496b..5deb17b8651b6 100644 --- a/compiler/rustc_parse_format/src/lib.rs +++ b/compiler/rustc_parse_format/src/lib.rs @@ -104,8 +104,8 @@ pub struct FormatSpec<'a> { pub enum Position<'a> { /// The argument is implied to be located at an index ArgumentImplicitlyIs(usize), - /// The argument is located at a specific index given in the format - ArgumentIs(usize), + /// The argument is located at a specific index given in the format, + ArgumentIs(usize, Option), /// The argument has a name. ArgumentNamed(&'a str, InnerSpan), } @@ -113,7 +113,7 @@ pub enum Position<'a> { impl Position<'_> { pub fn index(&self) -> Option { match self { - ArgumentIs(i) | ArgumentImplicitlyIs(i) => Some(*i), + ArgumentIs(i, ..) | ArgumentImplicitlyIs(i) => Some(*i), _ => None, } } @@ -502,8 +502,15 @@ impl<'a> Parser<'a> { /// Returns `Some(parsed_position)` if the position is not implicitly /// consuming a macro argument, `None` if it's the case. fn position(&mut self) -> Option> { + let start_position = self.cur.peek().map(|item| item.0); if let Some(i) = self.integer() { - Some(ArgumentIs(i)) + let inner_span = start_position.and_then(|start| { + self.cur + .peek() + .cloned() + .and_then(|item| Some(self.to_span_index(start).to(self.to_span_index(item.0)))) + }); + Some(ArgumentIs(i, inner_span)) } else { match self.cur.peek() { Some(&(start, c)) if rustc_lexer::is_id_start(c) => { @@ -574,6 +581,10 @@ impl<'a> Parser<'a> { // no '0' flag and '0$' as the width instead. if let Some(end) = self.consume_pos('$') { spec.width = CountIsParam(0); + + if let Some((pos, _)) = self.cur.peek().cloned() { + spec.width_span = Some(self.to_span_index(pos - 2).to(self.to_span_index(pos))); + } havewidth = true; spec.width_span = Some(self.to_span_index(end - 1).to(self.to_span_index(end + 1))); } else { @@ -586,6 +597,7 @@ impl<'a> Parser<'a> { spec.width = w; spec.width_span = sp; } + if let Some(start) = self.consume_pos('.') { if let Some(end) = self.consume_pos('*') { // Resolve `CountIsNextParam`. diff --git a/compiler/rustc_parse_format/src/tests.rs b/compiler/rustc_parse_format/src/tests.rs index 9c305b4996a13..a98f816644bd6 100644 --- a/compiler/rustc_parse_format/src/tests.rs +++ b/compiler/rustc_parse_format/src/tests.rs @@ -62,18 +62,30 @@ fn format_nothing() { } #[test] fn format_position() { - same("{3}", &[NextArgument(Argument { position: ArgumentIs(3), format: fmtdflt() })]); + same( + "{3}", + &[NextArgument(Argument { + position: ArgumentIs(3, Some(InnerSpan { start: 2, end: 3 })), + format: fmtdflt(), + })], + ); } #[test] fn format_position_nothing_else() { - same("{3:}", &[NextArgument(Argument { position: ArgumentIs(3), format: fmtdflt() })]); + same( + "{3:}", + &[NextArgument(Argument { + position: ArgumentIs(3, Some(InnerSpan { start: 2, end: 3 })), + format: fmtdflt(), + })], + ); } #[test] fn format_type() { same( "{3:x}", &[NextArgument(Argument { - position: ArgumentIs(3), + position: ArgumentIs(3, Some(InnerSpan { start: 2, end: 3 })), format: FormatSpec { fill: None, align: AlignUnknown, @@ -93,7 +105,7 @@ fn format_align_fill() { same( "{3:>}", &[NextArgument(Argument { - position: ArgumentIs(3), + position: ArgumentIs(3, Some(InnerSpan { start: 2, end: 3 })), format: FormatSpec { fill: None, align: AlignRight, @@ -110,7 +122,7 @@ fn format_align_fill() { same( "{3:0<}", &[NextArgument(Argument { - position: ArgumentIs(3), + position: ArgumentIs(3, Some(InnerSpan { start: 2, end: 3 })), format: FormatSpec { fill: Some('0'), align: AlignLeft, @@ -127,7 +139,7 @@ fn format_align_fill() { same( "{3:* OnUnimplementedFormatString { } } // `{:1}` and `{}` are not to be used - Position::ArgumentIs(_) | Position::ArgumentImplicitlyIs(_) => { + Position::ArgumentIs(..) | Position::ArgumentImplicitlyIs(_) => { let reported = struct_span_err!( tcx.sess, span, diff --git a/src/test/ui/macros/issue-98466.stderr b/src/test/ui/macros/issue-98466.stderr index ad11d181b6218..4a39dd1440b1f 100644 --- a/src/test/ui/macros/issue-98466.stderr +++ b/src/test/ui/macros/issue-98466.stderr @@ -2,80 +2,80 @@ warning: named argument `_x` is not used by name --> $DIR/issue-98466.rs:7:26 | LL | println!("_x is {}", _x = 5); - | -- ^^ this named argument is only referred to by position in formatting string - | | - | this formatting argument uses named argument `_x` by position + | - ^^ this named argument is only referred to by position in formatting string + | | + | this formatting argument uses named argument `_x` by position | = note: `#[warn(named_arguments_used_positionally)]` on by default help: use the named argument by name to avoid ambiguity | LL | println!("_x is {_x}", _x = 5); - | ~~~~ + | ++ warning: named argument `y` is not used by name --> $DIR/issue-98466.rs:10:26 | LL | println!("_x is {}", y = _x); - | -- ^ this named argument is only referred to by position in formatting string - | | - | this formatting argument uses named argument `y` by position + | - ^ this named argument is only referred to by position in formatting string + | | + | this formatting argument uses named argument `y` by position | help: use the named argument by name to avoid ambiguity | LL | println!("_x is {y}", y = _x); - | ~~~ + | + warning: named argument `y` is not used by name --> $DIR/issue-98466.rs:13:83 | LL | println!("first positional arg {}, second positional arg {}, _x is {}", 1, 2, y = _x); - | -- ^ this named argument is only referred to by position in formatting string - | | - | this formatting argument uses named argument `y` by position + | - ^ this named argument is only referred to by position in formatting string + | | + | this formatting argument uses named argument `y` by position | help: use the named argument by name to avoid ambiguity | LL | println!("first positional arg {}, second positional arg {}, _x is {y}", 1, 2, y = _x); - | ~~~ + | + warning: named argument `_x` is not used by name --> $DIR/issue-98466.rs:19:34 | LL | let _f = format!("_x is {}", _x = 5); - | -- ^^ this named argument is only referred to by position in formatting string - | | - | this formatting argument uses named argument `_x` by position + | - ^^ this named argument is only 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 | let _f = format!("_x is {_x}", _x = 5); - | ~~~~ + | ++ warning: named argument `y` is not used by name --> $DIR/issue-98466.rs:22:34 | LL | let _f = format!("_x is {}", y = _x); - | -- ^ this named argument is only referred to by position in formatting string - | | - | this formatting argument uses named argument `y` by position + | - ^ this named argument is only referred to by position in formatting string + | | + | this formatting argument uses named argument `y` by position | help: use the named argument by name to avoid ambiguity | LL | let _f = format!("_x is {y}", y = _x); - | ~~~ + | + warning: named argument `y` is not used by name --> $DIR/issue-98466.rs:25:91 | LL | let _f = format!("first positional arg {}, second positional arg {}, _x is {}", 1, 2, y = _x); - | -- ^ this named argument is only referred to by position in formatting string - | | - | this formatting argument uses named argument `y` by position + | - ^ this named argument is only referred to by position in formatting string + | | + | this formatting argument uses named argument `y` by position | help: use the named argument by name to avoid ambiguity | LL | let _f = format!("first positional arg {}, second positional arg {}, _x is {y}", 1, 2, y = _x); - | ~~~ + | + warning: 6 warnings emitted diff --git a/src/test/ui/macros/issue-99265.fixed b/src/test/ui/macros/issue-99265.fixed new file mode 100644 index 0000000000000..f3be9c6285d6c --- /dev/null +++ b/src/test/ui/macros/issue-99265.fixed @@ -0,0 +1,139 @@ +// check-pass +// run-rustfix + +fn main() { + println!("{b} {a}", a=1, b=2); + //~^ WARNING named argument `a` is not used by name [named_arguments_used_positionally] + //~| HELP use the named argument by name to avoid ambiguity + + println!("{} {a} {b} {c} {d}", 0, a=1, b=2, c=3, d=4); + //~^ WARNING named argument `a` is not used by name [named_arguments_used_positionally] + //~| WARNING named argument `b` is not used by name [named_arguments_used_positionally] + //~| WARNING named argument `c` is not used by name [named_arguments_used_positionally] + //~| WARNING named argument `d` is not used by name [named_arguments_used_positionally] + //~| HELP use the named argument by name to avoid ambiguity + //~| HELP use the named argument by name to avoid ambiguity + //~| HELP use the named argument by name to avoid ambiguity + //~| HELP use the named argument by name to avoid ambiguity + + println!("Hello {:width$}!", "x", width = 5); + //~^ WARNING named argument `width` is not used by name [named_arguments_used_positionally + //~| HELP use the named argument by name to avoid ambiguity + + println!("Hello {f:width$.precision$}!", f = 0.02f32, width = 5, precision = 2); + //~^ WARNING named argument `width` is not used by name [named_arguments_used_positionally + //~| WARNING named argument `precision` is not used by name [named_arguments_used_positionally] + //~| WARNING named argument `f` is not used by name [named_arguments_used_positionally] + //~| HELP use the named argument by name to avoid ambiguity + //~| HELP use the named argument by name to avoid ambiguity + //~| HELP use the named argument by name to avoid ambiguity + + println!("Hello {f:width$.precision$}!", f = 0.02f32, width = 5, precision = 2); + //~^ WARNING named argument `width` is not used by name [named_arguments_used_positionally + //~| WARNING named argument `precision` is not used by name [named_arguments_used_positionally] + //~| WARNING named argument `f` is not used by name [named_arguments_used_positionally] + //~| HELP use the named argument by name to avoid ambiguity + //~| HELP use the named argument by name to avoid ambiguity + //~| HELP use the named argument by name to avoid ambiguity + + println!( + "{}, Hello {f:width$.precision$} {g:width2$.precision2$}! {f}", + //~^ HELP use the named argument by name to avoid ambiguity + //~| HELP use the named argument by name to avoid ambiguity + //~| HELP use the named argument by name to avoid ambiguity + //~| HELP use the named argument by name to avoid ambiguity + //~| HELP use the named argument by name to avoid ambiguity + //~| HELP use the named argument by name to avoid ambiguity + //~| HELP use the named argument by name to avoid ambiguity + 1, + f = 0.02f32, + //~^ WARNING named argument `f` is not used by name [named_arguments_used_positionally] + //~| WARNING named argument `f` is not used by name [named_arguments_used_positionally] + width = 5, + //~^ WARNING named argument `width` is not used by name [named_arguments_used_positionally + precision = 2, + //~^ WARNING named argument `precision` is not used by name [named_arguments_used_positionally] + g = 0.02f32, + //~^ WARNING named argument `g` is not used by name [named_arguments_used_positionally] + width2 = 5, + //~^ WARNING named argument `width2` is not used by name [named_arguments_used_positionally + precision2 = 2 + //~^ WARNING named argument `precision2` is not used by name [named_arguments_used_positionally] + ); + + println!("Hello {f:0.1}!", f = 0.02f32); + //~^ WARNING named argument `f` is not used by name [named_arguments_used_positionally] + //~| HELP use the named argument by name to avoid ambiguity + + println!("Hello {f:0.1}!", f = 0.02f32); + //~^ WARNING named argument `f` is not used by name [named_arguments_used_positionally] + //~| HELP use the named argument by name to avoid ambiguity + + println!("Hello {f:width$.precision$}!", f = 0.02f32, width = 5, precision = 2); + + let width = 5; + let precision = 2; + println!("Hello {f:width$.precision$}!", f = 0.02f32); + + let val = 5; + println!("{v:v$}", v = val); + //~^ WARNING named argument `v` is not used by name [named_arguments_used_positionally] + //~| WARNING named argument `v` is not used by name [named_arguments_used_positionally] + //~| HELP use the named argument by name to avoid ambiguity + //~| HELP use the named argument by name to avoid ambiguity + println!("{v:v$}", v = val); + //~^ WARNING named argument `v` is not used by name [named_arguments_used_positionally] + //~| WARNING named argument `v` is not used by name [named_arguments_used_positionally] + //~| HELP use the named argument by name to avoid ambiguity + //~| HELP use the named argument by name to avoid ambiguity + println!("{v:v$.v$}", v = val); + //~^ WARNING named argument `v` is not used by name [named_arguments_used_positionally] + //~| WARNING named argument `v` is not used by name [named_arguments_used_positionally] + //~| WARNING named argument `v` is not used by name [named_arguments_used_positionally] + //~| HELP use the named argument by name to avoid ambiguity + //~| HELP use the named argument by name to avoid ambiguity + //~| HELP use the named argument by name to avoid ambiguity + println!("{v:v$.v$}", v = val); + //~^ WARNING named argument `v` is not used by name [named_arguments_used_positionally] + //~| WARNING named argument `v` is not used by name [named_arguments_used_positionally] + //~| WARNING named argument `v` is not used by name [named_arguments_used_positionally] + //~| HELP use the named argument by name to avoid ambiguity + //~| HELP use the named argument by name to avoid ambiguity + //~| HELP use the named argument by name to avoid ambiguity + + println!("{a} {a} {a}", a = 1); + //~^ WARNING named argument `a` is not used by name [named_arguments_used_positionally] + //~| WARNING named argument `a` is not used by name [named_arguments_used_positionally] + //~| HELP use the named argument by name to avoid ambiguity + //~| HELP use the named argument by name to avoid ambiguity + + println!("aaaaaaaaaaaaaaa\ + {a:b$.c$}", + //~^ HELP use the named argument by name to avoid ambiguity + //~| HELP use the named argument by name to avoid ambiguity + //~| HELP use the named argument by name to avoid ambiguity + a = 1.0, b = 1, c = 2, + //~^ WARNING named argument `a` is not used by name [named_arguments_used_positionally] + //~| WARNING named argument `b` is not used by name [named_arguments_used_positionally] + //~| WARNING named argument `c` is not used by name [named_arguments_used_positionally] + ); + + println!("aaaaaaaaaaaaaaa\ + {a:b$.c$}", + //~^ HELP use the named argument by name to avoid ambiguity + //~| HELP use the named argument by name to avoid ambiguity + //~| HELP use the named argument by name to avoid ambiguity + a = 1.0, b = 1, c = 2, + //~^ WARNING named argument `a` is not used by name [named_arguments_used_positionally] + //~| WARNING named argument `b` is not used by name [named_arguments_used_positionally] + //~| WARNING named argument `c` is not used by name [named_arguments_used_positionally] + ); + + println!("{{{x:width$.precision$}}}", x = 1.0, width = 3, precision = 2); + //~^ WARNING named argument `x` is not used by name [named_arguments_used_positionally] + //~| WARNING named argument `width` is not used by name [named_arguments_used_positionally] + //~| WARNING named argument `precision` is not used by name [named_arguments_used_positionally] + //~| HELP use the named argument by name to avoid ambiguity + //~| HELP use the named argument by name to avoid ambiguity + //~| HELP use the named argument by name to avoid ambiguity +} diff --git a/src/test/ui/macros/issue-99265.rs b/src/test/ui/macros/issue-99265.rs new file mode 100644 index 0000000000000..e7cf608765b0d --- /dev/null +++ b/src/test/ui/macros/issue-99265.rs @@ -0,0 +1,139 @@ +// check-pass +// run-rustfix + +fn main() { + println!("{b} {}", a=1, b=2); + //~^ WARNING named argument `a` is not used by name [named_arguments_used_positionally] + //~| HELP use the named argument by name to avoid ambiguity + + println!("{} {} {} {} {}", 0, a=1, b=2, c=3, d=4); + //~^ WARNING named argument `a` is not used by name [named_arguments_used_positionally] + //~| WARNING named argument `b` is not used by name [named_arguments_used_positionally] + //~| WARNING named argument `c` is not used by name [named_arguments_used_positionally] + //~| WARNING named argument `d` is not used by name [named_arguments_used_positionally] + //~| HELP use the named argument by name to avoid ambiguity + //~| HELP use the named argument by name to avoid ambiguity + //~| HELP use the named argument by name to avoid ambiguity + //~| HELP use the named argument by name to avoid ambiguity + + println!("Hello {:1$}!", "x", width = 5); + //~^ WARNING named argument `width` is not used by name [named_arguments_used_positionally + //~| HELP use the named argument by name to avoid ambiguity + + println!("Hello {:1$.2$}!", f = 0.02f32, width = 5, precision = 2); + //~^ WARNING named argument `width` is not used by name [named_arguments_used_positionally + //~| WARNING named argument `precision` is not used by name [named_arguments_used_positionally] + //~| WARNING named argument `f` is not used by name [named_arguments_used_positionally] + //~| HELP use the named argument by name to avoid ambiguity + //~| HELP use the named argument by name to avoid ambiguity + //~| HELP use the named argument by name to avoid ambiguity + + println!("Hello {0:1$.2$}!", f = 0.02f32, width = 5, precision = 2); + //~^ WARNING named argument `width` is not used by name [named_arguments_used_positionally + //~| WARNING named argument `precision` is not used by name [named_arguments_used_positionally] + //~| WARNING named argument `f` is not used by name [named_arguments_used_positionally] + //~| HELP use the named argument by name to avoid ambiguity + //~| HELP use the named argument by name to avoid ambiguity + //~| HELP use the named argument by name to avoid ambiguity + + println!( + "{}, Hello {1:2$.3$} {4:5$.6$}! {1}", + //~^ HELP use the named argument by name to avoid ambiguity + //~| HELP use the named argument by name to avoid ambiguity + //~| HELP use the named argument by name to avoid ambiguity + //~| HELP use the named argument by name to avoid ambiguity + //~| HELP use the named argument by name to avoid ambiguity + //~| HELP use the named argument by name to avoid ambiguity + //~| HELP use the named argument by name to avoid ambiguity + 1, + f = 0.02f32, + //~^ WARNING named argument `f` is not used by name [named_arguments_used_positionally] + //~| WARNING named argument `f` is not used by name [named_arguments_used_positionally] + width = 5, + //~^ WARNING named argument `width` is not used by name [named_arguments_used_positionally + precision = 2, + //~^ WARNING named argument `precision` is not used by name [named_arguments_used_positionally] + g = 0.02f32, + //~^ WARNING named argument `g` is not used by name [named_arguments_used_positionally] + width2 = 5, + //~^ WARNING named argument `width2` is not used by name [named_arguments_used_positionally + precision2 = 2 + //~^ WARNING named argument `precision2` is not used by name [named_arguments_used_positionally] + ); + + println!("Hello {:0.1}!", f = 0.02f32); + //~^ WARNING named argument `f` is not used by name [named_arguments_used_positionally] + //~| HELP use the named argument by name to avoid ambiguity + + println!("Hello {0:0.1}!", f = 0.02f32); + //~^ WARNING named argument `f` is not used by name [named_arguments_used_positionally] + //~| HELP use the named argument by name to avoid ambiguity + + println!("Hello {f:width$.precision$}!", f = 0.02f32, width = 5, precision = 2); + + let width = 5; + let precision = 2; + println!("Hello {f:width$.precision$}!", f = 0.02f32); + + let val = 5; + println!("{:0$}", v = val); + //~^ WARNING named argument `v` is not used by name [named_arguments_used_positionally] + //~| WARNING named argument `v` is not used by name [named_arguments_used_positionally] + //~| HELP use the named argument by name to avoid ambiguity + //~| HELP use the named argument by name to avoid ambiguity + println!("{0:0$}", v = val); + //~^ WARNING named argument `v` is not used by name [named_arguments_used_positionally] + //~| WARNING named argument `v` is not used by name [named_arguments_used_positionally] + //~| HELP use the named argument by name to avoid ambiguity + //~| HELP use the named argument by name to avoid ambiguity + println!("{:0$.0$}", v = val); + //~^ WARNING named argument `v` is not used by name [named_arguments_used_positionally] + //~| WARNING named argument `v` is not used by name [named_arguments_used_positionally] + //~| WARNING named argument `v` is not used by name [named_arguments_used_positionally] + //~| HELP use the named argument by name to avoid ambiguity + //~| HELP use the named argument by name to avoid ambiguity + //~| HELP use the named argument by name to avoid ambiguity + println!("{0:0$.0$}", v = val); + //~^ WARNING named argument `v` is not used by name [named_arguments_used_positionally] + //~| WARNING named argument `v` is not used by name [named_arguments_used_positionally] + //~| WARNING named argument `v` is not used by name [named_arguments_used_positionally] + //~| HELP use the named argument by name to avoid ambiguity + //~| HELP use the named argument by name to avoid ambiguity + //~| HELP use the named argument by name to avoid ambiguity + + println!("{} {a} {0}", a = 1); + //~^ WARNING named argument `a` is not used by name [named_arguments_used_positionally] + //~| WARNING named argument `a` is not used by name [named_arguments_used_positionally] + //~| HELP use the named argument by name to avoid ambiguity + //~| HELP use the named argument by name to avoid ambiguity + + println!("aaaaaaaaaaaaaaa\ + {:1$.2$}", + //~^ HELP use the named argument by name to avoid ambiguity + //~| HELP use the named argument by name to avoid ambiguity + //~| HELP use the named argument by name to avoid ambiguity + a = 1.0, b = 1, c = 2, + //~^ WARNING named argument `a` is not used by name [named_arguments_used_positionally] + //~| WARNING named argument `b` is not used by name [named_arguments_used_positionally] + //~| WARNING named argument `c` is not used by name [named_arguments_used_positionally] + ); + + println!("aaaaaaaaaaaaaaa\ + {0:1$.2$}", + //~^ HELP use the named argument by name to avoid ambiguity + //~| HELP use the named argument by name to avoid ambiguity + //~| HELP use the named argument by name to avoid ambiguity + a = 1.0, b = 1, c = 2, + //~^ WARNING named argument `a` is not used by name [named_arguments_used_positionally] + //~| WARNING named argument `b` is not used by name [named_arguments_used_positionally] + //~| WARNING named argument `c` is not used by name [named_arguments_used_positionally] + ); + + println!("{{{:1$.2$}}}", x = 1.0, width = 3, precision = 2); + //~^ WARNING named argument `x` is not used by name [named_arguments_used_positionally] + //~| WARNING named argument `width` is not used by name [named_arguments_used_positionally] + //~| WARNING named argument `precision` is not used by name [named_arguments_used_positionally] + //~| HELP use the named argument by name to avoid ambiguity + //~| HELP use the named argument by name to avoid ambiguity + //~| HELP use the named argument by name to avoid ambiguity +} diff --git a/src/test/ui/macros/issue-99265.stderr b/src/test/ui/macros/issue-99265.stderr new file mode 100644 index 0000000000000..0798ad8dc517c --- /dev/null +++ b/src/test/ui/macros/issue-99265.stderr @@ -0,0 +1,562 @@ +warning: named argument `a` is not used by name + --> $DIR/issue-99265.rs:5:24 + | +LL | println!("{b} {}", a=1, b=2); + | - ^ this named argument is only referred to by position in formatting string + | | + | this formatting argument uses named argument `a` by position + | + = note: `#[warn(named_arguments_used_positionally)]` on by default +help: use the named argument by name to avoid ambiguity + | +LL | println!("{b} {a}", a=1, b=2); + | + + +warning: named argument `a` is not used by name + --> $DIR/issue-99265.rs:9:35 + | +LL | println!("{} {} {} {} {}", 0, a=1, b=2, c=3, d=4); + | - ^ this named argument is only 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} {} {} {}", 0, a=1, b=2, c=3, d=4); + | + + +warning: named argument `b` is not used by name + --> $DIR/issue-99265.rs:9:40 + | +LL | println!("{} {} {} {} {}", 0, a=1, b=2, c=3, d=4); + | - ^ this named argument is only referred to by position in formatting string + | | + | this formatting argument uses named argument `b` by position + | +help: use the named argument by name to avoid ambiguity + | +LL | println!("{} {} {b} {} {}", 0, a=1, b=2, c=3, d=4); + | + + +warning: named argument `c` is not used by name + --> $DIR/issue-99265.rs:9:45 + | +LL | println!("{} {} {} {} {}", 0, a=1, b=2, c=3, d=4); + | - ^ this named argument is only referred to by position in formatting string + | | + | this formatting argument uses named argument `c` by position + | +help: use the named argument by name to avoid ambiguity + | +LL | println!("{} {} {} {c} {}", 0, a=1, b=2, c=3, d=4); + | + + +warning: named argument `d` is not used by name + --> $DIR/issue-99265.rs:9:50 + | +LL | println!("{} {} {} {} {}", 0, a=1, b=2, c=3, d=4); + | - ^ this named argument is only referred to by position in formatting string + | | + | this formatting argument uses named argument `d` by position + | +help: use the named argument by name to avoid ambiguity + | +LL | println!("{} {} {} {} {d}", 0, a=1, b=2, c=3, d=4); + | + + +warning: named argument `width` is not used by name + --> $DIR/issue-99265.rs:19:35 + | +LL | println!("Hello {:1$}!", "x", width = 5); + | -- ^^^^^ this named argument is only 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$}!", "x", width = 5); + | ~~~~~~ + +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 only 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 `precision` is not used by name + --> $DIR/issue-99265.rs:23:57 + | +LL | println!("Hello {:1$.2$}!", f = 0.02f32, width = 5, precision = 2); + | -- ^^^^^^^^^ this named argument is only referred to by position in formatting string + | | + | this formatting argument uses named argument `precision$` by position + | +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 + | +LL | println!("Hello {:1$.2$}!", f = 0.02f32, width = 5, precision = 2); + | - ^ this named argument is only 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 only 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 + | +LL | println!("Hello {0:1$.2$}!", f = 0.02f32, width = 5, precision = 2); + | -- ^^^^^^^^^ this named argument is only referred to by position in formatting string + | | + | this formatting argument uses named argument `precision$` by position + | +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 + | +LL | println!("Hello {0:1$.2$}!", f = 0.02f32, width = 5, precision = 2); + | - ^ this named argument is only 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:52:9 + | +LL | "{}, Hello {1:2$.3$} {4:5$.6$}! {1}", + | -- this formatting argument uses named argument `width$` by position +... +LL | width = 5, + | ^^^^^ this named argument is only 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 `precision` is not used by name + --> $DIR/issue-99265.rs:54:9 + | +LL | "{}, Hello {1:2$.3$} {4:5$.6$}! {1}", + | -- this formatting argument uses named argument `precision$` by position +... +LL | precision = 2, + | ^^^^^^^^^ this named argument is only referred to by position in formatting string + | +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 + | +LL | "{}, Hello {1:2$.3$} {4:5$.6$}! {1}", + | - this formatting argument uses named argument `f` by position +... +LL | f = 0.02f32, + | ^ this named argument is only 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 only 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}", + | ~~~~~~~ + +warning: named argument `precision2` is not used by name + --> $DIR/issue-99265.rs:60:9 + | +LL | "{}, Hello {1:2$.3$} {4:5$.6$}! {1}", + | -- this formatting argument uses named argument `precision2$` by position +... +LL | precision2 = 2 + | ^^^^^^^^^^ this named argument is only referred to by position in formatting string + | +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 + | +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 only 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}", + | ~ + +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 +... +LL | f = 0.02f32, + | ^ this named argument is only referred to by position in formatting string + | +help: use the named argument by name to avoid ambiguity + | +LL | "{}, Hello {1:2$.3$} {4:5$.6$}! {f}", + | ~ + +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 only 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 `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 only 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 only 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$}", v = val); + | ~~ + +warning: named argument `v` is not used by name + --> $DIR/issue-99265.rs:79:23 + | +LL | println!("{:0$}", v = val); + | - ^ this named argument is only 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 + | +LL | println!("{0:0$}", v = val); + | -- ^ this named argument is only 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$}", 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 only 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 only 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 only 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$}", 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 only 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 only 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 + | +LL | println!("{0:0$.0$}", v = val); + | -- ^ this named argument is only 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:0$.v$}", 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 only 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 `a` is not used by name + --> $DIR/issue-99265.rs:104:28 + | +LL | println!("{} {a} {0}", a = 1); + | - ^ this named argument is only 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} {0}", a = 1); + | + + +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 only 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 + | +LL | {:1$.2$}", + | -- this formatting argument uses named argument `b$` by position +... +LL | a = 1.0, b = 1, c = 2, + | ^ this named argument is only referred to by position in formatting string + | +help: use the named argument by name to avoid ambiguity + | +LL | {:b$.2$}", + | ~~ + +warning: named argument `c` is not used by name + --> $DIR/issue-99265.rs:115:30 + | +LL | {:1$.2$}", + | -- this formatting argument uses named argument `c$` by position +... +LL | a = 1.0, b = 1, c = 2, + | ^ this named argument is only referred to by position in formatting string + | +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 + | +LL | {:1$.2$}", + | - this formatting argument uses named argument `a` by position +... +LL | a = 1.0, b = 1, c = 2, + | ^ this named argument is only referred to by position in formatting string + | +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 only 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 + | +LL | {0:1$.2$}", + | -- this formatting argument uses named argument `c$` by position +... +LL | a = 1.0, b = 1, c = 2, + | ^ this named argument is only referred to by position in formatting string + | +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 + | +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 only referred to by position in formatting string + | +help: use the named argument by name to avoid ambiguity + | +LL | {a:1$.2$}", + | ~ + +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 only 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!("{{{:width$.2$}}}", x = 1.0, width = 3, precision = 2); + | ~~~~~~ + +warning: named argument `precision` is not used by name + --> $DIR/issue-99265.rs:132:50 + | +LL | println!("{{{:1$.2$}}}", x = 1.0, width = 3, precision = 2); + | -- ^^^^^^^^^ this named argument is only referred to by position in formatting string + | | + | this formatting argument uses named argument `precision$` by position + | +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 + | +LL | println!("{{{:1$.2$}}}", x = 1.0, width = 3, precision = 2); + | - ^ this named argument is only 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!("{{{x:1$.2$}}}", x = 1.0, width = 3, precision = 2); + | + + +warning: 42 warnings emitted + diff --git a/src/tools/clippy/clippy_lints/src/write.rs b/src/tools/clippy/clippy_lints/src/write.rs index 08b8894752011..3a99d1b417fee 100644 --- a/src/tools/clippy/clippy_lints/src/write.rs +++ b/src/tools/clippy/clippy_lints/src/write.rs @@ -441,7 +441,7 @@ impl SimpleFormatArgs { }; match arg.position { - ArgumentIs(n) | ArgumentImplicitlyIs(n) => { + ArgumentIs(n, _) | ArgumentImplicitlyIs(n) => { if self.unnamed.len() <= n { // Use a dummy span to mark all unseen arguments. self.unnamed.resize_with(n, || vec![DUMMY_SP]);