Skip to content

Commit b1c357e

Browse files
Introduce InnerSpan abstraction
This should be used when trying to get at subsets of a larger span, especially when the larger span is not available in the code attempting to work with those subsets (especially common in the fmt_macros crate). This is usually a good replacement for (BytePos, BytePos) and (usize, usize) tuples. This commit also removes from_inner_byte_pos, since it took usize arguments, which is error prone.
1 parent a859440 commit b1c357e

File tree

6 files changed

+82
-75
lines changed

6 files changed

+82
-75
lines changed

src/libfmt_macros/lib.rs

+42-47
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,16 @@ use std::str;
2424
use std::string;
2525
use std::iter;
2626

27-
use syntax_pos::Symbol;
27+
use syntax_pos::{InnerSpan, Symbol};
28+
29+
#[derive(Copy, Clone)]
30+
struct InnerOffset(usize);
31+
32+
impl InnerOffset {
33+
fn to(self, end: InnerOffset) -> InnerSpan {
34+
InnerSpan::new(self.0, end.0)
35+
}
36+
}
2837

2938
/// A piece is a portion of the format string which represents the next part
3039
/// to emit. These are emitted as a stream by the `Parser` class.
@@ -136,9 +145,8 @@ pub struct ParseError {
136145
pub description: string::String,
137146
pub note: Option<string::String>,
138147
pub label: string::String,
139-
pub start: SpanIndex,
140-
pub end: SpanIndex,
141-
pub secondary_label: Option<(string::String, SpanIndex, SpanIndex)>,
148+
pub span: InnerSpan,
149+
pub secondary_label: Option<(string::String, InnerSpan)>,
142150
}
143151

144152
/// The parser structure for interpreting the input format string. This is
@@ -157,44 +165,36 @@ pub struct Parser<'a> {
157165
/// `Some(raw count)` when the string is "raw", used to position spans correctly
158166
style: Option<usize>,
159167
/// Start and end byte offset of every successfully parsed argument
160-
pub arg_places: Vec<(SpanIndex, SpanIndex)>,
168+
pub arg_places: Vec<InnerSpan>,
161169
/// Characters that need to be shifted
162170
skips: Vec<usize>,
163-
/// Span offset of the last opening brace seen, used for error reporting
164-
last_opening_brace_pos: Option<SpanIndex>,
171+
/// Span of the last opening brace seen, used for error reporting
172+
last_opening_brace: Option<InnerSpan>,
165173
/// Wether the source string is comes from `println!` as opposed to `format!` or `print!`
166174
append_newline: bool,
167175
}
168176

