style: Option<usize>,
/// How many newlines have been seen in the string so far, to adjust the error spans
seen_newlines: usize,
+ pub arg_places: Vec<(usize, usize)>,
}
impl<'a> Iterator for Parser<'a> {
if self.consume('{') {
Some(String(self.string(pos + 1)))
} else {
- let ret = Some(NextArgument(self.argument()));
- self.must_consume('}');
- ret
+ let mut arg = self.argument();
+ if let Some(arg_pos) = self.must_consume('}').map(|end| {
+ (pos + raw + 1, end + raw + 2)
+ }) {
+ self.arg_places.push(arg_pos);
+ }
+ Some(NextArgument(arg))
}
}
'}' => {
curarg: 0,
style,
seen_newlines: 0,
+ arg_places: vec![],
}
}
/// Forces consumption of the specified character. If the character is not
/// found, an error is emitted.
- fn must_consume(&mut self, c: char) {
+ fn must_consume(&mut self, c: char) -> Option<usize> {
self.ws();
let raw = self.style.unwrap_or(0);
if let Some(&(pos, maybe)) = self.cur.peek() {
if c == maybe {
self.cur.next();
+ Some(pos)
} else {
let pos = pos + padding + 1;
self.err(format!("expected `{:?}`, found `{:?}`", c, maybe),
format!("expected `{}`", c),
pos,
pos);
+ None
}
} else {
let msg = format!("expected `{:?}` but string was terminated", c);
} else {
self.err(msg, format!("expected `{:?}`", c), pos, pos);
}
+ None
}
}
use syntax::parse::token;
use syntax::ptr::P;
use syntax::symbol::Symbol;
-use syntax_pos::{Span, DUMMY_SP};
+use syntax_pos::{Span, MultiSpan, DUMMY_SP};
use syntax::tokenstream;
use std::collections::{HashMap, HashSet};
/// errors for the case where all arguments are positional and for when
/// there are named arguments or numbered positional arguments in the
/// format string.
- fn report_invalid_references(&self, numbered_position_args: bool) {
+ fn report_invalid_references(&self, numbered_position_args: bool, arg_places: &[(usize, usize)]) {
let mut e;
- let mut refs: Vec<String> = self.invalid_refs
- .iter()
- .map(|r| r.to_string())
- .collect();
+ let sps = arg_places.iter()
+ .map(|&(start, end)| self.fmtsp.from_inner_byte_pos(start, end))
+ .collect::<Vec<_>>();
+ let sp = MultiSpan::from_spans(sps);
+ let mut refs: Vec<_> = self.invalid_refs
+ .iter()
+ .map(|r| r.to_string())
+ .collect();
if self.names.is_empty() && !numbered_position_args {
- e = self.ecx.mut_span_err(self.fmtsp,
+ e = self.ecx.mut_span_err(sp,
&format!("{} positional argument{} in format string, but {}",
self.pieces.len(),
if self.pieces.len() > 1 { "s" } else { "" },
self.describe_num_args()));
} else {
let arg_list = match refs.len() {
- 1 => format!("argument {}", refs.pop().unwrap()),
- _ => format!("arguments {head} and {tail}",
- tail=refs.pop().unwrap(),
+ 1 => {
+ let reg = refs.pop().unwrap();
+ format!("argument {}", reg)
+ },
+ _ => {
+ let reg = refs.pop().unwrap();
+ format!("arguments {head} and {tail}",
+ tail=reg,
head=refs.join(", "))
+ }
};
- e = self.ecx.mut_span_err(self.fmtsp,
+ e = self.ecx.mut_span_err(sp,
&format!("invalid reference to positional {} ({})",
arg_list,
self.describe_num_args()));
}
if cx.invalid_refs.len() >= 1 {
- cx.report_invalid_references(numbered_position_args);
+ cx.report_invalid_references(numbered_position_args, &parser.arg_places);
}
// Make sure that all arguments were used and all arguments have types.
+++ /dev/null
-// Copyright 2013 The Rust Project Developers. See the COPYRIGHT
-// file at the top-level directory of this distribution and at
-// http://rust-lang.org/COPYRIGHT.
-//
-// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
-// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
-// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
-// option. This file may not be copied, modified, or distributed
-// except according to those terms.
-
-fn main() {
- // bad arguments to the format! call
-
- // bad number of arguments, see #44954 (originally #15780)
-
- format!("{}");
- //~^ ERROR: 1 positional argument in format string, but no arguments were given
-
- format!("{1}", 1);
- //~^ ERROR: invalid reference to positional argument 1 (there is 1 argument)
- //~^^ ERROR: argument never used
-
- format!("{} {}");
- //~^ ERROR: 2 positional arguments in format string, but no arguments were given
-
- format!("{0} {1}", 1);
- //~^ ERROR: invalid reference to positional argument 1 (there is 1 argument)
-
- format!("{0} {1} {2}", 1, 2);
- //~^ 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)
- format!("{name} {value} {} {} {} {} {} {}", 0, name=1, value=2);
- //~^ ERROR: invalid reference to positional arguments 3, 4 and 5 (there are 3 arguments)
-
- format!("{} {foo} {} {bar} {}", 1, 2, 3);
- //~^ ERROR: there is no argument named `foo`
- //~^^ ERROR: there is no argument named `bar`
-
- format!("{foo}"); //~ ERROR: no argument named `foo`
- format!("", 1, 2); //~ ERROR: multiple unused formatting arguments
- format!("{}", 1, 2); //~ ERROR: argument never used
- format!("{1}", 1, 2); //~ ERROR: argument never used
- format!("{}", 1, foo=2); //~ ERROR: named argument never used
- format!("{foo}", 1, foo=2); //~ ERROR: argument never used
- format!("", foo=2); //~ ERROR: named argument never used
- format!("{} {}", 1, 2, foo=1, bar=2); //~ ERROR: multiple unused formatting arguments
-
- format!("{foo}", foo=1, foo=2); //~ ERROR: duplicate argument
- format!("", foo=1, 2); //~ ERROR: positional arguments cannot follow
-
- // bad named arguments, #35082
-
- format!("{valuea} {valueb}", valuea=5, valuec=7);
- //~^ ERROR there is no argument named `valueb`
- //~^^ ERROR named argument never used
-
- // bad syntax of the format string
-
- format!("{"); //~ ERROR: expected `'}'` but string was terminated
-
- format!("foo } bar"); //~ ERROR: unmatched `}` found
- format!("foo }"); //~ ERROR: unmatched `}` found
-
- format!("foo %s baz", "bar"); //~ ERROR: argument never used
-}
--- /dev/null
+// Copyright 2013 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+fn main() {
+ // bad arguments to the format! call
+
+ // bad number of arguments, see #44954 (originally #15780)
+
+ format!("{}");
+ //~^ ERROR: 1 positional argument in format string, but no arguments were given
+
+ format!("{1}", 1);
+ //~^ ERROR: invalid reference to positional argument 1 (there is 1 argument)
+ //~^^ ERROR: argument never used
+
+ format!("{} {}");
+ //~^ ERROR: 2 positional arguments in format string, but no arguments were given
+
+ format!("{0} {1}", 1);
+ //~^ ERROR: invalid reference to positional argument 1 (there is 1 argument)
+
+ format!("{0} {1} {2}", 1, 2);
+ //~^ 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)
+ format!("{name} {value} {} {} {} {} {} {}", 0, name=1, value=2);
+ //~^ ERROR: invalid reference to positional arguments 3, 4 and 5 (there are 3 arguments)
+
+ format!("{} {foo} {} {bar} {}", 1, 2, 3);
+ //~^ ERROR: there is no argument named `foo`
+ //~^^ ERROR: there is no argument named `bar`
+
+ format!("{foo}"); //~ ERROR: no argument named `foo`
+ format!("", 1, 2); //~ ERROR: multiple unused formatting arguments
+ format!("{}", 1, 2); //~ ERROR: argument never used
+ format!("{1}", 1, 2); //~ ERROR: argument never used
+ format!("{}", 1, foo=2); //~ ERROR: named argument never used
+ format!("{foo}", 1, foo=2); //~ ERROR: argument never used
+ format!("", foo=2); //~ ERROR: named argument never used
+ format!("{} {}", 1, 2, foo=1, bar=2); //~ ERROR: multiple unused formatting arguments
+
+ format!("{foo}", foo=1, foo=2); //~ ERROR: duplicate argument
+ format!("", foo=1, 2); //~ ERROR: positional arguments cannot follow
+
+ // bad named arguments, #35082
+
+ format!("{valuea} {valueb}", valuea=5, valuec=7);
+ //~^ ERROR there is no argument named `valueb`
+ //~^^ ERROR named argument never used
+
+ // bad syntax of the format string
+
+ format!("{"); //~ ERROR: expected `'}'` but string was terminated
+
+ format!("foo } bar"); //~ ERROR: unmatched `}` found
+ format!("foo }"); //~ ERROR: unmatched `}` found
+
+ format!("foo %s baz", "bar"); //~ ERROR: argument never used
+}
--- /dev/null
+error: 1 positional argument in format string, but no arguments were given
+ --> $DIR/ifmt-bad-arg.rs:16:14
+ |
+LL | format!("{}");
+ | ^^
+
+error: invalid reference to positional argument 1 (there is 1 argument)
+ --> $DIR/ifmt-bad-arg.rs:19:14
+ |
+LL | format!("{1}", 1);
+ | ^^^
+ |
+ = note: positional arguments are zero-based
+
+error: argument never used
+ --> $DIR/ifmt-bad-arg.rs:19:20
+ |
+LL | format!("{1}", 1);
+ | ^
+
+error: 2 positional arguments in format string, but no arguments were given
+ --> $DIR/ifmt-bad-arg.rs:23:14
+ |
+LL | format!("{} {}");
+ | ^^ ^^
+
+error: invalid reference to positional argument 1 (there is 1 argument)
+ --> $DIR/ifmt-bad-arg.rs:26:14
+ |
+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:29:14
+ |
+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:32: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:34:14
+ |
+LL | format!("{name} {value} {} {} {} {} {} {}", 0, name=1, value=2);
+ | ^^^^^^ ^^^^^^^ ^^ ^^ ^^ ^^ ^^ ^^
+ |
+ = note: positional arguments are zero-based
+
+error: there is no argument named `foo`
+ --> $DIR/ifmt-bad-arg.rs:37:13
+ |
+LL | format!("{} {foo} {} {bar} {}", 1, 2, 3);
+ | ^^^^^^^^^^^^^^^^^^^^^^
+
+error: there is no argument named `bar`
+ --> $DIR/ifmt-bad-arg.rs:37:13
+ |
+LL | format!("{} {foo} {} {bar} {}", 1, 2, 3);
+ | ^^^^^^^^^^^^^^^^^^^^^^
+
+error: there is no argument named `foo`
+ --> $DIR/ifmt-bad-arg.rs:41:13
+ |
+LL | format!("{foo}"); //~ ERROR: no argument named `foo`
+ | ^^^^^^^
+
+error: multiple unused formatting arguments
+ --> $DIR/ifmt-bad-arg.rs:42:17
+ |
+LL | format!("", 1, 2); //~ ERROR: multiple unused formatting arguments
+ | -- ^ ^
+ | |
+ | multiple missing formatting arguments
+
+error: argument never used
+ --> $DIR/ifmt-bad-arg.rs:43:22
+ |
+LL | format!("{}", 1, 2); //~ ERROR: argument never used
+ | ^
+
+error: argument never used
+ --> $DIR/ifmt-bad-arg.rs:44:20
+ |
+LL | format!("{1}", 1, 2); //~ ERROR: argument never used
+ | ^
+
+error: named argument never used
+ --> $DIR/ifmt-bad-arg.rs:45:26
+ |
+LL | format!("{}", 1, foo=2); //~ ERROR: named argument never used
+ | ^
+
+error: argument never used
+ --> $DIR/ifmt-bad-arg.rs:46:22
+ |
+LL | format!("{foo}", 1, foo=2); //~ ERROR: argument never used
+ | ^
+
+error: named argument never used
+ --> $DIR/ifmt-bad-arg.rs:47:21
+ |
+LL | format!("", foo=2); //~ ERROR: named argument never used
+ | ^
+
+error: multiple unused formatting arguments
+ --> $DIR/ifmt-bad-arg.rs:48:32
+ |
+LL | format!("{} {}", 1, 2, foo=1, bar=2); //~ ERROR: multiple unused formatting arguments
+ | ------- ^ ^
+ | |
+ | multiple missing formatting arguments
+
+error: duplicate argument named `foo`
+ --> $DIR/ifmt-bad-arg.rs:50:33
+ |
+LL | format!("{foo}", foo=1, foo=2); //~ ERROR: duplicate argument
+ | ^
+ |
+note: previously here
+ --> $DIR/ifmt-bad-arg.rs:50:26
+ |
+LL | format!("{foo}", foo=1, foo=2); //~ ERROR: duplicate argument
+ | ^
+
+error: expected ident, positional arguments cannot follow named arguments
+ --> $DIR/ifmt-bad-arg.rs:51:24
+ |
+LL | format!("", foo=1, 2); //~ ERROR: positional arguments cannot follow
+ | ^
+
+error: there is no argument named `valueb`
+ --> $DIR/ifmt-bad-arg.rs:55:13
+ |
+LL | format!("{valuea} {valueb}", valuea=5, valuec=7);
+ | ^^^^^^^^^^^^^^^^^^^
+
+error: named argument never used
+ --> $DIR/ifmt-bad-arg.rs:55:51
+ |
+LL | format!("{valuea} {valueb}", valuea=5, valuec=7);
+ | ^
+
+error: invalid format string: expected `'}'` but string was terminated
+ --> $DIR/ifmt-bad-arg.rs:61:15
+ |
+LL | format!("{"); //~ ERROR: expected `'}'` but string was terminated
+ | ^ expected `'}'` in format string
+ |
+ = note: if you intended to print `{`, you can escape it using `{{`
+
+error: invalid format string: unmatched `}` found
+ --> $DIR/ifmt-bad-arg.rs:63:18
+ |
+LL | format!("foo } bar"); //~ ERROR: unmatched `}` found
+ | ^ unmatched `}` in format string
+ |
+ = note: if you intended to print `}`, you can escape it using `}}`
+
+error: invalid format string: unmatched `}` found
+ --> $DIR/ifmt-bad-arg.rs:64:18
+ |
+LL | format!("foo }"); //~ ERROR: unmatched `}` found
+ | ^ unmatched `}` in format string
+ |
+ = note: if you intended to print `}`, you can escape it using `}}`
+
+error: argument never used
+ --> $DIR/ifmt-bad-arg.rs:66:27
+ |
+LL | format!("foo %s baz", "bar"); //~ ERROR: argument never used
+ | ^^^^^
+ |
+ = help: `%s` should be written as `{}`
+ = note: printf formatting not supported; see the documentation for `std::fmt`
+
+error: aborting due to 26 previous errors
+
error: 1 positional argument in format string, but no arguments were given
- --> $DIR/macro-backtrace-println.rs:24:30
+ --> $DIR/macro-backtrace-println.rs:24:31
|
LL | ($fmt:expr) => (myprint!(concat!($fmt, "/n"))); //~ ERROR no arguments were given
- | ^^^^^^^^^^^^^^^^^^^
+ | ^^
...
LL | myprintln!("{}");
| ----------------- in this macro invocation