diff options
Diffstat (limited to 'compiler/rustc_parse_format')
-rw-r--r-- | compiler/rustc_parse_format/src/lib.rs | 87 | ||||
-rw-r--r-- | compiler/rustc_parse_format/src/tests.rs | 43 |
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() { |