Skip to content

Commit 5e75001

Browse files
committed
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 #55155.
1 parent a1bad57 commit 5e75001

File tree

4 files changed

+15
-6
lines changed

4 files changed

+15
-6
lines changed

src/libfmt_macros/lib.rs

Lines changed: 3 additions & 4 deletions
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

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -861,7 +861,9 @@ pub fn expand_preparsed_format_args(ecx: &mut ExtCtxt,
861861
}
862862

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

867869
let mut cx = Context {

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

Lines changed: 2 additions & 0 deletions
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

Lines changed: 7 additions & 1 deletion
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)