From 5e2f29af851b7d89ed7f4be91bd1932d45b90eaa Mon Sep 17 00:00:00 2001 From: Aleksey Kladov Date: Fri, 10 Apr 2020 19:28:32 +0200 Subject: Add failing test --- crates/ra_hir_ty/src/tests/macros.rs | 31 +++++++++++++++++++++++++++++-- 1 file changed, 29 insertions(+), 2 deletions(-) diff --git a/crates/ra_hir_ty/src/tests/macros.rs b/crates/ra_hir_ty/src/tests/macros.rs index ff4599b71..f2a9b1c40 100644 --- a/crates/ra_hir_ty/src/tests/macros.rs +++ b/crates/ra_hir_ty/src/tests/macros.rs @@ -1,10 +1,13 @@ +use std::fs; + use insta::assert_snapshot; use ra_db::fixture::WithFixture; - -use super::{infer, type_at, type_at_pos}; +use test_utils::project_dir; use crate::test_db::TestDB; +use super::{infer, type_at, type_at_pos}; + #[test] fn cfg_impl_def() { let (db, pos) = TestDB::with_position( @@ -481,6 +484,30 @@ fn bar() -> u32 {0} assert_eq!("u32", type_at_pos(&db, pos)); } +#[test] +#[ignore] +fn include_accidentally_quadratic() { + let file = project_dir().join("crates/ra_syntax/test_data/accidentally_quadratic"); + let big_file = fs::read_to_string(file).unwrap(); + let big_file = vec![big_file; 10].join("\n"); + + let fixture = r#" +//- /main.rs +#[rustc_builtin_macro] +macro_rules! include {() => {}} + +include!("foo.rs"); + +fn main() { + RegisterBlock { }<|>; +} + "#; + let fixture = format!("{}\n//- /foo.rs\n{}", fixture, big_file); + + let (db, pos) = TestDB::with_position(&fixture); + assert_eq!("RegisterBlock", type_at_pos(&db, pos)); +} + #[test] fn infer_builtin_macros_include_concat() { let (db, pos) = TestDB::with_position( -- cgit v1.2.3 From 428d4dfe710f7fe7564e6db82c4b44caaf84655d Mon Sep 17 00:00:00 2001 From: Aleksey Kladov Date: Fri, 10 Apr 2020 19:41:01 +0200 Subject: Fix accidently quadratic behavior when processing includes closes #3927 --- crates/ra_mbe/src/syntax_bridge.rs | 36 +++++++++++++++++++----------------- 1 file changed, 19 insertions(+), 17 deletions(-) diff --git a/crates/ra_mbe/src/syntax_bridge.rs b/crates/ra_mbe/src/syntax_bridge.rs index 8e8ae2b29..9fb5cb058 100644 --- a/crates/ra_mbe/src/syntax_bridge.rs +++ b/crates/ra_mbe/src/syntax_bridge.rs @@ -137,21 +137,23 @@ impl TokenMap { 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 @@ impl TokenIdAlloc { 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) { + fn close_delim(&mut self, idx: usize, close_abs_range: Option) { 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 @@ trait TokenConvertor { 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 @@ trait TokenConvertor { 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 @@ trait TokenConvertor { } 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() { -- cgit v1.2.3 From 72a0db8dc46c63409a93745d04758049515abaf0 Mon Sep 17 00:00:00 2001 From: Aleksey Kladov Date: Fri, 10 Apr 2020 20:25:55 +0200 Subject: profile queries --- crates/ra_hir_def/src/lang_item.rs | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/crates/ra_hir_def/src/lang_item.rs b/crates/ra_hir_def/src/lang_item.rs index 01b367278..d96ac8c0a 100644 --- a/crates/ra_hir_def/src/lang_item.rs +++ b/crates/ra_hir_def/src/lang_item.rs @@ -4,6 +4,7 @@ //! features, such as Fn family of traits. use std::sync::Arc; +use ra_prof::profile; use ra_syntax::SmolStr; use rustc_hash::FxHashMap; @@ -78,6 +79,8 @@ impl LangItems { /// Salsa query. This will look for lang items in a specific crate. pub(crate) fn crate_lang_items_query(db: &dyn DefDatabase, krate: CrateId) -> Arc { + let _p = profile("crate_lang_items_query"); + let mut lang_items = LangItems::default(); let crate_def_map = db.crate_def_map(krate); @@ -95,6 +98,7 @@ impl LangItems { db: &dyn DefDatabase, module: ModuleId, ) -> Option> { + let _p = profile("module_lang_items_query"); let mut lang_items = LangItems::default(); lang_items.collect_lang_items(db, module); if lang_items.items.is_empty() { @@ -111,6 +115,7 @@ impl LangItems { start_crate: CrateId, item: SmolStr, ) -> Option { + let _p = profile("lang_item_query"); let lang_items = db.crate_lang_items(start_crate); let start_crate_target = lang_items.items.get(&item); if let Some(target) = start_crate_target { -- cgit v1.2.3 From 1b68c72fe93424213db895a4066eafb99dfdeac9 Mon Sep 17 00:00:00 2001 From: Aleksey Kladov Date: Fri, 10 Apr 2020 20:46:42 +0200 Subject: Move timeit to stdx --- crates/ra_prof/src/lib.rs | 15 --------------- crates/stdx/src/lib.rs | 16 +++++++++++++++- 2 files changed, 15 insertions(+), 16 deletions(-) diff --git a/crates/ra_prof/src/lib.rs b/crates/ra_prof/src/lib.rs index 00ea3a9b0..2d4f68f5e 100644 --- a/crates/ra_prof/src/lib.rs +++ b/crates/ra_prof/src/lib.rs @@ -113,21 +113,6 @@ pub fn profile(label: Label) -> Profiler { }) } -pub fn print_time(label: Label) -> impl Drop { - struct Guard { - label: Label, - start: Instant, - } - - impl Drop for Guard { - fn drop(&mut self) { - eprintln!("{}: {:?}", self.label, self.start.elapsed()) - } - } - - Guard { label, start: Instant::now() } -} - pub struct Profiler { label: Option