Fix accidently quadratic behavior when processing includes

closes #3927
This commit is contained in:
Aleksey Kladov 2020-04-10 19:41:01 +02:00
parent 5e2f29af85
commit 428d4dfe71

View File

@ -137,21 +137,23 @@ fn insert_delim(
token_id: tt::TokenId,
open_relative_range: TextRange,
close_relative_range: TextRange,
) {
) -> usize {
let res = self.entries.len();
self.entries
.push((token_id, TokenTextRange::Delimiter(open_relative_range, close_relative_range)));
res
}
fn update_close_delim(&mut self, token_id: tt::TokenId, close_relative_range: TextRange) {
if let Some(entry) = self.entries.iter_mut().find(|(tid, _)| *tid == token_id) {
if let TokenTextRange::Delimiter(dim, _) = entry.1 {
entry.1 = TokenTextRange::Delimiter(dim, close_relative_range);
}
fn update_close_delim(&mut self, idx: usize, close_relative_range: TextRange) {
let (_, token_text_range) = &mut self.entries[idx];
if let TokenTextRange::Delimiter(dim, _) = token_text_range {
*token_text_range = TokenTextRange::Delimiter(*dim, close_relative_range);
}
}
fn remove_delim(&mut self, token_id: tt::TokenId) {
self.entries.retain(|(tid, _)| *tid != token_id);
fn remove_delim(&mut self, idx: usize) {
// FIXME: This could be accidently quadratic
self.entries.remove(idx);
}
}
@ -238,24 +240,24 @@ fn alloc(&mut self, absolute_range: TextRange) -> tt::TokenId {
token_id
}
fn open_delim(&mut self, open_abs_range: TextRange) -> tt::TokenId {
fn open_delim(&mut self, open_abs_range: TextRange) -> (tt::TokenId, usize) {
let token_id = tt::TokenId(self.next_id);
self.next_id += 1;
self.map.insert_delim(
let idx = self.map.insert_delim(
token_id,
open_abs_range - self.global_offset,
open_abs_range - self.global_offset,
);
token_id
(token_id, idx)
}
fn close_delim(&mut self, id: tt::TokenId, close_abs_range: Option<TextRange>) {
fn close_delim(&mut self, idx: usize, close_abs_range: Option<TextRange>) {
match close_abs_range {
None => {
self.map.remove_delim(id);
self.map.remove_delim(idx);
}
Some(close) => {
self.map.update_close_delim(id, close - self.global_offset);
self.map.update_close_delim(idx, close - self.global_offset);
}
}
}
@ -322,7 +324,7 @@ fn collect_leaf(&mut self, result: &mut Vec<tt::TokenTree>) {
if let Some((kind, closed)) = delim {
let mut subtree = tt::Subtree::default();
let id = self.id_alloc().open_delim(range);
let (id, idx) = self.id_alloc().open_delim(range);
subtree.delimiter = Some(tt::Delimiter { kind, id });
while self.peek().map(|it| it.kind() != closed).unwrap_or(false) {
@ -331,7 +333,7 @@ fn collect_leaf(&mut self, result: &mut Vec<tt::TokenTree>) {
let last_range = match self.bump() {
None => {
// For error resilience, we insert an char punct for the opening delim here
self.id_alloc().close_delim(id, None);
self.id_alloc().close_delim(idx, None);
let leaf: tt::Leaf = tt::Punct {
id: self.id_alloc().alloc(range),
char: token.to_char().unwrap(),
@ -344,7 +346,7 @@ fn collect_leaf(&mut self, result: &mut Vec<tt::TokenTree>) {
}
Some(it) => it.1,
};
self.id_alloc().close_delim(id, Some(last_range));
self.id_alloc().close_delim(idx, Some(last_range));
subtree.into()
} else {
let spacing = match self.peek() {