169-
#[derive(Clone, Copy, Debug)]
170-
pub struct SpanIndex(pub usize);
171-
172-
impl SpanIndex {
173-
pub fn unwrap(self) -> usize {
174-
self.0
175-
}
176-
}
177-
178177
impl<'a> Iterator for Parser<'a> {
179178
type Item = Piece<'a>;
180179

181180
fn next(&mut self) -> Option<Piece<'a>> {
182181
if let Some(&(pos, c)) = self.cur.peek() {
183182
match c {
184183
'{' => {
185-
let curr_last_brace = self.last_opening_brace_pos;
186-
self.last_opening_brace_pos = Some(self.to_span_index(pos));
184+
let curr_last_brace = self.last_opening_brace;
185+
let byte_pos = self.to_span_index(pos);
186+
self.last_opening_brace = Some(byte_pos.to(byte_pos));
187187
self.cur.next();
188188
if self.consume('{') {
189-
self.last_opening_brace_pos = curr_last_brace;
189+
self.last_opening_brace = curr_last_brace;
190190

191191
Some(String(self.string(pos + 1)))
192192
} else {
193193
let arg = self.argument();
194-
if let Some(arg_pos) = self.must_consume('}').map(|end| {
195-
(self.to_span_index(pos), self.to_span_index(end + 1))
196-
}) {
197-
self.arg_places.push(arg_pos);
194+
if let Some(end) = self.must_consume('}') {
195+
let start = self.to_span_index(pos);
196+
let end = self.to_span_index(end + 1);
197+
self.arg_places.push(start.to(end));
198198
}
199199
Some(NextArgument(arg))
200200
}
@@ -209,8 +209,7 @@ impl<'a> Iterator for Parser<'a> {
209209
"unmatched `}` found",
210210
"unmatched `}`",
211211
"if you intended to print `}`, you can escape it using `}}`",
212-
err_pos,
213-
err_pos,
212+
err_pos.to(err_pos),
214213
);
215214
None
216215
}
@@ -242,7 +241,7 @@ impl<'a> Parser<'a> {
242241
style,
243242
arg_places: vec![],
244243
skips,
245-
last_opening_brace_pos: None,
244+
last_opening_brace: None,
246245
append_newline,
247246
}
248247
}
@@ -254,15 +253,13 @@ impl<'a> Parser<'a> {
254253
&mut self,
255254
description: S1,
256255
label: S2,
257-
start: SpanIndex,
258-
end: SpanIndex,
256+
span: InnerSpan,
259257
) {
260258
self.errors.push(ParseError {
261259
description: description.into(),
262260
note: None,
263261
label: label.into(),
264-
start,
265-
end,
262+
span,
266263
secondary_label: None,
267264
});
268265
}
@@ -275,15 +272,13 @@ impl<'a> Parser<'a> {
275272
description: S1,
276273
label: S2,
277274
note: S3,
278-
start: SpanIndex,
279-
end: SpanIndex,
275+
span: InnerSpan,
280276
) {
281277
self.errors.push(ParseError {
282278
description: description.into(),
283279
note: Some(note.into()),
284280
label: label.into(),
285-
start,
286-
end,
281+
span,
287282
secondary_label: None,
288283
});
289284
}
@@ -304,7 +299,7 @@ impl<'a> Parser<'a> {
304299
}
305300
}
306301

307-
fn to_span_index(&self, pos: usize) -> SpanIndex {
302+
fn to_span_index(&self, pos: usize) -> InnerOffset {
308303
let mut pos = pos;
309304
let raw = self.style.map(|raw| raw + 1).unwrap_or(0);
310305
for skip in &self.skips {
@@ -316,7 +311,7 @@ impl<'a> Parser<'a> {
316311
break;
317312
}
318313
}
319-
SpanIndex(raw + pos + 1)
314+
InnerOffset(raw + pos + 1)
320315
}
321316

322317
/// Forces consumption of the specified character. If the character is not
@@ -334,8 +329,8 @@ impl<'a> Parser<'a> {
334329
let label = "expected `}`".to_owned();
335330
let (note, secondary_label) = if c == '}' {
336331
(Some("if you intended to print `{`, you can escape it using `{{`".to_owned()),
337-
self.last_opening_brace_pos.map(|pos| {
338-
("because of this opening brace".to_owned(), pos, pos)
332+
self.last_opening_brace.map(|sp| {
333+
("because of this opening brace".to_owned(), sp)
339334
}))
340335
} else {
341336
(None, None)
@@ -344,8 +339,7 @@ impl<'a> Parser<'a> {
344339
description,
345340
note,
346341
label,
347-
start: pos,
348-
end: pos,
342+
span: pos.to(pos),
349343
secondary_label,
350344
});
351345
None
@@ -359,8 +353,8 @@ impl<'a> Parser<'a> {
359353
let label = format!("expected `{:?}`", c);
360354
let (note, secondary_label) = if c == '}' {
361355
(Some("if you intended to print `{`, you can escape it using `{{`".to_owned()),
362-
self.last_opening_brace_pos.map(|pos| {
363-
("because of this opening brace".to_owned(), pos, pos)
356+
self.last_opening_brace.map(|sp| {
357+
("because of this opening brace".to_owned(), sp)
364358
}))
365359
} else {
366360
(None, None)
@@ -369,12 +363,11 @@ impl<'a> Parser<'a> {
369363
description,
370364
note,
371365
label,
372-
start: pos,
373-
end: pos,
366+
span: pos.to(pos),
374367
secondary_label,
375368
});
376369
} else {
377-
self.err(description, format!("expected `{:?}`", c), pos, pos);
370+
self.err(description, format!("expected `{:?}`", c), pos.to(pos));
378371
}
379372
None
380373
}
@@ -446,8 +439,10 @@ impl<'a> Parser<'a> {
446439
self.err_with_note(format!("invalid argument name `{}`", invalid_name),
447440
"invalid argument name",
448441
"argument names cannot start with an underscore",
449-
self.to_span_index(pos),
450-
self.to_span_index(pos + invalid_name.len()));
442+
self.to_span_index(pos).to(
443+
self.to_span_index(pos + invalid_name.len())
444+
),
445+
);
451446
Some(ArgumentNamed(Symbol::intern(invalid_name)))
452447
},
453448

src/librustdoc/passes/check_code_block_syntax.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ use errors::Applicability;
22
use syntax::parse::lexer::{StringReader as Lexer};
33
use syntax::parse::{ParseSess, token};
44
use syntax::source_map::FilePathMapping;
5-
use syntax_pos::FileName;
5+
use syntax_pos::{InnerSpan, FileName};
66

77
use crate::clean;
88
use crate::core::DocContext;
@@ -63,7 +63,7 @@ impl<'a, 'tcx> SyntaxChecker<'a, 'tcx> {
6363
}
6464

6565
if code_block.syntax.is_none() && code_block.is_fenced {
66-
let sp = sp.from_inner_byte_pos(0, 3);
66+
let sp = sp.from_inner(InnerSpan::new(0, 3));
6767
diag.span_suggestion(
6868
sp,
6969
"mark blocks that do not contain Rust code as text",

src/librustdoc/passes/mod.rs

+3-3
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ use rustc::lint as lint;
66
use rustc::middle::privacy::AccessLevels;
77
use rustc::util::nodemap::DefIdSet;
88
use std::mem;
9-
use syntax_pos::{DUMMY_SP, Span};
9+
use syntax_pos::{DUMMY_SP, InnerSpan, Span};
1010
use std::ops::Range;
1111

1212
use crate::clean::{self, GetDefId, Item};
@@ -440,10 +440,10 @@ crate fn source_span_for_markdown_range(
440440
}
441441
}
442442

443-
let sp = span_of_attrs(attrs).from_inner_byte_pos(
443+
let sp = span_of_attrs(attrs).from_inner(InnerSpan::new(
444444
md_range.start + start_bytes,
445445
md_range.end + start_bytes + end_bytes,
446-
);
446+
));
447447

448448
Some(sp)
449449
}

src/libsyntax_ext/format.rs

+6-8
Original file line numberDiff line numberDiff line change
@@ -900,25 +900,23 @@ pub fn expand_preparsed_format_args(ecx: &mut ExtCtxt<'_>,
900900

901901
if !parser.errors.is_empty() {
902902
let err = parser.errors.remove(0);
903-
let sp = fmt.span.from_inner_byte_pos(err.start.unwrap(), err.end.unwrap());
903+
let sp = fmt.span.from_inner(err.span);
904904
let mut e = ecx.struct_span_err(sp, &format!("invalid format string: {}",
905905
err.description));
906906
e.span_label(sp, err.label + " in format string");
907907
if let Some(note) = err.note {
908908
e.note(&note);
909909
}
910-
if let Some((label, start, end)) = err.secondary_label {
911-
let sp = fmt.span.from_inner_byte_pos(start.unwrap(), end.unwrap());
910+
if let Some((label, span)) = err.secondary_label {
911+
let sp = fmt.span.from_inner(span);
912912
e.span_label(sp, label);
913913
}
914914
e.emit();
915915
return DummyResult::raw_expr(sp, true);
916916
}
917917

918918
let arg_spans = parser.arg_places.iter()
919-
.map(|&(parse::SpanIndex(start), parse::SpanIndex(end))| {
920-
fmt.span.from_inner_byte_pos(start, end)
921-
})
919+
.map(|span| fmt.span.from_inner(*span))
922920
.collect();
923921

924922
let mut cx = Context {
@@ -1065,8 +1063,8 @@ pub fn expand_preparsed_format_args(ecx: &mut ExtCtxt<'_>,
10651063
show_doc_note = true;
10661064
}
10671065

1068-
if let Some((start, end)) = pos {
1069-
let sp = fmt_sp.from_inner_byte_pos(start, end);
1066+
if let Some(inner_sp) = pos {
1067+
let sp = fmt_sp.from_inner(inner_sp);
10701068
suggestions.push((sp, trn));
10711069
} else {
10721070
diag.help(&format!("`{}` should be written as `{}`", sub, trn));

0 commit comments

Comments
 (0)