diff --git a/compiler/rustc_builtin_macros/src/asm.rs b/compiler/rustc_builtin_macros/src/asm.rs index 1a6e56947916..ac37c4973d87 100644 --- a/compiler/rustc_builtin_macros/src/asm.rs +++ b/compiler/rustc_builtin_macros/src/asm.rs @@ -700,11 +700,11 @@ fn expand_preparsed_asm(ecx: &mut ExtCtxt<'_>, args: AsmArgs) -> Option match args.named_args.get(&name) { + parse::ArgumentNamed(name, span) => match args.named_args.get(&name) { Some(&idx) => Some(idx), None => { let msg = format!("there is no argument named `{}`", name); - ecx.struct_span_err(span, &msg).emit(); + ecx.struct_span_err(template_span.from_inner(span), &msg).emit(); None } }, diff --git a/compiler/rustc_builtin_macros/src/format.rs b/compiler/rustc_builtin_macros/src/format.rs index 584fbd1b605c..6141d00f6971 100644 --- a/compiler/rustc_builtin_macros/src/format.rs +++ b/compiler/rustc_builtin_macros/src/format.rs @@ -11,7 +11,7 @@ use rustc_errors::{pluralize, Applicability, DiagnosticBuilder}; use rustc_expand::base::{self, *}; use rustc_parse_format as parse; use rustc_span::symbol::{sym, Ident, Symbol}; -use rustc_span::{MultiSpan, Span}; +use rustc_span::{InnerSpan, MultiSpan, Span}; use smallvec::SmallVec; use std::borrow::Cow; @@ -26,7 +26,7 @@ enum ArgumentType { enum Position { Exact(usize), Capture(usize), - Named(Symbol), + Named(Symbol, InnerSpan), } struct Context<'a, 'b> { @@ -247,13 +247,13 @@ impl<'a, 'b> Context<'a, 'b> { match *p { parse::String(_) => {} parse::NextArgument(ref mut arg) => { - if let parse::ArgumentNamed(s) = arg.position { + if let parse::ArgumentNamed(s, _) = arg.position { arg.position = parse::ArgumentIs(lookup(s)); } - if let parse::CountIsName(s) = arg.format.width { + if let parse::CountIsName(s, _) = arg.format.width { arg.format.width = parse::CountIsParam(lookup(s)); } - if let parse::CountIsName(s) = arg.format.precision { + if let parse::CountIsName(s, _) = arg.format.precision { arg.format.precision = parse::CountIsParam(lookup(s)); } } @@ -276,7 +276,7 @@ impl<'a, 'b> Context<'a, 'b> { // 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::ArgumentNamed(s) => Named(s), + parse::ArgumentNamed(s, span) => Named(s, span), }; let ty = Placeholder(match arg.format.ty { @@ -346,8 +346,8 @@ impl<'a, 'b> Context<'a, 'b> { parse::CountIsParam(i) => { self.verify_arg_type(Exact(i), Count); } - parse::CountIsName(s) => { - self.verify_arg_type(Named(s), Count); + parse::CountIsName(s, span) => { + self.verify_arg_type(Named(s, span), Count); } } } @@ -533,7 +533,7 @@ impl<'a, 'b> Context<'a, 'b> { } } - Named(name) => { + Named(name, span) => { match self.names.get(&name) { Some(&idx) => { // Treat as positional arg. @@ -548,7 +548,7 @@ impl<'a, 'b> Context<'a, 'b> { self.arg_types.push(Vec::new()); self.arg_unique_types.push(Vec::new()); let span = if self.is_literal { - *self.arg_spans.get(self.curpiece).unwrap_or(&self.fmtsp) + self.fmtsp.from_inner(span) } else { self.fmtsp }; @@ -559,7 +559,7 @@ impl<'a, 'b> Context<'a, 'b> { } else { let msg = format!("there is no argument named `{}`", name); let sp = if self.is_literal { - *self.arg_spans.get(self.curpiece).unwrap_or(&self.fmtsp) + self.fmtsp.from_inner(span) } else { self.fmtsp }; @@ -629,7 +629,7 @@ impl<'a, 'b> Context<'a, 'b> { } parse::CountImplied => count(sym::Implied, None), // should never be the case, names are already resolved - parse::CountIsName(_) => panic!("should never happen"), + parse::CountIsName(..) => panic!("should never happen"), } } @@ -676,7 +676,7 @@ impl<'a, 'b> Context<'a, 'b> { // should never be the case, because names are already // resolved. - parse::ArgumentNamed(_) => panic!("should never happen"), + parse::ArgumentNamed(..) => panic!("should never happen"), } }; diff --git a/compiler/rustc_parse_format/src/lib.rs b/compiler/rustc_parse_format/src/lib.rs index 9d653de910fe..a6a2cbc277c2 100644 --- a/compiler/rustc_parse_format/src/lib.rs +++ b/compiler/rustc_parse_format/src/lib.rs @@ -95,7 +95,7 @@ pub enum Position { /// The argument is located at a specific index given in the format ArgumentIs(usize), /// The argument has a name. - ArgumentNamed(Symbol), + ArgumentNamed(Symbol, InnerSpan), } impl Position { @@ -147,7 +147,7 @@ pub enum Count { /// The count is specified explicitly. CountIs(usize), /// The count is specified by the argument with the given name. - CountIsName(Symbol), + CountIsName(Symbol, InnerSpan), /// The count is specified by the argument at the given index. CountIsParam(usize), /// The count is implied and cannot be explicitly specified. @@ -494,8 +494,11 @@ impl<'a> Parser<'a> { Some(ArgumentIs(i)) } else { match self.cur.peek() { - Some(&(_, c)) if rustc_lexer::is_id_start(c) => { - Some(ArgumentNamed(Symbol::intern(self.word()))) + Some(&(start, c)) if rustc_lexer::is_id_start(c) => { + let word = self.word(); + let end = start + word.len(); + let span = self.to_span_index(start).to(self.to_span_index(end)); + Some(ArgumentNamed(Symbol::intern(word), span)) } // This is an `ArgumentNext`. @@ -662,8 +665,9 @@ impl<'a> Parser<'a> { if word.is_empty() { self.cur = tmp; (CountImplied, None) - } else if self.consume('$') { - (CountIsName(Symbol::intern(word)), None) + } else if let Some(end) = self.consume_pos('$') { + let span = self.to_span_index(start + 1).to(self.to_span_index(end)); + (CountIsName(Symbol::intern(word), span), None) } else { self.cur = tmp; (CountImplied, None) diff --git a/compiler/rustc_parse_format/src/tests.rs b/compiler/rustc_parse_format/src/tests.rs index b7693a85ad95..6c960fdc72bf 100644 --- a/compiler/rustc_parse_format/src/tests.rs +++ b/compiler/rustc_parse_format/src/tests.rs @@ -221,8 +221,8 @@ fn format_counts() { fill: None, align: AlignUnknown, flags: 0, - precision: CountIsName(Symbol::intern("b")), - width: CountIsName(Symbol::intern("a")), + precision: CountIsName(Symbol::intern("b"), InnerSpan::new(6, 7)), + width: CountIsName(Symbol::intern("a"), InnerSpan::new(4, 4)), precision_span: None, width_span: None, ty: "?", diff --git a/compiler/rustc_trait_selection/src/traits/on_unimplemented.rs b/compiler/rustc_trait_selection/src/traits/on_unimplemented.rs index bdf677a63b63..b05dbbe898a4 100644 --- a/compiler/rustc_trait_selection/src/traits/on_unimplemented.rs +++ b/compiler/rustc_trait_selection/src/traits/on_unimplemented.rs @@ -309,23 +309,23 @@ impl<'tcx> OnUnimplementedFormatString { Piece::String(_) => (), // Normal string, no need to check it Piece::NextArgument(a) => match a.position { // `{Self}` is allowed - Position::ArgumentNamed(s) if s == kw::SelfUpper => (), + Position::ArgumentNamed(s, _) if s == kw::SelfUpper => (), // `{ThisTraitsName}` is allowed - Position::ArgumentNamed(s) if s == name => (), + Position::ArgumentNamed(s, _) if s == name => (), // `{from_method}` is allowed - Position::ArgumentNamed(s) if s == sym::from_method => (), + Position::ArgumentNamed(s, _) if s == sym::from_method => (), // `{from_desugaring}` is allowed - Position::ArgumentNamed(s) if s == sym::from_desugaring => (), + Position::ArgumentNamed(s, _) if s == sym::from_desugaring => (), // `{ItemContext}` is allowed - Position::ArgumentNamed(s) if s == sym::ItemContext => (), + Position::ArgumentNamed(s, _) if s == sym::ItemContext => (), // `{integral}` and `{integer}` and `{float}` are allowed - Position::ArgumentNamed(s) + Position::ArgumentNamed(s, _) if s == sym::integral || s == sym::integer_ || s == sym::float => { () } // So is `{A}` if A is a type parameter - Position::ArgumentNamed(s) => { + Position::ArgumentNamed(s, _) => { match generics.params.iter().find(|param| param.name == s) { Some(_) => (), None => { @@ -392,7 +392,7 @@ impl<'tcx> OnUnimplementedFormatString { .map(|p| match p { Piece::String(s) => s, Piece::NextArgument(a) => match a.position { - Position::ArgumentNamed(s) => match generic_map.get(&s) { + Position::ArgumentNamed(s, _) => match generic_map.get(&s) { Some(val) => val, None if s == name => &trait_str, None => { diff --git a/src/test/ui/asm/bad-template.aarch64_mirunsafeck.stderr b/src/test/ui/asm/bad-template.aarch64_mirunsafeck.stderr index 3b1d922a7f75..11c4e01f4186 100644 --- a/src/test/ui/asm/bad-template.aarch64_mirunsafeck.stderr +++ b/src/test/ui/asm/bad-template.aarch64_mirunsafeck.stderr @@ -23,10 +23,10 @@ LL | asm!("{1}", in(reg) foo); = help: if this argument is intentionally unused, consider using it in an asm comment: `"/* {0} */"` error: there is no argument named `a` - --> $DIR/bad-template.rs:36:15 + --> $DIR/bad-template.rs:36:16 | LL | asm!("{a}"); - | ^^^ + | ^ error: invalid reference to argument at index 0 --> $DIR/bad-template.rs:38:15 @@ -123,10 +123,10 @@ LL | global_asm!("{1}", const FOO); = help: if this argument is intentionally unused, consider using it in an asm comment: `"/* {0} */"` error: there is no argument named `a` - --> $DIR/bad-template.rs:63:14 + --> $DIR/bad-template.rs:63:15 | LL | global_asm!("{a}"); - | ^^^ + | ^ error: invalid reference to argument at index 0 --> $DIR/bad-template.rs:65:14 diff --git a/src/test/ui/asm/bad-template.aarch64_thirunsafeck.stderr b/src/test/ui/asm/bad-template.aarch64_thirunsafeck.stderr index 3b1d922a7f75..11c4e01f4186 100644 --- a/src/test/ui/asm/bad-template.aarch64_thirunsafeck.stderr +++ b/src/test/ui/asm/bad-template.aarch64_thirunsafeck.stderr @@ -23,10 +23,10 @@ LL | asm!("{1}", in(reg) foo); = help: if this argument is intentionally unused, consider using it in an asm comment: `"/* {0} */"` error: there is no argument named `a` - --> $DIR/bad-template.rs:36:15 + --> $DIR/bad-template.rs:36:16 | LL | asm!("{a}"); - | ^^^ + | ^ error: invalid reference to argument at index 0 --> $DIR/bad-template.rs:38:15 @@ -123,10 +123,10 @@ LL | global_asm!("{1}", const FOO); = help: if this argument is intentionally unused, consider using it in an asm comment: `"/* {0} */"` error: there is no argument named `a` - --> $DIR/bad-template.rs:63:14 + --> $DIR/bad-template.rs:63:15 | LL | global_asm!("{a}"); - | ^^^ + | ^ error: invalid reference to argument at index 0 --> $DIR/bad-template.rs:65:14 diff --git a/src/test/ui/asm/bad-template.x86_64_mirunsafeck.stderr b/src/test/ui/asm/bad-template.x86_64_mirunsafeck.stderr index 3b69186f1e18..c198e0a69dde 100644 --- a/src/test/ui/asm/bad-template.x86_64_mirunsafeck.stderr +++ b/src/test/ui/asm/bad-template.x86_64_mirunsafeck.stderr @@ -23,10 +23,10 @@ LL | asm!("{1}", in(reg) foo); = help: if this argument is intentionally unused, consider using it in an asm comment: `"/* {0} */"` error: there is no argument named `a` - --> $DIR/bad-template.rs:36:15 + --> $DIR/bad-template.rs:36:16 | LL | asm!("{a}"); - | ^^^ + | ^ error: invalid reference to argument at index 0 --> $DIR/bad-template.rs:38:15 @@ -123,10 +123,10 @@ LL | global_asm!("{1}", const FOO); = help: if this argument is intentionally unused, consider using it in an asm comment: `"/* {0} */"` error: there is no argument named `a` - --> $DIR/bad-template.rs:63:14 + --> $DIR/bad-template.rs:63:15 | LL | global_asm!("{a}"); - | ^^^ + | ^ error: invalid reference to argument at index 0 --> $DIR/bad-template.rs:65:14 diff --git a/src/test/ui/asm/bad-template.x86_64_thirunsafeck.stderr b/src/test/ui/asm/bad-template.x86_64_thirunsafeck.stderr index 3b69186f1e18..c198e0a69dde 100644 --- a/src/test/ui/asm/bad-template.x86_64_thirunsafeck.stderr +++ b/src/test/ui/asm/bad-template.x86_64_thirunsafeck.stderr @@ -23,10 +23,10 @@ LL | asm!("{1}", in(reg) foo); = help: if this argument is intentionally unused, consider using it in an asm comment: `"/* {0} */"` error: there is no argument named `a` - --> $DIR/bad-template.rs:36:15 + --> $DIR/bad-template.rs:36:16 | LL | asm!("{a}"); - | ^^^ + | ^ error: invalid reference to argument at index 0 --> $DIR/bad-template.rs:38:15 @@ -123,10 +123,10 @@ LL | global_asm!("{1}", const FOO); = help: if this argument is intentionally unused, consider using it in an asm comment: `"/* {0} */"` error: there is no argument named `a` - --> $DIR/bad-template.rs:63:14 + --> $DIR/bad-template.rs:63:15 | LL | global_asm!("{a}"); - | ^^^ + | ^ error: invalid reference to argument at index 0 --> $DIR/bad-template.rs:65:14 diff --git a/src/test/ui/fmt/format-args-capture-issue-93378.stderr b/src/test/ui/fmt/format-args-capture-issue-93378.stderr index 588541044fe1..b8e2b2afb386 100644 --- a/src/test/ui/fmt/format-args-capture-issue-93378.stderr +++ b/src/test/ui/fmt/format-args-capture-issue-93378.stderr @@ -10,10 +10,10 @@ error: invalid reference to positional argument 0 (no arguments were given) --> $DIR/format-args-capture-issue-93378.rs:9:23 | 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 are 3 arguments expected + | this parameter corresponds to the precision flag | = note: positional arguments are zero-based = note: for information about formatting flags, visit https://doc.rust-lang.org/std/fmt/index.html diff --git a/src/test/ui/fmt/format-args-capture-issue-94010.rs b/src/test/ui/fmt/format-args-capture-issue-94010.rs new file mode 100644 index 000000000000..bd03e9c93ae2 --- /dev/null +++ b/src/test/ui/fmt/format-args-capture-issue-94010.rs @@ -0,0 +1,7 @@ +fn main() { + const FOO: i32 = 123; + println!("{foo:X}"); + //~^ ERROR: cannot find value `foo` in this scope + println!("{:.foo$}", 0); + //~^ ERROR: cannot find value `foo` in this scope +} diff --git a/src/test/ui/fmt/format-args-capture-issue-94010.stderr b/src/test/ui/fmt/format-args-capture-issue-94010.stderr new file mode 100644 index 000000000000..ed90dc855360 --- /dev/null +++ b/src/test/ui/fmt/format-args-capture-issue-94010.stderr @@ -0,0 +1,20 @@ +error[E0425]: cannot find value `foo` in this scope + --> $DIR/format-args-capture-issue-94010.rs:3:16 + | +LL | const FOO: i32 = 123; + | --------------------- similarly named constant `FOO` defined here +LL | println!("{foo:X}"); + | ^^^ help: a constant with a similar name exists (notice the capitalization): `FOO` + +error[E0425]: cannot find value `foo` in this scope + --> $DIR/format-args-capture-issue-94010.rs:5:18 + | +LL | const FOO: i32 = 123; + | --------------------- similarly named constant `FOO` defined here +... +LL | println!("{:.foo$}", 0); + | ^^^ help: a constant with a similar name exists (notice the capitalization): `FOO` + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0425`. diff --git a/src/test/ui/fmt/format-args-capture-missing-variables.stderr b/src/test/ui/fmt/format-args-capture-missing-variables.stderr index d53c206003f9..d980e7be273e 100644 --- a/src/test/ui/fmt/format-args-capture-missing-variables.stderr +++ b/src/test/ui/fmt/format-args-capture-missing-variables.stderr @@ -7,40 +7,40 @@ LL | format!("{valuea} {valueb}", valuea=5, valuec=7); | formatting specifier missing error[E0425]: cannot find value `foo` in this scope - --> $DIR/format-args-capture-missing-variables.rs:2:17 + --> $DIR/format-args-capture-missing-variables.rs:2:18 | LL | format!("{} {foo} {} {bar} {}", 1, 2, 3); - | ^^^^^ not found in this scope + | ^^^ not found in this scope error[E0425]: cannot find value `bar` in this scope - --> $DIR/format-args-capture-missing-variables.rs:2:26 + --> $DIR/format-args-capture-missing-variables.rs:2:27 | LL | format!("{} {foo} {} {bar} {}", 1, 2, 3); - | ^^^^^ not found in this scope + | ^^^ not found in this scope error[E0425]: cannot find value `foo` in this scope - --> $DIR/format-args-capture-missing-variables.rs:6:14 + --> $DIR/format-args-capture-missing-variables.rs:6:15 | LL | format!("{foo}"); - | ^^^^^ not found in this scope + | ^^^ not found in this scope error[E0425]: cannot find value `valueb` in this scope - --> $DIR/format-args-capture-missing-variables.rs:8:23 + --> $DIR/format-args-capture-missing-variables.rs:8:24 | LL | format!("{valuea} {valueb}", valuea=5, valuec=7); - | ^^^^^^^^ not found in this scope + | ^^^^^^ not found in this scope error[E0425]: cannot find value `foo` in this scope - --> $DIR/format-args-capture-missing-variables.rs:14:9 + --> $DIR/format-args-capture-missing-variables.rs:14:10 | LL | {foo} - | ^^^^^ not found in this scope + | ^^^ not found in this scope error[E0425]: cannot find value `foo` in this scope - --> $DIR/format-args-capture-missing-variables.rs:19:13 + --> $DIR/format-args-capture-missing-variables.rs:19:14 | LL | panic!("{foo} {bar}", bar=1); - | ^^^^^ not found in this scope + | ^^^ not found in this scope error: aborting due to 7 previous errors diff --git a/src/test/ui/fmt/ifmt-bad-arg.stderr b/src/test/ui/fmt/ifmt-bad-arg.stderr index acc4e95f5bb7..3f1f1006713b 100644 --- a/src/test/ui/fmt/ifmt-bad-arg.stderr +++ b/src/test/ui/fmt/ifmt-bad-arg.stderr @@ -263,34 +263,34 @@ LL | println!("{:.*}"); = note: for information about formatting flags, visit https://doc.rust-lang.org/std/fmt/index.html error[E0425]: cannot find value `foo` in this scope - --> $DIR/ifmt-bad-arg.rs:27:17 + --> $DIR/ifmt-bad-arg.rs:27:18 | LL | format!("{} {foo} {} {bar} {}", 1, 2, 3); - | ^^^^^ not found in this scope + | ^^^ not found in this scope error[E0425]: cannot find value `bar` in this scope - --> $DIR/ifmt-bad-arg.rs:27:26 + --> $DIR/ifmt-bad-arg.rs:27:27 | LL | format!("{} {foo} {} {bar} {}", 1, 2, 3); - | ^^^^^ not found in this scope + | ^^^ not found in this scope error[E0425]: cannot find value `foo` in this scope - --> $DIR/ifmt-bad-arg.rs:31:14 + --> $DIR/ifmt-bad-arg.rs:31:15 | LL | format!("{foo}"); - | ^^^^^ not found in this scope + | ^^^ not found in this scope error[E0425]: cannot find value `valueb` in this scope - --> $DIR/ifmt-bad-arg.rs:45:23 + --> $DIR/ifmt-bad-arg.rs:45:24 | LL | format!("{valuea} {valueb}", valuea=5, valuec=7); - | ^^^^^^^^ not found in this scope + | ^^^^^^ not found in this scope error[E0425]: cannot find value `foo` in this scope - --> $DIR/ifmt-bad-arg.rs:60:9 + --> $DIR/ifmt-bad-arg.rs:60:10 | LL | {foo} - | ^^^^^ not found in this scope + | ^^^ not found in this scope error[E0308]: mismatched types --> $DIR/ifmt-bad-arg.rs:78:32 diff --git a/src/tools/clippy/clippy_lints/src/write.rs b/src/tools/clippy/clippy_lints/src/write.rs index b0044695ea8a..1fa6301ebd73 100644 --- a/src/tools/clippy/clippy_lints/src/write.rs +++ b/src/tools/clippy/clippy_lints/src/write.rs @@ -453,7 +453,7 @@ impl SimpleFormatArgs { } } }, - ArgumentNamed(n) => { + ArgumentNamed(n, _) => { if let Some(x) = self.named.iter_mut().find(|x| x.0 == n) { match x.1.as_slice() { // A non-empty format string has been seen already.