fish_indent: fix accidentally quadratic perf regression due to chars().last()

Iterator::last() consumes the entire iterator, even for DoubleEndedIterator,
see https://github.com/rust-lang/rust/pull/28125#issuecomment-145070161

Because of this, "at_line_start()" took 90% of

    fish_indent share/completions/git.fish

making it take 1000ms instead of 30 ms. Fix that.
This commit is contained in:
Johannes Altmanninger 2024-01-07 18:56:52 +01:00
parent 57d7c46d22
commit 8d2fa4ae95
6 changed files with 7 additions and 7 deletions

View file

@ -545,7 +545,7 @@ fn unescape_string_internal(input: &wstr, flags: UnescapeFlags) -> Option<WStrin
// In general, this is ANY_STRING. But as a hack, if the last appended char
// is ANY_STRING, delete the last char and store ANY_STRING_RECURSIVE to
// reflect the fact that ** is the recursive wildcard.
if result.chars().last() == Some(ANY_STRING) {
if result.chars().next_back() == Some(ANY_STRING) {
assert!(!result.is_empty());
result.truncate(result.len() - 1);
to_append_or_none = Some(ANY_STRING_RECURSIVE);

View file

@ -319,7 +319,7 @@ impl<'source, 'ast> PrettyPrinterState<'source, 'ast> {
// \return whether we are at the start of a new line.
fn at_line_start(&self) -> bool {
self.output.chars().last().is_none_or(|c| c == '\n')
self.output.chars().next_back().is_none_or(|c| c == '\n')
}
// \return whether we have a space before the output.

View file

@ -782,7 +782,7 @@ pub fn is_potential_path(
return false;
}
let mut abs_path = path_apply_working_directory(&clean_potential_path_fragment, wd);
let must_be_full_dir = abs_path.chars().last() == Some('/');
let must_be_full_dir = abs_path.chars().next_back() == Some('/');
if flags.contains(PathFlags::PATH_FOR_CD) {
abs_path = normalize_path(&abs_path, /*allow_leading_double_slashes=*/ true);
}

View file

@ -340,7 +340,7 @@ pub fn path_get_cdpath(dir: &wstr, wd: &wstr, vars: &dyn Environment) -> Option<
if dir.is_empty() {
return None;
}
assert!(wd.chars().last() == Some('/'));
assert!(wd.chars().next_back() == Some('/'));
let paths = path_apply_cdpath(dir, wd, vars);
for a_dir in paths {

View file

@ -3798,7 +3798,7 @@ fn get_autosuggestion_performer(
// Here we do something a little funny. If the line ends with a space, and the cursor is not
// at the end, don't use completion autosuggestions. It ends up being pretty weird seeing
// stuff get spammed on the right while you go back to edit a line
let last_char = search_string.chars().last().unwrap();
let last_char = search_string.chars().next_back().unwrap();
let cursor_at_end = cursor_pos == search_string.len();
if !cursor_at_end && last_char.is_whitespace() {
return nothing;
@ -4693,7 +4693,7 @@ impl ReaderData {
// Historical behavior is to trim trailing spaces, unless escape (#7661).
let mut text = self.command_line.text().to_owned();
while text.chars().last() == Some(' ')
while text.chars().next_back() == Some(' ')
&& count_preceding_backslashes(&text, text.len() - 1) % 2 == 0
{
text.pop();

View file

@ -632,7 +632,7 @@ mod expander {
// ANY_STRING_RECURSIVE character is present in both the head and the tail.
let head_any = wc_segment.slice_to(asr_idx + 1);
let any_tail = wc.slice_from(asr_idx);
assert!(head_any.chars().last().unwrap() == ANY_STRING_RECURSIVE);
assert!(head_any.chars().next_back().unwrap() == ANY_STRING_RECURSIVE);
assert!(any_tail.chars().next().unwrap() == ANY_STRING_RECURSIVE);
dir.rewind();