diff --git a/src/formatting.rs b/src/formatting.rs index 1e1e329f624..047351aa084 100644 --- a/src/formatting.rs +++ b/src/formatting.rs @@ -582,12 +582,14 @@ impl<'a> FormatLines<'a> { fn char(&mut self, c: char, kind: FullCodeCharKind) { self.newline_count = 0; self.line_len += if c == '\t' { + self.line_buffer + .push_str(&" ".repeat(self.config.tab_spaces())); self.config.tab_spaces() } else { - 1 + self.line_buffer.push(c); + c.len_utf8() }; self.last_was_space = c.is_whitespace(); - self.line_buffer.push(c); if kind.is_string() { self.current_line_contains_string_literal = true; } diff --git a/src/test/parser.rs b/src/test/parser.rs index d951c8469e6..3e8d3a73295 100644 --- a/src/test/parser.rs +++ b/src/test/parser.rs @@ -3,6 +3,7 @@ use std::path::PathBuf; use super::read_config; +use crate::FormatReportFormatterBuilder; use crate::modules::{ModuleResolutionError, ModuleResolutionErrorKind}; use crate::{ErrorKind, Input, Session}; @@ -69,3 +70,21 @@ fn crate_parsing_stashed_diag2() { let filename = "tests/parser/stashed-diag2.rs"; assert_parser_error(filename); } + +#[test] +fn indexing_mismatch_with_annotated_snippet() { + // See also https://github.com/rust-lang/rustfmt/issues/4968 + let filename = "tests/parser/issue_4968.rs"; + let file = PathBuf::from(filename); + let config = read_config(&file); + let mut session = Session::::new(config, None); + let report = session.format(Input::File(filename.into())).unwrap(); + let report = FormatReportFormatterBuilder::new(&report).build(); + { + // Panic can only be triggered if we actually try to write the report + // and call into the annotated_snippet dependency. + use std::io::Write; + + write!(&mut Vec::new(), "{report}").unwrap(); + } +} diff --git a/tests/parser/issue_4968.rs b/tests/parser/issue_4968.rs new file mode 100644 index 00000000000..eb0c65756ef --- /dev/null +++ b/tests/parser/issue_4968.rs @@ -0,0 +1,12 @@ +// rustfmt-hard_tabs: true +// rustfmt-max_width: 40 +// rustfmt-error_on_unformatted: true +// rustfmt-error_on_line_overflow: true + +fn foo(x: u32) { + if x > 10 { + if x > 20 { + println!("0123456789abcdefghijklmnopqrstuvwxyz"); + } + } +}