Skip to content

Commit 21a012a

Browse files
estebankJohnHeitmann
authored andcommitted
Point at correct span for arguments in format strings
When a format string has escaped whitespace characters format arguments were shifted by one per each escaped character. Account for these escaped characters when synthesizing the spans. Fix rust-lang#55155.
1 parent 92e3a35 commit 21a012a

File tree

4 files changed

+15
-6
lines changed

4 files changed

+15
-6
lines changed

src/libfmt_macros/lib.rs

+3-4
Original file line numberDiff line numberDiff line change
@@ -144,7 +144,7 @@ pub struct Parser<'a> {
144144
/// `Some(raw count)` when the string is "raw", used to position spans correctly
145145
style: Option<usize>,
146146
/// Start and end byte offset of every successfully parsed argument
147-
pub arg_places: Vec<(usize, usize)>,
147+
pub arg_places: Vec<(SpanIndex, SpanIndex)>,
148148
/// Characters that need to be shifted
149149
skips: Vec<usize>,
150150
/// Span offset of the last opening brace seen, used for error reporting
@@ -154,7 +154,7 @@ pub struct Parser<'a> {
154154
}
155155

156156
#[derive(Clone, Copy, Debug)]
157-
pub struct SpanIndex(usize);
157+
pub struct SpanIndex(pub usize);
158158

159159
impl SpanIndex {
160160
pub fn unwrap(self) -> usize {
@@ -166,7 +166,6 @@ impl<'a> Iterator for Parser<'a> {
166166
type Item = Piece<'a>;
167167

168168
fn next(&mut self) -> Option<Piece<'a>> {
169-
let raw = self.raw();
170169
if let Some(&(pos, c)) = self.cur.peek() {
171170
match c {
172171
'{' => {
@@ -180,7 +179,7 @@ impl<'a> Iterator for Parser<'a> {
180179
} else {
181180
let arg = self.argument();
182181
if let Some(arg_pos) = self.must_consume('}').map(|end| {
183-
(pos + raw + 1, end + raw + 2)
182+
(self.to_span_index(pos), self.to_span_index(end + 1))
184183
}) {
185184
self.arg_places.push(arg_pos);
186185
}

src/libsyntax_ext/format.rs

+3-1
Original file line numberDiff line numberDiff line change
@@ -860,7 +860,9 @@ pub fn expand_preparsed_format_args(ecx: &mut ExtCtxt,
860860
}
861861

862862
let arg_spans = parser.arg_places.iter()
863-
.map(|&(start, end)| fmt.span.from_inner_byte_pos(start, end))
863+
.map(|&(parse::SpanIndex(start), parse::SpanIndex(end))| {
864+
fmt.span.from_inner_byte_pos(start, end)
865+
})
864866
.collect();
865867

866868
let mut cx = Context {

src/test/ui/fmt/format-string-error-2.rs

+2
Original file line numberDiff line numberDiff line change
@@ -67,4 +67,6 @@ raw { \n
6767
asdf}
6868
", asdf=1);
6969
//~^^ ERROR invalid format string
70+
println!("\t{}");
71+
//~^ ERROR 1 positional argument in format string
7072
}

src/test/ui/fmt/format-string-error-2.stderr

+7-1
Original file line numberDiff line numberDiff line change
@@ -133,5 +133,11 @@ LL | asdf}
133133
|
134134
= note: if you intended to print `{`, you can escape it using `{{`
135135

136-
error: aborting due to 13 previous errors
136+
error: 1 positional argument in format string, but no arguments were given
137+
--> $DIR/format-string-error-2.rs:70:17
138+
|
139+
LL | println!("/t{}");
140+
| ^^
141+
142+
error: aborting due to 14 previous errors
137143

0 commit comments

Comments
 (0)