1
Fork 0

Point at incorrect named arg in format string

This commit is contained in:
Esteban Küber 2018-07-23 00:01:17 -07:00
parent 38abca8c2d
commit 42306591b9
2 changed files with 27 additions and 10 deletions

View file

@ -111,8 +111,10 @@ struct Context<'a, 'b: 'a> {
/// still existed in this phase of processing. /// still existed in this phase of processing.
/// Used only for `all_pieces_simple` tracking in `build_piece`. /// Used only for `all_pieces_simple` tracking in `build_piece`.
curarg: usize, curarg: usize,
curpiece: usize,
/// Keep track of invalid references to positional arguments /// Keep track of invalid references to positional arguments
invalid_refs: Vec<usize>, invalid_refs: Vec<usize>,
arg_spans: Vec<Span>,
} }
/// Parses the arguments from the given list of tokens, returning None /// Parses the arguments from the given list of tokens, returning None
@ -235,6 +237,7 @@ impl<'a, 'b> Context<'a, 'b> {
let ty = Placeholder(arg.format.ty.to_string()); let ty = Placeholder(arg.format.ty.to_string());
self.verify_arg_type(pos, ty); self.verify_arg_type(pos, ty);
self.curpiece += 1;
} }
} }
} }
@ -347,7 +350,9 @@ impl<'a, 'b> Context<'a, 'b> {
Some(e) => *e, Some(e) => *e,
None => { None => {
let msg = format!("there is no argument named `{}`", name); let msg = format!("there is no argument named `{}`", name);
self.ecx.span_err(self.fmtsp, &msg[..]); let sp = *self.arg_spans.get(self.curpiece).unwrap_or(&self.fmtsp);
let mut err = self.ecx.struct_span_err(sp, &msg[..]);
err.emit();
return; return;
} }
}; };
@ -773,6 +778,7 @@ pub fn expand_preparsed_format_args(ecx: &mut ExtCtxt,
arg_unique_types, arg_unique_types,
names, names,
curarg: 0, curarg: 0,
curpiece: 0,
arg_index_map: Vec::new(), arg_index_map: Vec::new(),
count_args: Vec::new(), count_args: Vec::new(),
count_positions: HashMap::new(), count_positions: HashMap::new(),
@ -785,6 +791,7 @@ pub fn expand_preparsed_format_args(ecx: &mut ExtCtxt,
macsp, macsp,
fmtsp: fmt.span, fmtsp: fmt.span,
invalid_refs: Vec::new(), invalid_refs: Vec::new(),
arg_spans: Vec::new(),
}; };
let fmt_str = &*fmt.node.0.as_str(); let fmt_str = &*fmt.node.0.as_str();
@ -793,12 +800,22 @@ pub fn expand_preparsed_format_args(ecx: &mut ExtCtxt,
ast::StrStyle::Raw(raw) => Some(raw as usize), ast::StrStyle::Raw(raw) => Some(raw as usize),
}; };
let mut parser = parse::Parser::new(fmt_str, str_style); let mut parser = parse::Parser::new(fmt_str, str_style);
let mut unverified_pieces = vec![];
let mut pieces = vec![]; let mut pieces = vec![];
while let Some(mut piece) = parser.next() { while let Some(piece) = parser.next() {
if !parser.errors.is_empty() { if !parser.errors.is_empty() {
break; break;
} }
unverified_pieces.push(piece);
}
cx.arg_spans = parser.arg_places.iter()
.map(|&(start, end)| fmt.span.from_inner_byte_pos(start, end))
.collect();
// This needs to happen *after* the Parser has consumed all pieces to create all the spans
for mut piece in unverified_pieces {
cx.verify_piece(&piece); cx.verify_piece(&piece);
cx.resolve_name_inplace(&mut piece); cx.resolve_name_inplace(&mut piece);
pieces.push(piece); pieces.push(piece);

View file

@ -57,22 +57,22 @@ LL | format!("{name} {value} {} {} {} {} {} {}", 0, name=1, value=2);
= note: positional arguments are zero-based = note: positional arguments are zero-based
error: there is no argument named `foo` error: there is no argument named `foo`
--> $DIR/ifmt-bad-arg.rs:37:13 --> $DIR/ifmt-bad-arg.rs:37:17
| |
LL | format!("{} {foo} {} {bar} {}", 1, 2, 3); LL | format!("{} {foo} {} {bar} {}", 1, 2, 3);
| ^^^^^^^^^^^^^^^^^^^^^^ | ^^^^^
error: there is no argument named `bar` error: there is no argument named `bar`
--> $DIR/ifmt-bad-arg.rs:37:13 --> $DIR/ifmt-bad-arg.rs:37:26
| |
LL | format!("{} {foo} {} {bar} {}", 1, 2, 3); LL | format!("{} {foo} {} {bar} {}", 1, 2, 3);
| ^^^^^^^^^^^^^^^^^^^^^^ | ^^^^^
error: there is no argument named `foo` error: there is no argument named `foo`
--> $DIR/ifmt-bad-arg.rs:41:13 --> $DIR/ifmt-bad-arg.rs:41:14
| |
LL | format!("{foo}"); //~ ERROR: no argument named `foo` LL | format!("{foo}"); //~ ERROR: no argument named `foo`
| ^^^^^^^ | ^^^^^
error: multiple unused formatting arguments error: multiple unused formatting arguments
--> $DIR/ifmt-bad-arg.rs:42:17 --> $DIR/ifmt-bad-arg.rs:42:17
@ -139,10 +139,10 @@ LL | format!("", foo=1, 2); //~ ERROR: positional arguments cannot
| ^ | ^
error: there is no argument named `valueb` error: there is no argument named `valueb`
--> $DIR/ifmt-bad-arg.rs:55:13 --> $DIR/ifmt-bad-arg.rs:55:23
| |
LL | format!("{valuea} {valueb}", valuea=5, valuec=7); LL | format!("{valuea} {valueb}", valuea=5, valuec=7);
| ^^^^^^^^^^^^^^^^^^^ | ^^^^^^^^
error: named argument never used error: named argument never used
--> $DIR/ifmt-bad-arg.rs:55:51 --> $DIR/ifmt-bad-arg.rs:55:51