Point at incorrect named arg in format string
This commit is contained in:
parent
38abca8c2d
commit
42306591b9
2 changed files with 27 additions and 10 deletions
|
@ -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);
|
||||||
|
|
|
@ -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
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue