Skip to content

Commit

Permalink
Point at incorrect named arg in format string
Browse files Browse the repository at this point in the history
  • Loading branch information
Esteban Küber committed Jul 23, 2018
1 parent 38abca8 commit 4230659
Show file tree
Hide file tree
Showing 2 changed files with 27 additions and 10 deletions.
21 changes: 19 additions & 2 deletions src/libsyntax_ext/format.rs
Original file line number Diff line number Diff line change
Expand Up @@ -111,8 +111,10 @@ struct Context<'a, 'b: 'a> {
/// still existed in this phase of processing.
/// Used only for `all_pieces_simple` tracking in `build_piece`.
curarg: usize,
curpiece: usize,
/// Keep track of invalid references to positional arguments
invalid_refs: Vec<usize>,
arg_spans: Vec<Span>,
}

/// Parses the arguments from the given list of tokens, returning None
Expand Down Expand Up @@ -235,6 +237,7 @@ impl<'a, 'b> Context<'a, 'b> {

let ty = Placeholder(arg.format.ty.to_string());
self.verify_arg_type(pos, ty);
self.curpiece += 1;
}
}
}
Expand Down Expand Up @@ -347,7 +350,9 @@ impl<'a, 'b> Context<'a, 'b> {
Some(e) => *e,
None => {
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;
}
};
Expand Down Expand Up @@ -773,6 +778,7 @@ pub fn expand_preparsed_format_args(ecx: &mut ExtCtxt,
arg_unique_types,
names,
curarg: 0,
curpiece: 0,
arg_index_map: Vec::new(),
count_args: Vec::new(),
count_positions: HashMap::new(),
Expand All @@ -785,6 +791,7 @@ pub fn expand_preparsed_format_args(ecx: &mut ExtCtxt,
macsp,
fmtsp: fmt.span,
invalid_refs: Vec::new(),
arg_spans: Vec::new(),
};

let fmt_str = &*fmt.node.0.as_str();
Expand All @@ -793,12 +800,22 @@ pub fn expand_preparsed_format_args(ecx: &mut ExtCtxt,
ast::StrStyle::Raw(raw) => Some(raw as usize),
};
let mut parser = parse::Parser::new(fmt_str, str_style);
let mut unverified_pieces = vec![];
let mut pieces = vec![];

while let Some(mut piece) = parser.next() {
while let Some(piece) = parser.next() {
if !parser.errors.is_empty() {
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.resolve_name_inplace(&mut piece);
pieces.push(piece);
Expand Down
16 changes: 8 additions & 8 deletions src/test/ui/ifmt-bad-arg.stderr
Original file line number Diff line number Diff line change
Expand Up @@ -57,22 +57,22 @@ 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
--> $DIR/ifmt-bad-arg.rs:37:17
|
LL | format!("{} {foo} {} {bar} {}", 1, 2, 3);
| ^^^^^^^^^^^^^^^^^^^^^^
| ^^^^^

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);
| ^^^^^^^^^^^^^^^^^^^^^^
| ^^^^^

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`
| ^^^^^^^
| ^^^^^

error: multiple unused formatting arguments
--> $DIR/ifmt-bad-arg.rs:42:17
Expand Down Expand Up @@ -139,10 +139,10 @@ LL | format!("", foo=1, 2); //~ ERROR: positional arguments cannot
| ^

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);
| ^^^^^^^^^^^^^^^^^^^
| ^^^^^^^^

error: named argument never used
--> $DIR/ifmt-bad-arg.rs:55:51
Expand Down

0 comments on commit 4230659

Please sign in to comment.