summaryrefslogtreecommitdiffstats
path: root/compiler/rustc_parse_format/src
diff options
context:
space:
mode:
Diffstat (limited to 'compiler/rustc_parse_format/src')
-rw-r--r--compiler/rustc_parse_format/src/lib.rs87
-rw-r--r--compiler/rustc_parse_format/src/tests.rs43
2 files changed, 74 insertions, 56 deletions
diff --git a/compiler/rustc_parse_format/src/lib.rs b/compiler/rustc_parse_format/src/lib.rs
index 4890fade5..a9e502016 100644
--- a/compiler/rustc_parse_format/src/lib.rs
+++ b/compiler/rustc_parse_format/src/lib.rs
@@ -9,6 +9,8 @@
html_playground_url = "https://play.rust-lang.org/",
test(attr(deny(warnings)))
)]
+#![deny(rustc::untranslatable_diagnostic)]
+#![deny(rustc::diagnostic_outside_of_impl)]
// We want to be able to build this crate with a stable compiler, so no
// `#![feature]` attributes should be added.
@@ -165,6 +167,8 @@ pub enum Count<'a> {
CountIsName(&'a str, InnerSpan),
/// The count is specified by the argument at the given index.
CountIsParam(usize),
+ /// The count is specified by a star (like in `{:.*}`) that refers to the argument at the given index.
+ CountIsStar(usize),
/// The count is implied and cannot be explicitly specified.
CountImplied,
}
@@ -262,9 +266,7 @@ impl<'a> Iterator for Parser<'a> {
}
} else {
if self.is_literal {
- let start = self.to_span_index(self.cur_line_start);
- let end = self.to_span_index(self.input.len());
- let span = start.to(end);
+ let span = self.span(self.cur_line_start, self.input.len());
if self.line_spans.last() != Some(&span) {
self.line_spans.push(span);
}
@@ -382,6 +384,12 @@ impl<'a> Parser<'a> {
InnerOffset(raw + pos + 1)
}
+ fn span(&self, start_pos: usize, end_pos: usize) -> InnerSpan {
+ let start = self.to_span_index(start_pos);
+ let end = self.to_span_index(end_pos);
+ start.to(end)
+ }
+
/// Forces consumption of the specified character. If the character is not
/// found, an error is emitted.
fn must_consume(&mut self, c: char) -> Option<usize> {
@@ -470,9 +478,7 @@ impl<'a> Parser<'a> {
return &self.input[start..pos];
}
'\n' if self.is_literal => {
- let start = self.to_span_index(self.cur_line_start);
- let end = self.to_span_index(pos);
- self.line_spans.push(start.to(end));
+ self.line_spans.push(self.span(self.cur_line_start, pos));
self.cur_line_start = pos + 1;
self.cur.next();
}
@@ -535,6 +541,10 @@ impl<'a> Parser<'a> {
}
}
+ fn current_pos(&mut self) -> usize {
+ if let Some(&(pos, _)) = self.cur.peek() { pos } else { self.input.len() }
+ }
+
/// Parses a format specifier at the current position, returning all of the
/// relevant information in the `FormatSpec` struct.
fn format(&mut self) -> FormatSpec<'a> {
@@ -588,39 +598,37 @@ impl<'a> Parser<'a> {
// no '0' flag and '0$' as the width instead.
if let Some(end) = self.consume_pos('$') {
spec.width = CountIsParam(0);
-
- if let Some((pos, _)) = self.cur.peek().cloned() {
- spec.width_span = Some(self.to_span_index(pos - 2).to(self.to_span_index(pos)));
- }
+ spec.width_span = Some(self.span(end - 1, end + 1));
havewidth = true;
- spec.width_span = Some(self.to_span_index(end - 1).to(self.to_span_index(end + 1)));
} else {
spec.flags |= 1 << (FlagSignAwareZeroPad as u32);
}
}
+
if !havewidth {
- let width_span_start = if let Some((pos, _)) = self.cur.peek() { *pos } else { 0 };
- let (w, sp) = self.count(width_span_start);
- spec.width = w;
- spec.width_span = sp;
+ let start = self.current_pos();
+ spec.width = self.count(start);
+ if spec.width != CountImplied {
+ let end = self.current_pos();
+ spec.width_span = Some(self.span(start, end));
+ }
}
if let Some(start) = self.consume_pos('.') {
- if let Some(end) = self.consume_pos('*') {
+ if self.consume('*') {
// Resolve `CountIsNextParam`.
// We can do this immediately as `position` is resolved later.
let i = self.curarg;
self.curarg += 1;
- spec.precision = CountIsParam(i);
- spec.precision_span =
- Some(self.to_span_index(start).to(self.to_span_index(end + 1)));
+ spec.precision = CountIsStar(i);
} else {
- let (p, sp) = self.count(start);
- spec.precision = p;
- spec.precision_span = sp;
+ spec.precision = self.count(start + 1);
}
+ let end = self.current_pos();
+ spec.precision_span = Some(self.span(start, end));
}
- let ty_span_start = self.cur.peek().map(|(pos, _)| *pos);
+
+ let ty_span_start = self.current_pos();
// Optional radix followed by the actual format specifier
if self.consume('x') {
if self.consume('?') {
@@ -640,11 +648,9 @@ impl<'a> Parser<'a> {
spec.ty = "?";
} else {
spec.ty = self.word();
- let ty_span_end = self.cur.peek().map(|(pos, _)| *pos);
if !spec.ty.is_empty() {
- spec.ty_span = ty_span_start
- .and_then(|s| ty_span_end.map(|e| (s, e)))
- .map(|(start, end)| self.to_span_index(start).to(self.to_span_index(end)));
+ let ty_span_end = self.current_pos();
+ spec.ty_span = Some(self.span(ty_span_start, ty_span_end));
}
}
spec
@@ -668,13 +674,11 @@ impl<'a> Parser<'a> {
return spec;
}
- let ty_span_start = self.cur.peek().map(|(pos, _)| *pos);
+ let ty_span_start = self.current_pos();
spec.ty = self.word();
- let ty_span_end = self.cur.peek().map(|(pos, _)| *pos);
if !spec.ty.is_empty() {
- spec.ty_span = ty_span_start
- .and_then(|s| ty_span_end.map(|e| (s, e)))
- .map(|(start, end)| self.to_span_index(start).to(self.to_span_index(end)));
+ let ty_span_end = self.current_pos();
+ spec.ty_span = Some(self.span(ty_span_start, ty_span_end));
}
spec
@@ -683,26 +687,21 @@ impl<'a> Parser<'a> {
/// Parses a `Count` parameter at the current position. This does not check
/// for 'CountIsNextParam' because that is only used in precision, not
/// width.
- fn count(&mut self, start: usize) -> (Count<'a>, Option<InnerSpan>) {
+ fn count(&mut self, start: usize) -> Count<'a> {
if let Some(i) = self.integer() {
- if let Some(end) = self.consume_pos('$') {
- let span = self.to_span_index(start).to(self.to_span_index(end + 1));
- (CountIsParam(i), Some(span))
- } else {
- (CountIs(i), None)
- }
+ if self.consume('$') { CountIsParam(i) } else { CountIs(i) }
} else {
let tmp = self.cur.clone();
let word = self.word();
if word.is_empty() {
self.cur = tmp;
- (CountImplied, None)
+ CountImplied
} else if let Some(end) = self.consume_pos('$') {
- let span = self.to_span_index(start + 1).to(self.to_span_index(end));
- (CountIsName(word, span), None)
+ let name_span = self.span(start, end);
+ CountIsName(word, name_span)
} else {
self.cur = tmp;
- (CountImplied, None)
+ CountImplied
}
}
}
@@ -735,7 +734,7 @@ impl<'a> Parser<'a> {
"invalid argument name `_`",
"invalid argument name",
"argument name cannot be a single underscore",
- self.to_span_index(start).to(self.to_span_index(end)),
+ self.span(start, end),
);
}
word
diff --git a/compiler/rustc_parse_format/src/tests.rs b/compiler/rustc_parse_format/src/tests.rs
index 578530696..2f8c229c6 100644
--- a/compiler/rustc_parse_format/src/tests.rs
+++ b/compiler/rustc_parse_format/src/tests.rs
@@ -1,5 +1,6 @@
use super::*;
+#[track_caller]
fn same(fmt: &'static str, p: &[Piece<'static>]) {
let parser = Parser::new(fmt, None, None, false, ParseMode::Format);
assert_eq!(parser.collect::<Vec<Piece<'static>>>(), p);
@@ -190,9 +191,9 @@ fn format_counts() {
align: AlignUnknown,
flags: 0,
precision: CountImplied,
- width: CountIs(10),
precision_span: None,
- width_span: None,
+ width: CountIs(10),
+ width_span: Some(InnerSpan { start: 3, end: 5 }),
ty: "x",
ty_span: None,
},
@@ -208,9 +209,9 @@ fn format_counts() {
align: AlignUnknown,
flags: 0,
precision: CountIs(10),
+ precision_span: Some(InnerSpan { start: 6, end: 9 }),
width: CountIsParam(10),
- precision_span: None,
- width_span: Some(InnerSpan::new(3, 6)),
+ width_span: Some(InnerSpan { start: 3, end: 6 }),
ty: "x",
ty_span: None,
},
@@ -226,9 +227,9 @@ fn format_counts() {
align: AlignUnknown,
flags: 0,
precision: CountIs(10),
+ precision_span: Some(InnerSpan { start: 6, end: 9 }),
width: CountIsParam(0),
- precision_span: None,
- width_span: Some(InnerSpan::new(4, 6)),
+ width_span: Some(InnerSpan { start: 4, end: 6 }),
ty: "x",
ty_span: None,
},
@@ -243,9 +244,9 @@ fn format_counts() {
fill: None,
align: AlignUnknown,
flags: 0,
- precision: CountIsParam(0),
+ precision: CountIsStar(0),
+ precision_span: Some(InnerSpan { start: 3, end: 5 }),
width: CountImplied,
- precision_span: Some(InnerSpan::new(3, 5)),
width_span: None,
ty: "x",
ty_span: None,
@@ -279,15 +280,33 @@ fn format_counts() {
fill: None,
align: AlignUnknown,
flags: 0,
- precision: CountIsName("b", InnerSpan::new(6, 7)),
- width: CountIsName("a", InnerSpan::new(4, 4)),
- precision_span: None,
- width_span: None,
+ precision: CountIsName("b", InnerSpan { start: 6, end: 7 }),
+ precision_span: Some(InnerSpan { start: 5, end: 8 }),
+ width: CountIsName("a", InnerSpan { start: 3, end: 4 }),
+ width_span: Some(InnerSpan { start: 3, end: 5 }),
ty: "?",
ty_span: None,
},
})],
);
+ same(
+ "{:.4}",
+ &[NextArgument(Argument {
+ position: ArgumentImplicitlyIs(0),
+ position_span: InnerSpan { start: 2, end: 2 },
+ format: FormatSpec {
+ fill: None,
+ align: AlignUnknown,
+ flags: 0,
+ precision: CountIs(4),
+ precision_span: Some(InnerSpan { start: 3, end: 5 }),
+ width: CountImplied,
+ width_span: None,
+ ty: "",
+ ty_span: None,
+ },
+ })],
+ )
}
#[test]
fn format_flags() {