aboutsummaryrefslogtreecommitdiff
path: root/crates
diff options
context:
space:
mode:
Diffstat (limited to 'crates')
-rw-r--r--crates/base_db/src/lib.rs1
-rw-r--r--crates/hir/src/lib.rs5
-rw-r--r--crates/hir_def/src/import_map.rs169
-rw-r--r--crates/hir_def/src/lang_item.rs1
-rw-r--r--crates/hir_def/src/nameres/collector.rs4
-rw-r--r--crates/hir_def/src/per_ns.rs2
-rw-r--r--crates/hir_expand/src/builtin_attr.rs67
-rw-r--r--crates/hir_expand/src/db.rs14
-rw-r--r--crates/hir_expand/src/eager.rs1
-rw-r--r--crates/hir_expand/src/hygiene.rs1
-rw-r--r--crates/hir_expand/src/lib.rs4
-rw-r--r--crates/hir_expand/src/name.rs9
-rw-r--r--crates/ide/src/prime_caches.rs7
-rw-r--r--crates/ide/src/references.rs20
-rw-r--r--crates/ide_assists/src/handlers/remove_unused_param.rs30
-rw-r--r--crates/ide_completion/src/completions/qualified_path.rs26
-rw-r--r--crates/ide_completion/src/completions/unqualified_path.rs12
-rw-r--r--crates/ide_completion/src/render.rs386
-rw-r--r--crates/ide_db/src/defs.rs8
-rw-r--r--crates/ide_db/src/symbol_index.rs2
-rw-r--r--crates/profile/Cargo.toml3
-rw-r--r--crates/profile/src/memory_usage.rs16
-rw-r--r--crates/rust-analyzer/src/cli.rs1
-rw-r--r--crates/rust-analyzer/src/cli/analysis_stats.rs1
-rw-r--r--crates/rust-analyzer/src/cli/diagnostics.rs8
-rw-r--r--crates/rust-analyzer/src/cli/load_cargo.rs18
-rw-r--r--crates/rust-analyzer/src/cli/ssr.rs9
-rw-r--r--crates/rust-analyzer/src/integrated_benchmarks.rs2
28 files changed, 506 insertions, 321 deletions
diff --git a/crates/base_db/src/lib.rs b/crates/base_db/src/lib.rs
index 62bf2a4b2..54baa3a63 100644
--- a/crates/base_db/src/lib.rs
+++ b/crates/base_db/src/lib.rs
@@ -120,6 +120,7 @@ impl<T: SourceDatabaseExt> FileLoader for FileLoaderDelegate<&'_ T> {
120 } 120 }
121 121
122 fn relevant_crates(&self, file_id: FileId) -> Arc<FxHashSet<CrateId>> { 122 fn relevant_crates(&self, file_id: FileId) -> Arc<FxHashSet<CrateId>> {
123 let _p = profile::span("relevant_crates");
123 let source_root = self.0.file_source_root(file_id); 124 let source_root = self.0.file_source_root(file_id);
124 self.0.source_root_crates(source_root) 125 self.0.source_root_crates(source_root)
125 } 126 }
diff --git a/crates/hir/src/lib.rs b/crates/hir/src/lib.rs
index dba46df04..b9c1dc44d 100644
--- a/crates/hir/src/lib.rs
+++ b/crates/hir/src/lib.rs
@@ -191,6 +191,7 @@ impl Crate {
191 db: &dyn DefDatabase, 191 db: &dyn DefDatabase,
192 query: import_map::Query, 192 query: import_map::Query,
193 ) -> impl Iterator<Item = Either<ModuleDef, MacroDef>> { 193 ) -> impl Iterator<Item = Either<ModuleDef, MacroDef>> {
194 let _p = profile::span("query_external_importables");
194 import_map::search_dependencies(db, self.into(), query).into_iter().map(|item| match item { 195 import_map::search_dependencies(db, self.into(), query).into_iter().map(|item| match item {
195 ItemInNs::Types(mod_id) | ItemInNs::Values(mod_id) => Either::Left(mod_id.into()), 196 ItemInNs::Types(mod_id) | ItemInNs::Values(mod_id) => Either::Left(mod_id.into()),
196 ItemInNs::Macros(mac_id) => Either::Right(mac_id.into()), 197 ItemInNs::Macros(mac_id) => Either::Right(mac_id.into()),
@@ -1344,6 +1345,7 @@ impl MacroDef {
1344 MacroDefKind::Declarative(_) => MacroKind::Declarative, 1345 MacroDefKind::Declarative(_) => MacroKind::Declarative,
1345 MacroDefKind::BuiltIn(_, _) | MacroDefKind::BuiltInEager(_, _) => MacroKind::BuiltIn, 1346 MacroDefKind::BuiltIn(_, _) | MacroDefKind::BuiltInEager(_, _) => MacroKind::BuiltIn,
1346 MacroDefKind::BuiltInDerive(_, _) => MacroKind::Derive, 1347 MacroDefKind::BuiltInDerive(_, _) => MacroKind::Derive,
1348 MacroDefKind::BuiltInAttr(_, _) => MacroKind::Attr,
1347 MacroDefKind::ProcMacro(_, base_db::ProcMacroKind::CustomDerive, _) => { 1349 MacroDefKind::ProcMacro(_, base_db::ProcMacroKind::CustomDerive, _) => {
1348 MacroKind::Derive 1350 MacroKind::Derive
1349 } 1351 }
@@ -2184,6 +2186,7 @@ impl Type {
2184 name: Option<&Name>, 2186 name: Option<&Name>,
2185 mut callback: impl FnMut(&Ty, Function) -> Option<T>, 2187 mut callback: impl FnMut(&Ty, Function) -> Option<T>,
2186 ) -> Option<T> { 2188 ) -> Option<T> {
2189 let _p = profile::span("iterate_method_candidates");
2187 // There should be no inference vars in types passed here 2190 // There should be no inference vars in types passed here
2188 // FIXME check that? 2191 // FIXME check that?
2189 // FIXME replace Unknown by bound vars here 2192 // FIXME replace Unknown by bound vars here
@@ -2217,6 +2220,7 @@ impl Type {
2217 name: Option<&Name>, 2220 name: Option<&Name>,
2218 mut callback: impl FnMut(&Ty, AssocItem) -> Option<T>, 2221 mut callback: impl FnMut(&Ty, AssocItem) -> Option<T>,
2219 ) -> Option<T> { 2222 ) -> Option<T> {
2223 let _p = profile::span("iterate_path_candidates");
2220 let canonical = hir_ty::replace_errors_with_variables(&self.ty); 2224 let canonical = hir_ty::replace_errors_with_variables(&self.ty);
2221 2225
2222 let env = self.env.clone(); 2226 let env = self.env.clone();
@@ -2254,6 +2258,7 @@ impl Type {
2254 &'a self, 2258 &'a self,
2255 db: &'a dyn HirDatabase, 2259 db: &'a dyn HirDatabase,
2256 ) -> impl Iterator<Item = Trait> + 'a { 2260 ) -> impl Iterator<Item = Trait> + 'a {
2261 let _p = profile::span("applicable_inherent_traits");
2257 self.autoderef(db) 2262 self.autoderef(db)
2258 .filter_map(|derefed_type| derefed_type.ty.dyn_trait()) 2263 .filter_map(|derefed_type| derefed_type.ty.dyn_trait())
2259 .flat_map(move |dyn_trait_id| hir_ty::all_super_traits(db.upcast(), dyn_trait_id)) 2264 .flat_map(move |dyn_trait_id| hir_ty::all_super_traits(db.upcast(), dyn_trait_id))
diff --git a/crates/hir_def/src/import_map.rs b/crates/hir_def/src/import_map.rs
index 960cabb5f..404e3e153 100644
--- a/crates/hir_def/src/import_map.rs
+++ b/crates/hir_def/src/import_map.rs
@@ -1,6 +1,6 @@
1//! A map of all publicly exported items in a crate. 1//! A map of all publicly exported items in a crate.
2 2
3use std::{cmp::Ordering, fmt, hash::BuildHasherDefault, sync::Arc}; 3use std::{fmt, hash::BuildHasherDefault, sync::Arc};
4 4
5use base_db::CrateId; 5use base_db::CrateId;
6use fst::{self, Streamer}; 6use fst::{self, Streamer};
@@ -69,81 +69,11 @@ pub struct ImportMap {
69impl ImportMap { 69impl ImportMap {
70 pub fn import_map_query(db: &dyn DefDatabase, krate: CrateId) -> Arc<Self> { 70 pub fn import_map_query(db: &dyn DefDatabase, krate: CrateId) -> Arc<Self> {
71 let _p = profile::span("import_map_query"); 71 let _p = profile::span("import_map_query");
72 let def_map = db.crate_def_map(krate);
73 let mut import_map = Self::default();
74
75 // We look only into modules that are public(ly reexported), starting with the crate root.
76 let empty = ImportPath { segments: vec![] };
77 let root = def_map.module_id(def_map.root());
78 let mut worklist = vec![(root, empty)];
79 while let Some((module, mod_path)) = worklist.pop() {
80 let ext_def_map;
81 let mod_data = if module.krate == krate {
82 &def_map[module.local_id]
83 } else {
84 // The crate might reexport a module defined in another crate.
85 ext_def_map = module.def_map(db);
86 &ext_def_map[module.local_id]
87 };
88
89 let visible_items = mod_data.scope.entries().filter_map(|(name, per_ns)| {
90 let per_ns = per_ns.filter_visibility(|vis| vis == Visibility::Public);
91 if per_ns.is_none() {
92 None
93 } else {
94 Some((name, per_ns))
95 }
96 });
97
98 for (name, per_ns) in visible_items {
99 let mk_path = || {
100 let mut path = mod_path.clone();
101 path.segments.push(name.clone());
102 path
103 };
104
105 for item in per_ns.iter_items() {
106 let path = mk_path();
107 let path_len = path.len();
108 let import_info =
109 ImportInfo { path, container: module, is_trait_assoc_item: false };
110
111 if let Some(ModuleDefId::TraitId(tr)) = item.as_module_def_id() {
112 import_map.collect_trait_assoc_items(
113 db,
114 tr,
115 matches!(item, ItemInNs::Types(_)),
116 &import_info,
117 );
118 }
119 72
120 match import_map.map.entry(item) { 73 let mut import_map = collect_import_map(db, krate);
121 Entry::Vacant(entry) => {
122 entry.insert(import_info);
123 }
124 Entry::Occupied(mut entry) => {
125 // If the new path is shorter, prefer that one.
126 if path_len < entry.get().path.len() {
127 *entry.get_mut() = import_info;
128 } else {
129 continue;
130 }
131 }
132 }
133
134 // If we've just added a path to a module, descend into it. We might traverse
135 // modules multiple times, but only if the new path to it is shorter than the
136 // first (else we `continue` above).
137 if let Some(ModuleDefId::ModuleId(mod_id)) = item.as_module_def_id() {
138 worklist.push((mod_id, mk_path()));
139 }
140 }
141 }
142 }
143 74
144 let mut importables = import_map.map.iter().collect::<Vec<_>>(); 75 let mut importables = import_map.map.iter().collect::<Vec<_>>();
145 76 importables.sort_by_cached_key(|(_, import_info)| fst_path(&import_info.path));
146 importables.sort_by(cmp);
147 77
148 // Build the FST, taking care not to insert duplicate values. 78 // Build the FST, taking care not to insert duplicate values.
149 79
@@ -151,13 +81,13 @@ impl ImportMap {
151 let mut last_batch_start = 0; 81 let mut last_batch_start = 0;
152 82
153 for idx in 0..importables.len() { 83 for idx in 0..importables.len() {
154 if let Some(next_item) = importables.get(idx + 1) { 84 let key = fst_path(&importables[last_batch_start].1.path);
155 if cmp(&importables[last_batch_start], next_item) == Ordering::Equal { 85 if let Some((_, next_import_info)) = importables.get(idx + 1) {
86 if key == fst_path(&next_import_info.path) {
156 continue; 87 continue;
157 } 88 }
158 } 89 }
159 90
160 let key = fst_path(&importables[last_batch_start].1.path);
161 builder.insert(key, last_batch_start as u64).unwrap(); 91 builder.insert(key, last_batch_start as u64).unwrap();
162 92
163 last_batch_start = idx + 1; 93 last_batch_start = idx + 1;
@@ -185,6 +115,7 @@ impl ImportMap {
185 is_type_in_ns: bool, 115 is_type_in_ns: bool,
186 original_import_info: &ImportInfo, 116 original_import_info: &ImportInfo,
187 ) { 117 ) {
118 let _p = profile::span("collect_trait_assoc_items");
188 for (assoc_item_name, item) in &db.trait_data(tr).items { 119 for (assoc_item_name, item) in &db.trait_data(tr).items {
189 let module_def_id = match item { 120 let module_def_id = match item {
190 AssocItemId::FunctionId(f) => ModuleDefId::from(*f), 121 AssocItemId::FunctionId(f) => ModuleDefId::from(*f),
@@ -210,6 +141,84 @@ impl ImportMap {
210 } 141 }
211} 142}
212 143
144fn collect_import_map(db: &dyn DefDatabase, krate: CrateId) -> ImportMap {
145 let _p = profile::span("collect_import_map");
146
147 let def_map = db.crate_def_map(krate);
148 let mut import_map = ImportMap::default();
149
150 // We look only into modules that are public(ly reexported), starting with the crate root.
151 let empty = ImportPath { segments: vec![] };
152 let root = def_map.module_id(def_map.root());
153 let mut worklist = vec![(root, empty)];
154 while let Some((module, mod_path)) = worklist.pop() {
155 let ext_def_map;
156 let mod_data = if module.krate == krate {
157 &def_map[module.local_id]
158 } else {
159 // The crate might reexport a module defined in another crate.
160 ext_def_map = module.def_map(db);
161 &ext_def_map[module.local_id]
162 };
163
164 let visible_items = mod_data.scope.entries().filter_map(|(name, per_ns)| {
165 let per_ns = per_ns.filter_visibility(|vis| vis == Visibility::Public);
166 if per_ns.is_none() {
167 None
168 } else {
169 Some((name, per_ns))
170 }
171 });
172
173 for (name, per_ns) in visible_items {
174 let mk_path = || {
175 let mut path = mod_path.clone();
176 path.segments.push(name.clone());
177 path
178 };
179
180 for item in per_ns.iter_items() {
181 let path = mk_path();
182 let path_len = path.len();
183 let import_info =
184 ImportInfo { path, container: module, is_trait_assoc_item: false };
185
186 if let Some(ModuleDefId::TraitId(tr)) = item.as_module_def_id() {
187 import_map.collect_trait_assoc_items(
188 db,
189 tr,
190 matches!(item, ItemInNs::Types(_)),
191 &import_info,
192 );
193 }
194
195 match import_map.map.entry(item) {
196 Entry::Vacant(entry) => {
197 entry.insert(import_info);
198 }
199 Entry::Occupied(mut entry) => {
200 // If the new path is shorter, prefer that one.
201 if path_len < entry.get().path.len() {
202 *entry.get_mut() = import_info;
203 } else {
204 continue;
205 }
206 }
207 }
208
209 // If we've just added a path to a module, descend into it. We might traverse
210 // modules multiple times, but only if the new path to it is shorter than the
211 // first (else we `continue` above).
212 if let Some(ModuleDefId::ModuleId(mod_id)) = item.as_module_def_id() {
213 worklist.push((mod_id, mk_path()));
214 }
215 }
216 }
217 }
218
219 import_map
220}
221
213impl PartialEq for ImportMap { 222impl PartialEq for ImportMap {
214 fn eq(&self, other: &Self) -> bool { 223 fn eq(&self, other: &Self) -> bool {
215 // `fst` and `importables` are built from `map`, so we don't need to compare them. 224 // `fst` and `importables` are built from `map`, so we don't need to compare them.
@@ -240,17 +249,12 @@ impl fmt::Debug for ImportMap {
240} 249}
241 250
242fn fst_path(path: &ImportPath) -> String { 251fn fst_path(path: &ImportPath) -> String {
252 let _p = profile::span("fst_path");
243 let mut s = path.to_string(); 253 let mut s = path.to_string();
244 s.make_ascii_lowercase(); 254 s.make_ascii_lowercase();
245 s 255 s
246} 256}
247 257
248fn cmp((_, lhs): &(&ItemInNs, &ImportInfo), (_, rhs): &(&ItemInNs, &ImportInfo)) -> Ordering {
249 let lhs_str = fst_path(&lhs.path);
250 let rhs_str = fst_path(&rhs.path);
251 lhs_str.cmp(&rhs_str)
252}
253
254#[derive(Debug, Eq, PartialEq, Hash)] 258#[derive(Debug, Eq, PartialEq, Hash)]
255pub enum ImportKind { 259pub enum ImportKind {
256 Module, 260 Module,
@@ -338,6 +342,7 @@ impl Query {
338 } 342 }
339 343
340 fn import_matches(&self, import: &ImportInfo, enforce_lowercase: bool) -> bool { 344 fn import_matches(&self, import: &ImportInfo, enforce_lowercase: bool) -> bool {
345 let _p = profile::span("import_map::Query::import_matches");
341 if import.is_trait_assoc_item { 346 if import.is_trait_assoc_item {
342 if self.exclude_import_kinds.contains(&ImportKind::AssociatedItem) { 347 if self.exclude_import_kinds.contains(&ImportKind::AssociatedItem) {
343 return false; 348 return false;
diff --git a/crates/hir_def/src/lang_item.rs b/crates/hir_def/src/lang_item.rs
index 9e90f745c..3a45cbfa1 100644
--- a/crates/hir_def/src/lang_item.rs
+++ b/crates/hir_def/src/lang_item.rs
@@ -141,6 +141,7 @@ impl LangItems {
141 ) where 141 ) where
142 T: Into<AttrDefId> + Copy, 142 T: Into<AttrDefId> + Copy,
143 { 143 {
144 let _p = profile::span("collect_lang_item");
144 if let Some(lang_item_name) = lang_attr(db, item) { 145 if let Some(lang_item_name) = lang_attr(db, item) {
145 self.items.entry(lang_item_name).or_insert_with(|| constructor(item)); 146 self.items.entry(lang_item_name).or_insert_with(|| constructor(item));
146 } 147 }
diff --git a/crates/hir_def/src/nameres/collector.rs b/crates/hir_def/src/nameres/collector.rs
index d019ba3a9..93f30f23d 100644
--- a/crates/hir_def/src/nameres/collector.rs
+++ b/crates/hir_def/src/nameres/collector.rs
@@ -9,6 +9,7 @@ use base_db::{CrateId, Edition, FileId, ProcMacroId};
9use cfg::{CfgExpr, CfgOptions}; 9use cfg::{CfgExpr, CfgOptions};
10use hir_expand::{ 10use hir_expand::{
11 ast_id_map::FileAstId, 11 ast_id_map::FileAstId,
12 builtin_attr::find_builtin_attr,
12 builtin_derive::find_builtin_derive, 13 builtin_derive::find_builtin_derive,
13 builtin_macro::find_builtin_macro, 14 builtin_macro::find_builtin_macro,
14 name::{name, AsName, Name}, 15 name::{name, AsName, Name},
@@ -1836,7 +1837,8 @@ impl ModCollector<'_, '_> {
1836 let attrs = self.item_tree.attrs(self.def_collector.db, krate, ModItem::from(id).into()); 1837 let attrs = self.item_tree.attrs(self.def_collector.db, krate, ModItem::from(id).into());
1837 if attrs.by_key("rustc_builtin_macro").exists() { 1838 if attrs.by_key("rustc_builtin_macro").exists() {
1838 let macro_id = find_builtin_macro(&mac.name, krate, ast_id) 1839 let macro_id = find_builtin_macro(&mac.name, krate, ast_id)
1839 .or_else(|| find_builtin_derive(&mac.name, krate, ast_id)); 1840 .or_else(|| find_builtin_derive(&mac.name, krate, ast_id))
1841 .or_else(|| find_builtin_attr(&mac.name, krate, ast_id));
1840 1842
1841 match macro_id { 1843 match macro_id {
1842 Some(macro_id) => { 1844 Some(macro_id) => {
diff --git a/crates/hir_def/src/per_ns.rs b/crates/hir_def/src/per_ns.rs
index a594afce6..a9f13cb82 100644
--- a/crates/hir_def/src/per_ns.rs
+++ b/crates/hir_def/src/per_ns.rs
@@ -62,6 +62,7 @@ impl PerNs {
62 } 62 }
63 63
64 pub fn filter_visibility(self, mut f: impl FnMut(Visibility) -> bool) -> PerNs { 64 pub fn filter_visibility(self, mut f: impl FnMut(Visibility) -> bool) -> PerNs {
65 let _p = profile::span("PerNs::filter_visibility");
65 PerNs { 66 PerNs {
66 types: self.types.filter(|(_, v)| f(*v)), 67 types: self.types.filter(|(_, v)| f(*v)),
67 values: self.values.filter(|(_, v)| f(*v)), 68 values: self.values.filter(|(_, v)| f(*v)),
@@ -86,6 +87,7 @@ impl PerNs {
86 } 87 }
87 88
88 pub fn iter_items(self) -> impl Iterator<Item = ItemInNs> { 89 pub fn iter_items(self) -> impl Iterator<Item = ItemInNs> {
90 let _p = profile::span("PerNs::iter_items");
89 self.types 91 self.types
90 .map(|it| ItemInNs::Types(it.0)) 92 .map(|it| ItemInNs::Types(it.0))
91 .into_iter() 93 .into_iter()
diff --git a/crates/hir_expand/src/builtin_attr.rs b/crates/hir_expand/src/builtin_attr.rs
new file mode 100644
index 000000000..c8432005e
--- /dev/null
+++ b/crates/hir_expand/src/builtin_attr.rs
@@ -0,0 +1,67 @@
1//! Builtin derives.
2
3use syntax::ast;
4
5use crate::{db::AstDatabase, name, AstId, CrateId, MacroCallId, MacroDefId, MacroDefKind};
6
7macro_rules! register_builtin {
8 ( $(($name:ident, $variant:ident) => $expand:ident),* ) => {
9 #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
10 pub enum BuiltinAttrExpander {
11 $($variant),*
12 }
13
14 impl BuiltinAttrExpander {
15 pub fn expand(
16 &self,
17 db: &dyn AstDatabase,
18 id: MacroCallId,
19 tt: &tt::Subtree,
20 ) -> Result<tt::Subtree, mbe::ExpandError> {
21 let expander = match *self {
22 $( BuiltinAttrExpander::$variant => $expand, )*
23 };
24 expander(db, id, tt)
25 }
26
27 fn find_by_name(name: &name::Name) -> Option<Self> {
28 match name {
29 $( id if id == &name::name![$name] => Some(BuiltinAttrExpander::$variant), )*
30 _ => None,
31 }
32 }
33 }
34
35 };
36}
37
38register_builtin! {
39 (bench, Bench) => dummy_attr_expand,
40 (cfg_accessible, CfgAccessible) => dummy_attr_expand,
41 (cfg_eval, CfgEval) => dummy_attr_expand,
42 (derive, Derive) => dummy_attr_expand,
43 (global_allocator, GlobalAllocator) => dummy_attr_expand,
44 (test, Test) => dummy_attr_expand,
45 (test_case, TestCase) => dummy_attr_expand
46}
47
48pub fn find_builtin_attr(
49 ident: &name::Name,
50 krate: CrateId,
51 ast_id: AstId<ast::Macro>,
52) -> Option<MacroDefId> {
53 let expander = BuiltinAttrExpander::find_by_name(ident)?;
54 Some(MacroDefId {
55 krate,
56 kind: MacroDefKind::BuiltInAttr(expander, ast_id),
57 local_inner: false,
58 })
59}
60
61fn dummy_attr_expand(
62 _db: &dyn AstDatabase,
63 _id: MacroCallId,
64 tt: &tt::Subtree,
65) -> Result<tt::Subtree, mbe::ExpandError> {
66 Ok(tt.clone())
67}
diff --git a/crates/hir_expand/src/db.rs b/crates/hir_expand/src/db.rs
index 18a05579f..45e6e446a 100644
--- a/crates/hir_expand/src/db.rs
+++ b/crates/hir_expand/src/db.rs
@@ -12,9 +12,9 @@ use syntax::{
12}; 12};
13 13
14use crate::{ 14use crate::{
15 ast_id_map::AstIdMap, hygiene::HygieneFrame, input::process_macro_input, BuiltinDeriveExpander, 15 ast_id_map::AstIdMap, hygiene::HygieneFrame, input::process_macro_input, BuiltinAttrExpander,
16 BuiltinFnLikeExpander, HirFileId, HirFileIdRepr, MacroCallId, MacroCallKind, MacroCallLoc, 16 BuiltinDeriveExpander, BuiltinFnLikeExpander, HirFileId, HirFileIdRepr, MacroCallId,
17 MacroDefId, MacroDefKind, MacroFile, ProcMacroExpander, 17 MacroCallKind, MacroCallLoc, MacroDefId, MacroDefKind, MacroFile, ProcMacroExpander,
18}; 18};
19 19
20/// Total limit on the number of tokens produced by any macro invocation. 20/// Total limit on the number of tokens produced by any macro invocation.
@@ -31,6 +31,8 @@ pub enum TokenExpander {
31 MacroDef { mac: mbe::MacroDef, def_site_token_map: mbe::TokenMap }, 31 MacroDef { mac: mbe::MacroDef, def_site_token_map: mbe::TokenMap },
32 /// Stuff like `line!` and `file!`. 32 /// Stuff like `line!` and `file!`.
33 Builtin(BuiltinFnLikeExpander), 33 Builtin(BuiltinFnLikeExpander),
34 /// `global_allocator` and such.
35 BuiltinAttr(BuiltinAttrExpander),
34 /// `derive(Copy)` and such. 36 /// `derive(Copy)` and such.
35 BuiltinDerive(BuiltinDeriveExpander), 37 BuiltinDerive(BuiltinDeriveExpander),
36 /// The thing we love the most here in rust-analyzer -- procedural macros. 38 /// The thing we love the most here in rust-analyzer -- procedural macros.
@@ -49,6 +51,7 @@ impl TokenExpander {
49 TokenExpander::MacroDef { mac, .. } => mac.expand(tt), 51 TokenExpander::MacroDef { mac, .. } => mac.expand(tt),
50 TokenExpander::Builtin(it) => it.expand(db, id, tt), 52 TokenExpander::Builtin(it) => it.expand(db, id, tt),
51 // FIXME switch these to ExpandResult as well 53 // FIXME switch these to ExpandResult as well
54 TokenExpander::BuiltinAttr(it) => it.expand(db, id, tt).into(),
52 TokenExpander::BuiltinDerive(it) => it.expand(db, id, tt).into(), 55 TokenExpander::BuiltinDerive(it) => it.expand(db, id, tt).into(),
53 TokenExpander::ProcMacro(_) => { 56 TokenExpander::ProcMacro(_) => {
54 // We store the result in salsa db to prevent non-deterministic behavior in 57 // We store the result in salsa db to prevent non-deterministic behavior in
@@ -64,6 +67,7 @@ impl TokenExpander {
64 TokenExpander::MacroRules { mac, .. } => mac.map_id_down(id), 67 TokenExpander::MacroRules { mac, .. } => mac.map_id_down(id),
65 TokenExpander::MacroDef { mac, .. } => mac.map_id_down(id), 68 TokenExpander::MacroDef { mac, .. } => mac.map_id_down(id),
66 TokenExpander::Builtin(..) 69 TokenExpander::Builtin(..)
70 | TokenExpander::BuiltinAttr(..)
67 | TokenExpander::BuiltinDerive(..) 71 | TokenExpander::BuiltinDerive(..)
68 | TokenExpander::ProcMacro(..) => id, 72 | TokenExpander::ProcMacro(..) => id,
69 } 73 }
@@ -74,6 +78,7 @@ impl TokenExpander {
74 TokenExpander::MacroRules { mac, .. } => mac.map_id_up(id), 78 TokenExpander::MacroRules { mac, .. } => mac.map_id_up(id),
75 TokenExpander::MacroDef { mac, .. } => mac.map_id_up(id), 79 TokenExpander::MacroDef { mac, .. } => mac.map_id_up(id),
76 TokenExpander::Builtin(..) 80 TokenExpander::Builtin(..)
81 | TokenExpander::BuiltinAttr(..)
77 | TokenExpander::BuiltinDerive(..) 82 | TokenExpander::BuiltinDerive(..)
78 | TokenExpander::ProcMacro(..) => (id, mbe::Origin::Call), 83 | TokenExpander::ProcMacro(..) => (id, mbe::Origin::Call),
79 } 84 }
@@ -299,6 +304,9 @@ fn macro_def(db: &dyn AstDatabase, id: MacroDefId) -> Option<Arc<TokenExpander>>
299 } 304 }
300 }, 305 },
301 MacroDefKind::BuiltIn(expander, _) => Some(Arc::new(TokenExpander::Builtin(expander))), 306 MacroDefKind::BuiltIn(expander, _) => Some(Arc::new(TokenExpander::Builtin(expander))),
307 MacroDefKind::BuiltInAttr(expander, _) => {
308 Some(Arc::new(TokenExpander::BuiltinAttr(expander)))
309 }
302 MacroDefKind::BuiltInDerive(expander, _) => { 310 MacroDefKind::BuiltInDerive(expander, _) => {
303 Some(Arc::new(TokenExpander::BuiltinDerive(expander))) 311 Some(Arc::new(TokenExpander::BuiltinDerive(expander)))
304 } 312 }
diff --git a/crates/hir_expand/src/eager.rs b/crates/hir_expand/src/eager.rs
index 14af628a1..9093255f4 100644
--- a/crates/hir_expand/src/eager.rs
+++ b/crates/hir_expand/src/eager.rs
@@ -224,6 +224,7 @@ fn eager_macro_recur(
224 } 224 }
225 MacroDefKind::Declarative(_) 225 MacroDefKind::Declarative(_)
226 | MacroDefKind::BuiltIn(..) 226 | MacroDefKind::BuiltIn(..)
227 | MacroDefKind::BuiltInAttr(..)
227 | MacroDefKind::BuiltInDerive(..) 228 | MacroDefKind::BuiltInDerive(..)
228 | MacroDefKind::ProcMacro(..) => { 229 | MacroDefKind::ProcMacro(..) => {
229 let res = lazy_expand(db, &def, curr.with_value(child.clone()), krate); 230 let res = lazy_expand(db, &def, curr.with_value(child.clone()), krate);
diff --git a/crates/hir_expand/src/hygiene.rs b/crates/hir_expand/src/hygiene.rs
index d98913907..05c6c3fb1 100644
--- a/crates/hir_expand/src/hygiene.rs
+++ b/crates/hir_expand/src/hygiene.rs
@@ -192,6 +192,7 @@ impl HygieneFrame {
192 (info, Some(loc.def.krate), loc.def.local_inner) 192 (info, Some(loc.def.krate), loc.def.local_inner)
193 } 193 }
194 MacroDefKind::BuiltIn(..) => (info, Some(loc.def.krate), false), 194 MacroDefKind::BuiltIn(..) => (info, Some(loc.def.krate), false),
195 MacroDefKind::BuiltInAttr(..) => (info, None, false),
195 MacroDefKind::BuiltInDerive(..) => (info, None, false), 196 MacroDefKind::BuiltInDerive(..) => (info, None, false),
196 MacroDefKind::BuiltInEager(..) => (info, None, false), 197 MacroDefKind::BuiltInEager(..) => (info, None, false),
197 MacroDefKind::ProcMacro(..) => (info, None, false), 198 MacroDefKind::ProcMacro(..) => (info, None, false),
diff --git a/crates/hir_expand/src/lib.rs b/crates/hir_expand/src/lib.rs
index 618f26b95..623791b58 100644
--- a/crates/hir_expand/src/lib.rs
+++ b/crates/hir_expand/src/lib.rs
@@ -8,6 +8,7 @@ pub mod db;
8pub mod ast_id_map; 8pub mod ast_id_map;
9pub mod name; 9pub mod name;
10pub mod hygiene; 10pub mod hygiene;
11pub mod builtin_attr;
11pub mod builtin_derive; 12pub mod builtin_derive;
12pub mod builtin_macro; 13pub mod builtin_macro;
13pub mod proc_macro; 14pub mod proc_macro;
@@ -32,6 +33,7 @@ use syntax::{
32}; 33};
33 34
34use crate::ast_id_map::FileAstId; 35use crate::ast_id_map::FileAstId;
36use crate::builtin_attr::BuiltinAttrExpander;
35use crate::builtin_derive::BuiltinDeriveExpander; 37use crate::builtin_derive::BuiltinDeriveExpander;
36use crate::builtin_macro::{BuiltinFnLikeExpander, EagerExpander}; 38use crate::builtin_macro::{BuiltinFnLikeExpander, EagerExpander};
37use crate::proc_macro::ProcMacroExpander; 39use crate::proc_macro::ProcMacroExpander;
@@ -206,6 +208,7 @@ impl MacroDefId {
206 let id = match &self.kind { 208 let id = match &self.kind {
207 MacroDefKind::Declarative(id) => id, 209 MacroDefKind::Declarative(id) => id,
208 MacroDefKind::BuiltIn(_, id) => id, 210 MacroDefKind::BuiltIn(_, id) => id,
211 MacroDefKind::BuiltInAttr(_, id) => id,
209 MacroDefKind::BuiltInDerive(_, id) => id, 212 MacroDefKind::BuiltInDerive(_, id) => id,
210 MacroDefKind::BuiltInEager(_, id) => id, 213 MacroDefKind::BuiltInEager(_, id) => id,
211 MacroDefKind::ProcMacro(.., id) => return Either::Right(*id), 214 MacroDefKind::ProcMacro(.., id) => return Either::Right(*id),
@@ -223,6 +226,7 @@ pub enum MacroDefKind {
223 Declarative(AstId<ast::Macro>), 226 Declarative(AstId<ast::Macro>),
224 BuiltIn(BuiltinFnLikeExpander, AstId<ast::Macro>), 227 BuiltIn(BuiltinFnLikeExpander, AstId<ast::Macro>),
225 // FIXME: maybe just Builtin and rename BuiltinFnLikeExpander to BuiltinExpander 228 // FIXME: maybe just Builtin and rename BuiltinFnLikeExpander to BuiltinExpander
229 BuiltInAttr(BuiltinAttrExpander, AstId<ast::Macro>),
226 BuiltInDerive(BuiltinDeriveExpander, AstId<ast::Macro>), 230 BuiltInDerive(BuiltinDeriveExpander, AstId<ast::Macro>),
227 BuiltInEager(EagerExpander, AstId<ast::Macro>), 231 BuiltInEager(EagerExpander, AstId<ast::Macro>),
228 ProcMacro(ProcMacroExpander, ProcMacroKind, AstId<ast::Fn>), 232 ProcMacro(ProcMacroExpander, ProcMacroKind, AstId<ast::Fn>),
diff --git a/crates/hir_expand/src/name.rs b/crates/hir_expand/src/name.rs
index 00b8adc1e..376fe130f 100644
--- a/crates/hir_expand/src/name.rs
+++ b/crates/hir_expand/src/name.rs
@@ -160,7 +160,6 @@ pub mod known {
160 str, 160 str,
161 // Special names 161 // Special names
162 macro_rules, 162 macro_rules,
163 derive,
164 doc, 163 doc,
165 cfg, 164 cfg,
166 cfg_attr, 165 cfg_attr,
@@ -240,6 +239,14 @@ pub mod known {
240 PartialOrd, 239 PartialOrd,
241 Eq, 240 Eq,
242 PartialEq, 241 PartialEq,
242 // Builtin attributes
243 bench,
244 cfg_accessible,
245 cfg_eval,
246 derive,
247 global_allocator,
248 test,
249 test_case,
243 // Safe intrinsics 250 // Safe intrinsics
244 abort, 251 abort,
245 size_of, 252 size_of,
diff --git a/crates/ide/src/prime_caches.rs b/crates/ide/src/prime_caches.rs
index d912a01b8..36801c964 100644
--- a/crates/ide/src/prime_caches.rs
+++ b/crates/ide/src/prime_caches.rs
@@ -33,14 +33,15 @@ pub(crate) fn prime_caches(db: &RootDatabase, cb: &(dyn Fn(PrimeCachesProgress)
33 // FIXME: This would be easy to parallelize, since it's in the ideal ordering for that. 33 // FIXME: This would be easy to parallelize, since it's in the ideal ordering for that.
34 // Unfortunately rayon prevents panics from propagation out of a `scope`, which breaks 34 // Unfortunately rayon prevents panics from propagation out of a `scope`, which breaks
35 // cancellation, so we cannot use rayon. 35 // cancellation, so we cannot use rayon.
36 for (i, krate) in topo.iter().enumerate() { 36 for (i, &crate_id) in topo.iter().enumerate() {
37 let crate_name = graph[*krate].display_name.as_deref().unwrap_or_default().to_string(); 37 let crate_name = graph[crate_id].display_name.as_deref().unwrap_or_default().to_string();
38 38
39 cb(PrimeCachesProgress::StartedOnCrate { 39 cb(PrimeCachesProgress::StartedOnCrate {
40 on_crate: crate_name, 40 on_crate: crate_name,
41 n_done: i, 41 n_done: i,
42 n_total: topo.len(), 42 n_total: topo.len(),
43 }); 43 });
44 db.crate_def_map(*krate); 44 db.crate_def_map(crate_id);
45 db.import_map(crate_id);
45 } 46 }
46} 47}
diff --git a/crates/ide/src/references.rs b/crates/ide/src/references.rs
index ae492a264..f8b64a669 100644
--- a/crates/ide/src/references.rs
+++ b/crates/ide/src/references.rs
@@ -1380,4 +1380,24 @@ lib::foo!();
1380 "#]], 1380 "#]],
1381 ); 1381 );
1382 } 1382 }
1383
1384 #[test]
1385 fn macro_doesnt_reference_attribute_on_call() {
1386 check(
1387 r#"
1388macro_rules! m {
1389 () => {};
1390}
1391
1392#[proc_macro_test::attr_noop]
1393m$0!();
1394
1395"#,
1396 expect![[r#"
1397 m Macro FileId(0) 0..32 13..14
1398
1399 FileId(0) 64..65
1400 "#]],
1401 );
1402 }
1383} 1403}
diff --git a/crates/ide_assists/src/handlers/remove_unused_param.rs b/crates/ide_assists/src/handlers/remove_unused_param.rs
index 2699d2861..fabfe7e93 100644
--- a/crates/ide_assists/src/handlers/remove_unused_param.rs
+++ b/crates/ide_assists/src/handlers/remove_unused_param.rs
@@ -37,8 +37,20 @@ pub(crate) fn remove_unused_param(acc: &mut Assists, ctx: &AssistContext) -> Opt
37 _ => return None, 37 _ => return None,
38 }; 38 };
39 let func = param.syntax().ancestors().find_map(ast::Fn::cast)?; 39 let func = param.syntax().ancestors().find_map(ast::Fn::cast)?;
40 let param_position = func.param_list()?.params().position(|it| it == param)?;
41 40
41 // check if fn is in impl Trait for ..
42 if func
43 .syntax()
44 .parent() // AssocItemList
45 .and_then(|x| x.parent())
46 .and_then(ast::Impl::cast)
47 .map_or(false, |imp| imp.trait_().is_some())
48 {
49 cov_mark::hit!(trait_impl);
50 return None;
51 }
52
53 let param_position = func.param_list()?.params().position(|it| it == param)?;
42 let fn_def = { 54 let fn_def = {
43 let func = ctx.sema.to_def(&func)?; 55 let func = ctx.sema.to_def(&func)?;
44 Definition::ModuleDef(func.into()) 56 Definition::ModuleDef(func.into())
@@ -254,6 +266,22 @@ fn main() { foo(9, 2) }
254 } 266 }
255 267
256 #[test] 268 #[test]
269 fn trait_impl() {
270 cov_mark::check!(trait_impl);
271 check_assist_not_applicable(
272 remove_unused_param,
273 r#"
274trait Trait {
275 fn foo(x: i32);
276}
277impl Trait for () {
278 fn foo($0x: i32) {}
279}
280"#,
281 );
282 }
283
284 #[test]
257 fn remove_across_files() { 285 fn remove_across_files() {
258 check_assist( 286 check_assist(
259 remove_unused_param, 287 remove_unused_param,
diff --git a/crates/ide_completion/src/completions/qualified_path.rs b/crates/ide_completion/src/completions/qualified_path.rs
index 0b0a81410..58d4dd9ee 100644
--- a/crates/ide_completion/src/completions/qualified_path.rs
+++ b/crates/ide_completion/src/completions/qualified_path.rs
@@ -657,6 +657,32 @@ fn main() { let _ = crate::$0 }
657 } 657 }
658 658
659 #[test] 659 #[test]
660 fn does_not_complete_non_fn_macros() {
661 check(
662 r#"
663mod m {
664 #[rustc_builtin_macro]
665 pub macro Clone {}
666}
667
668fn f() {m::$0}
669"#,
670 expect![[r#""#]],
671 );
672 check(
673 r#"
674mod m {
675 #[rustc_builtin_macro]
676 pub macro bench {}
677}
678
679fn f() {m::$0}
680"#,
681 expect![[r#""#]],
682 );
683 }
684
685 #[test]
660 fn completes_in_assoc_item_list() { 686 fn completes_in_assoc_item_list() {
661 check( 687 check(
662 r#" 688 r#"
diff --git a/crates/ide_completion/src/completions/unqualified_path.rs b/crates/ide_completion/src/completions/unqualified_path.rs
index 1f6c4069f..b1e6b2b77 100644
--- a/crates/ide_completion/src/completions/unqualified_path.rs
+++ b/crates/ide_completion/src/completions/unqualified_path.rs
@@ -481,14 +481,14 @@ impl S {
481 ); 481 );
482 check( 482 check(
483 r#" 483 r#"
484mod m { 484#[rustc_builtin_macro]
485 #[rustc_builtin_macro] 485pub macro bench {}
486 pub macro Clone {}
487}
488 486
489fn f() {m::$0} 487fn f() {$0}
490"#, 488"#,
491 expect![[r#""#]], 489 expect![[r#"
490 fn f() fn()
491 "#]],
492 ); 492 );
493 } 493 }
494 494
diff --git a/crates/ide_completion/src/render.rs b/crates/ide_completion/src/render.rs
index 7118183fe..902df46ca 100644
--- a/crates/ide_completion/src/render.rs
+++ b/crates/ide_completion/src/render.rs
@@ -24,34 +24,34 @@ use crate::{
24 CompletionContext, CompletionItem, CompletionItemKind, CompletionKind, CompletionRelevance, 24 CompletionContext, CompletionItem, CompletionItemKind, CompletionKind, CompletionRelevance,
25}; 25};
26 26
27pub(crate) fn render_field<'a>( 27pub(crate) fn render_field(
28 ctx: RenderContext<'a>, 28 ctx: RenderContext<'_>,
29 receiver: Option<hir::Name>, 29 receiver: Option<hir::Name>,
30 field: hir::Field, 30 field: hir::Field,
31 ty: &hir::Type, 31 ty: &hir::Type,
32) -> CompletionItem { 32) -> CompletionItem {
33 Render::new(ctx).render_field(receiver, field, ty) 33 render_field_(ctx, receiver, field, ty)
34} 34}
35 35
36pub(crate) fn render_tuple_field<'a>( 36pub(crate) fn render_tuple_field(
37 ctx: RenderContext<'a>, 37 ctx: RenderContext<'_>,
38 receiver: Option<hir::Name>, 38 receiver: Option<hir::Name>,
39 field: usize, 39 field: usize,
40 ty: &hir::Type, 40 ty: &hir::Type,
41) -> CompletionItem { 41) -> CompletionItem {
42 Render::new(ctx).render_tuple_field(receiver, field, ty) 42 render_tuple_field_(ctx, receiver, field, ty)
43} 43}
44 44
45pub(crate) fn render_resolution<'a>( 45pub(crate) fn render_resolution(
46 ctx: RenderContext<'a>, 46 ctx: RenderContext<'_>,
47 local_name: hir::Name, 47 local_name: hir::Name,
48 resolution: &hir::ScopeDef, 48 resolution: &hir::ScopeDef,
49) -> Option<CompletionItem> { 49) -> Option<CompletionItem> {
50 Render::new(ctx).render_resolution(local_name, None, resolution) 50 render_resolution_(ctx, local_name, None, resolution)
51} 51}
52 52
53pub(crate) fn render_resolution_with_import<'a>( 53pub(crate) fn render_resolution_with_import(
54 ctx: RenderContext<'a>, 54 ctx: RenderContext<'_>,
55 import_edit: ImportEdit, 55 import_edit: ImportEdit,
56) -> Option<CompletionItem> { 56) -> Option<CompletionItem> {
57 let resolution = hir::ScopeDef::from(import_edit.import.original_item); 57 let resolution = hir::ScopeDef::from(import_edit.import.original_item);
@@ -64,12 +64,10 @@ pub(crate) fn render_resolution_with_import<'a>(
64 hir::ScopeDef::ModuleDef(hir::ModuleDef::TypeAlias(t)) => t.name(ctx.completion.db), 64 hir::ScopeDef::ModuleDef(hir::ModuleDef::TypeAlias(t)) => t.name(ctx.completion.db),
65 _ => item_name(ctx.db(), import_edit.import.original_item)?, 65 _ => item_name(ctx.db(), import_edit.import.original_item)?,
66 }; 66 };
67 Render::new(ctx).render_resolution(local_name, Some(import_edit), &resolution).map( 67 render_resolution_(ctx, local_name, Some(import_edit), &resolution).map(|mut item| {
68 |mut item| { 68 item.completion_kind = CompletionKind::Magic;
69 item.completion_kind = CompletionKind::Magic; 69 item
70 item 70 })
71 },
72 )
73} 71}
74 72
75/// Interface for data and methods required for items rendering. 73/// Interface for data and methods required for items rendering.
@@ -121,216 +119,188 @@ impl<'a> RenderContext<'a> {
121 } 119 }
122} 120}
123 121
124/// Generic renderer for completion items. 122fn render_field_(
125#[derive(Debug)] 123 ctx: RenderContext<'_>,
126struct Render<'a> { 124 receiver: Option<hir::Name>,
127 ctx: RenderContext<'a>, 125 field: hir::Field,
128} 126 ty: &hir::Type,
129 127) -> CompletionItem {
130impl<'a> Render<'a> { 128 let is_deprecated = ctx.is_deprecated(field);
131 fn new(ctx: RenderContext<'a>) -> Render<'a> { 129 let name = field.name(ctx.db()).to_string();
132 Render { ctx } 130 let mut item = CompletionItem::new(
131 CompletionKind::Reference,
132 ctx.source_range(),
133 receiver.map_or_else(|| name.clone(), |receiver| format!("{}.{}", receiver, name)),
134 );
135 item.kind(SymbolKind::Field)
136 .detail(ty.display(ctx.db()).to_string())
137 .set_documentation(field.docs(ctx.db()))
138 .set_deprecated(is_deprecated);
139
140 item.set_relevance(CompletionRelevance {
141 type_match: compute_type_match(ctx.completion, ty),
142 exact_name_match: compute_exact_name_match(ctx.completion, &name),
143 ..CompletionRelevance::default()
144 });
145
146 if let Some(_ref_match) = compute_ref_match(ctx.completion, ty) {
147 // FIXME
148 // For now we don't properly calculate the edits for ref match
149 // completions on struct fields, so we've disabled them. See #8058.
133 } 150 }
134 151
135 fn render_field( 152 item.build()
136 &self, 153}
137 receiver: Option<hir::Name>,
138 field: hir::Field,
139 ty: &hir::Type,
140 ) -> CompletionItem {
141 let is_deprecated = self.ctx.is_deprecated(field);
142 let name = field.name(self.ctx.db()).to_string();
143 let mut item = CompletionItem::new(
144 CompletionKind::Reference,
145 self.ctx.source_range(),
146 receiver.map_or_else(|| name.clone(), |receiver| format!("{}.{}", receiver, name)),
147 );
148 item.kind(SymbolKind::Field)
149 .detail(ty.display(self.ctx.db()).to_string())
150 .set_documentation(field.docs(self.ctx.db()))
151 .set_deprecated(is_deprecated);
152
153 item.set_relevance(CompletionRelevance {
154 type_match: compute_type_match(self.ctx.completion, ty),
155 exact_name_match: compute_exact_name_match(self.ctx.completion, &name),
156 ..CompletionRelevance::default()
157 });
158
159 if let Some(_ref_match) = compute_ref_match(self.ctx.completion, ty) {
160 // FIXME
161 // For now we don't properly calculate the edits for ref match
162 // completions on struct fields, so we've disabled them. See #8058.
163 }
164 154
165 item.build() 155fn render_tuple_field_(
166 } 156 ctx: RenderContext<'_>,
157 receiver: Option<hir::Name>,
158 field: usize,
159 ty: &hir::Type,
160) -> CompletionItem {
161 let mut item = CompletionItem::new(
162 CompletionKind::Reference,
163 ctx.source_range(),
164 receiver.map_or_else(|| field.to_string(), |receiver| format!("{}.{}", receiver, field)),
165 );
167 166
168 fn render_tuple_field( 167 item.kind(SymbolKind::Field).detail(ty.display(ctx.db()).to_string());
169 &self,
170 receiver: Option<hir::Name>,
171 field: usize,
172 ty: &hir::Type,
173 ) -> CompletionItem {
174 let mut item = CompletionItem::new(
175 CompletionKind::Reference,
176 self.ctx.source_range(),
177 receiver
178 .map_or_else(|| field.to_string(), |receiver| format!("{}.{}", receiver, field)),
179 );
180 168
181 item.kind(SymbolKind::Field).detail(ty.display(self.ctx.db()).to_string()); 169 item.build()
170}
182 171
183 item.build() 172fn render_resolution_(
184 } 173 ctx: RenderContext<'_>,
174 local_name: hir::Name,
175 import_to_add: Option<ImportEdit>,
176 resolution: &hir::ScopeDef,
177) -> Option<CompletionItem> {
178 let _p = profile::span("render_resolution");
179 use hir::ModuleDef::*;
185 180
186 fn render_resolution( 181 let completion_kind = match resolution {
187 self, 182 hir::ScopeDef::ModuleDef(BuiltinType(..)) => CompletionKind::BuiltinType,
188 local_name: hir::Name, 183 _ => CompletionKind::Reference,
189 import_to_add: Option<ImportEdit>, 184 };
190 resolution: &hir::ScopeDef,
191 ) -> Option<CompletionItem> {
192 let _p = profile::span("render_resolution");
193 use hir::ModuleDef::*;
194
195 let completion_kind = match resolution {
196 hir::ScopeDef::ModuleDef(BuiltinType(..)) => CompletionKind::BuiltinType,
197 _ => CompletionKind::Reference,
198 };
199 185
200 let kind = match resolution { 186 let kind = match resolution {
201 hir::ScopeDef::ModuleDef(Function(func)) => { 187 hir::ScopeDef::ModuleDef(Function(func)) => {
202 return render_fn(self.ctx, import_to_add, Some(local_name), *func); 188 return render_fn(ctx, import_to_add, Some(local_name), *func);
203 } 189 }
204 hir::ScopeDef::ModuleDef(Variant(_)) 190 hir::ScopeDef::ModuleDef(Variant(_)) if ctx.completion.is_pat_or_const.is_some() => {
205 if self.ctx.completion.is_pat_or_const.is_some() => 191 CompletionItemKind::SymbolKind(SymbolKind::Variant)
206 { 192 }
207 CompletionItemKind::SymbolKind(SymbolKind::Variant) 193 hir::ScopeDef::ModuleDef(Variant(var)) => {
208 } 194 let item = render_variant(ctx, import_to_add, Some(local_name), *var, None);
209 hir::ScopeDef::ModuleDef(Variant(var)) => { 195 return Some(item);
210 let item = render_variant(self.ctx, import_to_add, Some(local_name), *var, None); 196 }
211 return Some(item); 197 hir::ScopeDef::MacroDef(mac) => {
212 } 198 let item = render_macro(ctx, import_to_add, local_name, *mac);
213 hir::ScopeDef::MacroDef(mac) => { 199 return item;
214 let item = render_macro(self.ctx, import_to_add, local_name, *mac); 200 }
215 return item;
216 }
217 201
218 hir::ScopeDef::ModuleDef(Module(..)) => { 202 hir::ScopeDef::ModuleDef(Module(..)) => CompletionItemKind::SymbolKind(SymbolKind::Module),
219 CompletionItemKind::SymbolKind(SymbolKind::Module) 203 hir::ScopeDef::ModuleDef(Adt(adt)) => CompletionItemKind::SymbolKind(match adt {
220 } 204 hir::Adt::Struct(_) => SymbolKind::Struct,
221 hir::ScopeDef::ModuleDef(Adt(adt)) => CompletionItemKind::SymbolKind(match adt { 205 hir::Adt::Union(_) => SymbolKind::Union,
222 hir::Adt::Struct(_) => SymbolKind::Struct, 206 hir::Adt::Enum(_) => SymbolKind::Enum,
223 hir::Adt::Union(_) => SymbolKind::Union, 207 }),
224 hir::Adt::Enum(_) => SymbolKind::Enum, 208 hir::ScopeDef::ModuleDef(Const(..)) => CompletionItemKind::SymbolKind(SymbolKind::Const),
225 }), 209 hir::ScopeDef::ModuleDef(Static(..)) => CompletionItemKind::SymbolKind(SymbolKind::Static),
226 hir::ScopeDef::ModuleDef(Const(..)) => { 210 hir::ScopeDef::ModuleDef(Trait(..)) => CompletionItemKind::SymbolKind(SymbolKind::Trait),
227 CompletionItemKind::SymbolKind(SymbolKind::Const) 211 hir::ScopeDef::ModuleDef(TypeAlias(..)) => {
228 } 212 CompletionItemKind::SymbolKind(SymbolKind::TypeAlias)
229 hir::ScopeDef::ModuleDef(Static(..)) => { 213 }
230 CompletionItemKind::SymbolKind(SymbolKind::Static) 214 hir::ScopeDef::ModuleDef(BuiltinType(..)) => CompletionItemKind::BuiltinType,
231 } 215 hir::ScopeDef::GenericParam(param) => CompletionItemKind::SymbolKind(match param {
232 hir::ScopeDef::ModuleDef(Trait(..)) => { 216 hir::GenericParam::TypeParam(_) => SymbolKind::TypeParam,
233 CompletionItemKind::SymbolKind(SymbolKind::Trait) 217 hir::GenericParam::LifetimeParam(_) => SymbolKind::LifetimeParam,
234 } 218 hir::GenericParam::ConstParam(_) => SymbolKind::ConstParam,
235 hir::ScopeDef::ModuleDef(TypeAlias(..)) => { 219 }),
236 CompletionItemKind::SymbolKind(SymbolKind::TypeAlias) 220 hir::ScopeDef::Local(..) => CompletionItemKind::SymbolKind(SymbolKind::Local),
237 } 221 hir::ScopeDef::Label(..) => CompletionItemKind::SymbolKind(SymbolKind::Label),
238 hir::ScopeDef::ModuleDef(BuiltinType(..)) => CompletionItemKind::BuiltinType, 222 hir::ScopeDef::AdtSelfType(..) | hir::ScopeDef::ImplSelfType(..) => {
239 hir::ScopeDef::GenericParam(param) => CompletionItemKind::SymbolKind(match param { 223 CompletionItemKind::SymbolKind(SymbolKind::SelfParam)
240 hir::GenericParam::TypeParam(_) => SymbolKind::TypeParam, 224 }
241 hir::GenericParam::LifetimeParam(_) => SymbolKind::LifetimeParam, 225 hir::ScopeDef::Unknown => {
242 hir::GenericParam::ConstParam(_) => SymbolKind::ConstParam, 226 let mut item = CompletionItem::new(
243 }), 227 CompletionKind::Reference,
244 hir::ScopeDef::Local(..) => CompletionItemKind::SymbolKind(SymbolKind::Local), 228 ctx.source_range(),
245 hir::ScopeDef::Label(..) => CompletionItemKind::SymbolKind(SymbolKind::Label), 229 local_name.to_string(),
246 hir::ScopeDef::AdtSelfType(..) | hir::ScopeDef::ImplSelfType(..) => { 230 );
247 CompletionItemKind::SymbolKind(SymbolKind::SelfParam) 231 item.kind(CompletionItemKind::UnresolvedReference).add_import(import_to_add);
248 } 232 return Some(item.build());
249 hir::ScopeDef::Unknown => { 233 }
250 let mut item = CompletionItem::new( 234 };
251 CompletionKind::Reference,
252 self.ctx.source_range(),
253 local_name.to_string(),
254 );
255 item.kind(CompletionItemKind::UnresolvedReference).add_import(import_to_add);
256 return Some(item.build());
257 }
258 };
259 235
260 let local_name = local_name.to_string(); 236 let local_name = local_name.to_string();
261 let mut item = 237 let mut item = CompletionItem::new(completion_kind, ctx.source_range(), local_name.clone());
262 CompletionItem::new(completion_kind, self.ctx.source_range(), local_name.clone()); 238 if let hir::ScopeDef::Local(local) = resolution {
263 if let hir::ScopeDef::Local(local) = resolution { 239 let ty = local.ty(ctx.db());
264 let ty = local.ty(self.ctx.db()); 240 if !ty.is_unknown() {
265 if !ty.is_unknown() { 241 item.detail(ty.display(ctx.db()).to_string());
266 item.detail(ty.display(self.ctx.db()).to_string()); 242 }
267 }
268 243
269 item.set_relevance(CompletionRelevance { 244 item.set_relevance(CompletionRelevance {
270 type_match: compute_type_match(self.ctx.completion, &ty), 245 type_match: compute_type_match(ctx.completion, &ty),
271 exact_name_match: compute_exact_name_match(self.ctx.completion, &local_name), 246 exact_name_match: compute_exact_name_match(ctx.completion, &local_name),
272 is_local: true, 247 is_local: true,
273 ..CompletionRelevance::default() 248 ..CompletionRelevance::default()
274 }); 249 });
275 250
276 if let Some(ref_match) = compute_ref_match(self.ctx.completion, &ty) { 251 if let Some(ref_match) = compute_ref_match(ctx.completion, &ty) {
277 item.ref_match(ref_match); 252 item.ref_match(ref_match);
278 } 253 }
279 }; 254 };
280 255
281 // Add `<>` for generic types 256 // Add `<>` for generic types
282 if matches!( 257 if matches!(
283 self.ctx.completion.path_context, 258 ctx.completion.path_context,
284 Some(PathCompletionContext { kind: Some(PathKind::Type), has_type_args: false, .. }) 259 Some(PathCompletionContext { kind: Some(PathKind::Type), has_type_args: false, .. })
285 ) && self.ctx.completion.config.add_call_parenthesis 260 ) && ctx.completion.config.add_call_parenthesis
286 { 261 {
287 if let Some(cap) = self.ctx.snippet_cap() { 262 if let Some(cap) = ctx.snippet_cap() {
288 let has_non_default_type_params = match resolution { 263 let has_non_default_type_params = match resolution {
289 hir::ScopeDef::ModuleDef(Adt(it)) => { 264 hir::ScopeDef::ModuleDef(Adt(it)) => it.has_non_default_type_params(ctx.db()),
290 it.has_non_default_type_params(self.ctx.db()) 265 hir::ScopeDef::ModuleDef(TypeAlias(it)) => it.has_non_default_type_params(ctx.db()),
291 } 266 _ => false,
292 hir::ScopeDef::ModuleDef(TypeAlias(it)) => { 267 };
293 it.has_non_default_type_params(self.ctx.db()) 268 if has_non_default_type_params {
294 } 269 cov_mark::hit!(inserts_angle_brackets_for_generics);
295 _ => false, 270 item.lookup_by(local_name.clone())
296 }; 271 .label(format!("{}<…>", local_name))
297 if has_non_default_type_params { 272 .insert_snippet(cap, format!("{}<$0>", local_name));
298 cov_mark::hit!(inserts_angle_brackets_for_generics);
299 item.lookup_by(local_name.clone())
300 .label(format!("{}<…>", local_name))
301 .insert_snippet(cap, format!("{}<$0>", local_name));
302 }
303 } 273 }
304 } 274 }
305 item.kind(kind)
306 .add_import(import_to_add)
307 .set_documentation(self.docs(resolution))
308 .set_deprecated(self.is_deprecated(resolution));
309 Some(item.build())
310 } 275 }
276 item.kind(kind)
277 .add_import(import_to_add)
278 .set_documentation(scope_def_docs(ctx.db(), resolution))
279 .set_deprecated(scope_def_is_deprecated(&ctx, resolution));
280 Some(item.build())
281}
311 282
312 fn docs(&self, resolution: &hir::ScopeDef) -> Option<hir::Documentation> { 283fn scope_def_docs(db: &RootDatabase, resolution: &hir::ScopeDef) -> Option<hir::Documentation> {
313 use hir::ModuleDef::*; 284 use hir::ModuleDef::*;
314 match resolution { 285 match resolution {
315 hir::ScopeDef::ModuleDef(Module(it)) => it.docs(self.ctx.db()), 286 hir::ScopeDef::ModuleDef(Module(it)) => it.docs(db),
316 hir::ScopeDef::ModuleDef(Adt(it)) => it.docs(self.ctx.db()), 287 hir::ScopeDef::ModuleDef(Adt(it)) => it.docs(db),
317 hir::ScopeDef::ModuleDef(Variant(it)) => it.docs(self.ctx.db()), 288 hir::ScopeDef::ModuleDef(Variant(it)) => it.docs(db),
318 hir::ScopeDef::ModuleDef(Const(it)) => it.docs(self.ctx.db()), 289 hir::ScopeDef::ModuleDef(Const(it)) => it.docs(db),
319 hir::ScopeDef::ModuleDef(Static(it)) => it.docs(self.ctx.db()), 290 hir::ScopeDef::ModuleDef(Static(it)) => it.docs(db),
320 hir::ScopeDef::ModuleDef(Trait(it)) => it.docs(self.ctx.db()), 291 hir::ScopeDef::ModuleDef(Trait(it)) => it.docs(db),
321 hir::ScopeDef::ModuleDef(TypeAlias(it)) => it.docs(self.ctx.db()), 292 hir::ScopeDef::ModuleDef(TypeAlias(it)) => it.docs(db),
322 _ => None, 293 _ => None,
323 }
324 } 294 }
295}
325 296
326 fn is_deprecated(&self, resolution: &hir::ScopeDef) -> bool { 297fn scope_def_is_deprecated(ctx: &RenderContext<'_>, resolution: &hir::ScopeDef) -> bool {
327 match resolution { 298 match resolution {
328 hir::ScopeDef::ModuleDef(it) => self.ctx.is_deprecated_assoc_item(*it), 299 hir::ScopeDef::ModuleDef(it) => ctx.is_deprecated_assoc_item(*it),
329 hir::ScopeDef::MacroDef(it) => self.ctx.is_deprecated(*it), 300 hir::ScopeDef::MacroDef(it) => ctx.is_deprecated(*it),
330 hir::ScopeDef::GenericParam(it) => self.ctx.is_deprecated(*it), 301 hir::ScopeDef::GenericParam(it) => ctx.is_deprecated(*it),
331 hir::ScopeDef::AdtSelfType(it) => self.ctx.is_deprecated(*it), 302 hir::ScopeDef::AdtSelfType(it) => ctx.is_deprecated(*it),
332 _ => false, 303 _ => false,
333 }
334 } 304 }
335} 305}
336 306
diff --git a/crates/ide_db/src/defs.rs b/crates/ide_db/src/defs.rs
index 1dcccbb8b..1b69d72f9 100644
--- a/crates/ide_db/src/defs.rs
+++ b/crates/ide_db/src/defs.rs
@@ -357,9 +357,9 @@ impl NameRefClass {
357 } 357 }
358 } 358 }
359 359
360 if let Some(macro_call) = parent.ancestors().find_map(ast::MacroCall::cast) { 360 if let Some(path) = name_ref.syntax().ancestors().find_map(ast::Path::cast) {
361 if let Some(path) = macro_call.path() { 361 if path.qualifier().is_none() {
362 if path.qualifier().is_none() { 362 if let Some(macro_call) = path.syntax().parent().and_then(ast::MacroCall::cast) {
363 // Only use this to resolve single-segment macro calls like `foo!()`. Multi-segment 363 // Only use this to resolve single-segment macro calls like `foo!()`. Multi-segment
364 // paths are handled below (allowing `log$0::info!` to resolve to the log crate). 364 // paths are handled below (allowing `log$0::info!` to resolve to the log crate).
365 if let Some(macro_def) = sema.resolve_macro_call(&macro_call) { 365 if let Some(macro_def) = sema.resolve_macro_call(&macro_call) {
@@ -367,9 +367,7 @@ impl NameRefClass {
367 } 367 }
368 } 368 }
369 } 369 }
370 }
371 370
372 if let Some(path) = name_ref.syntax().ancestors().find_map(ast::Path::cast) {
373 if let Some(resolved) = sema.resolve_path(&path) { 371 if let Some(resolved) = sema.resolve_path(&path) {
374 if path.syntax().parent().and_then(ast::Attr::cast).is_some() { 372 if path.syntax().parent().and_then(ast::Attr::cast).is_some() {
375 if let PathResolution::Def(ModuleDef::Function(func)) = resolved { 373 if let PathResolution::Def(ModuleDef::Function(func)) = resolved {
diff --git a/crates/ide_db/src/symbol_index.rs b/crates/ide_db/src/symbol_index.rs
index 5c372a7e5..000f87a85 100644
--- a/crates/ide_db/src/symbol_index.rs
+++ b/crates/ide_db/src/symbol_index.rs
@@ -197,6 +197,7 @@ pub fn world_symbols(db: &RootDatabase, query: Query) -> Vec<FileSymbol> {
197} 197}
198 198
199pub fn crate_symbols(db: &RootDatabase, krate: CrateId, query: Query) -> Vec<FileSymbol> { 199pub fn crate_symbols(db: &RootDatabase, krate: CrateId, query: Query) -> Vec<FileSymbol> {
200 let _p = profile::span("crate_symbols").detail(|| format!("{:?}", query));
200 // FIXME(#4842): This now depends on CrateDefMap, why not build the entire symbol index from 201 // FIXME(#4842): This now depends on CrateDefMap, why not build the entire symbol index from
201 // that instead? 202 // that instead?
202 203
@@ -321,6 +322,7 @@ impl SymbolIndex {
321 322
322impl Query { 323impl Query {
323 pub(crate) fn search(self, indices: &[&SymbolIndex]) -> Vec<FileSymbol> { 324 pub(crate) fn search(self, indices: &[&SymbolIndex]) -> Vec<FileSymbol> {
325 let _p = profile::span("symbol_index::Query::search");
324 let mut op = fst::map::OpBuilder::new(); 326 let mut op = fst::map::OpBuilder::new();
325 for file_symbols in indices.iter() { 327 for file_symbols in indices.iter() {
326 let automaton = fst::automaton::Subsequence::new(&self.lowercased); 328 let automaton = fst::automaton::Subsequence::new(&self.lowercased);
diff --git a/crates/profile/Cargo.toml b/crates/profile/Cargo.toml
index 1a8c8f862..653d3d983 100644
--- a/crates/profile/Cargo.toml
+++ b/crates/profile/Cargo.toml
@@ -20,6 +20,9 @@ jemalloc-ctl = { version = "0.4.1", package = "tikv-jemalloc-ctl", optional = tr
20[target.'cfg(target_os = "linux")'.dependencies] 20[target.'cfg(target_os = "linux")'.dependencies]
21perf-event = "0.4" 21perf-event = "0.4"
22 22
23[target.'cfg(windows)'.dependencies]
24winapi = { version = "0.3.8", features = ["psapi"] }
25
23[features] 26[features]
24cpu_profiler = [] 27cpu_profiler = []
25jemalloc = ["jemalloc-ctl"] 28jemalloc = ["jemalloc-ctl"]
diff --git a/crates/profile/src/memory_usage.rs b/crates/profile/src/memory_usage.rs
index 2917ded60..6ef58c9c1 100644
--- a/crates/profile/src/memory_usage.rs
+++ b/crates/profile/src/memory_usage.rs
@@ -35,6 +35,22 @@ impl MemoryUsage {
35 // Note: This is incredibly slow. 35 // Note: This is incredibly slow.
36 let alloc = unsafe { libc::mallinfo() }.uordblks as isize; 36 let alloc = unsafe { libc::mallinfo() }.uordblks as isize;
37 MemoryUsage { allocated: Bytes(alloc) } 37 MemoryUsage { allocated: Bytes(alloc) }
38 } else if #[cfg(windows)] {
39 // There doesn't seem to be an API for determining heap usage, so we try to
40 // approximate that by using the Commit Charge value.
41
42 use winapi::um::processthreadsapi::*;
43 use winapi::um::psapi::*;
44 use std::mem::{MaybeUninit, size_of};
45
46 let proc = unsafe { GetCurrentProcess() };
47 let mut mem_counters = MaybeUninit::uninit();
48 let cb = size_of::<PROCESS_MEMORY_COUNTERS>();
49 let ret = unsafe { GetProcessMemoryInfo(proc, mem_counters.as_mut_ptr(), cb as u32) };
50 assert!(ret != 0);
51
52 let usage = unsafe { mem_counters.assume_init().PagefileUsage };
53 MemoryUsage { allocated: Bytes(usage as isize) }
38 } else { 54 } else {
39 MemoryUsage { allocated: Bytes(0) } 55 MemoryUsage { allocated: Bytes(0) }
40 } 56 }
diff --git a/crates/rust-analyzer/src/cli.rs b/crates/rust-analyzer/src/cli.rs
index 76b666dc2..25ebcc0ec 100644
--- a/crates/rust-analyzer/src/cli.rs
+++ b/crates/rust-analyzer/src/cli.rs
@@ -16,7 +16,6 @@ use vfs::Vfs;
16pub use self::{ 16pub use self::{
17 analysis_stats::AnalysisStatsCmd, 17 analysis_stats::AnalysisStatsCmd,
18 diagnostics::diagnostics, 18 diagnostics::diagnostics,
19 load_cargo::{load_workspace, load_workspace_at, LoadCargoConfig},
20 ssr::{apply_ssr_rules, search_for_patterns}, 19 ssr::{apply_ssr_rules, search_for_patterns},
21}; 20};
22 21
diff --git a/crates/rust-analyzer/src/cli/analysis_stats.rs b/crates/rust-analyzer/src/cli/analysis_stats.rs
index 5364e907c..843c0ca37 100644
--- a/crates/rust-analyzer/src/cli/analysis_stats.rs
+++ b/crates/rust-analyzer/src/cli/analysis_stats.rs
@@ -70,6 +70,7 @@ impl AnalysisStatsCmd {
70 load_out_dirs_from_check: self.enable_build_scripts, 70 load_out_dirs_from_check: self.enable_build_scripts,
71 wrap_rustc: false, 71 wrap_rustc: false,
72 with_proc_macro: self.enable_proc_macros, 72 with_proc_macro: self.enable_proc_macros,
73 prefill_caches: false,
73 }; 74 };
74 let (host, vfs, _proc_macro) = 75 let (host, vfs, _proc_macro) =
75 load_workspace_at(&self.path, &cargo_config, &load_cargo_config, &|_| {})?; 76 load_workspace_at(&self.path, &cargo_config, &load_cargo_config, &|_| {})?;
diff --git a/crates/rust-analyzer/src/cli/diagnostics.rs b/crates/rust-analyzer/src/cli/diagnostics.rs
index c33c8179c..dc9a390fe 100644
--- a/crates/rust-analyzer/src/cli/diagnostics.rs
+++ b/crates/rust-analyzer/src/cli/diagnostics.rs
@@ -34,8 +34,12 @@ pub fn diagnostics(
34 with_proc_macro: bool, 34 with_proc_macro: bool,
35) -> Result<()> { 35) -> Result<()> {
36 let cargo_config = Default::default(); 36 let cargo_config = Default::default();
37 let load_cargo_config = 37 let load_cargo_config = LoadCargoConfig {
38 LoadCargoConfig { load_out_dirs_from_check, with_proc_macro, wrap_rustc: false }; 38 load_out_dirs_from_check,
39 with_proc_macro,
40 wrap_rustc: false,
41 prefill_caches: false,
42 };
39 let (host, _vfs, _proc_macro) = 43 let (host, _vfs, _proc_macro) =
40 load_workspace_at(path, &cargo_config, &load_cargo_config, &|_| {})?; 44 load_workspace_at(path, &cargo_config, &load_cargo_config, &|_| {})?;
41 let db = host.raw_database(); 45 let db = host.raw_database();
diff --git a/crates/rust-analyzer/src/cli/load_cargo.rs b/crates/rust-analyzer/src/cli/load_cargo.rs
index 8cee65478..19cb1c046 100644
--- a/crates/rust-analyzer/src/cli/load_cargo.rs
+++ b/crates/rust-analyzer/src/cli/load_cargo.rs
@@ -14,13 +14,14 @@ use vfs::{loader::Handle, AbsPath, AbsPathBuf};
14 14
15use crate::reload::{ProjectFolders, SourceRootConfig}; 15use crate::reload::{ProjectFolders, SourceRootConfig};
16 16
17pub struct LoadCargoConfig { 17pub(crate) struct LoadCargoConfig {
18 pub load_out_dirs_from_check: bool, 18 pub(crate) load_out_dirs_from_check: bool,
19 pub wrap_rustc: bool, 19 pub(crate) wrap_rustc: bool,
20 pub with_proc_macro: bool, 20 pub(crate) with_proc_macro: bool,
21 pub(crate) prefill_caches: bool,
21} 22}
22 23
23pub fn load_workspace_at( 24pub(crate) fn load_workspace_at(
24 root: &Path, 25 root: &Path,
25 cargo_config: &CargoConfig, 26 cargo_config: &CargoConfig,
26 load_config: &LoadCargoConfig, 27 load_config: &LoadCargoConfig,
@@ -33,7 +34,7 @@ pub fn load_workspace_at(
33 load_workspace(workspace, load_config, progress) 34 load_workspace(workspace, load_config, progress)
34} 35}
35 36
36pub fn load_workspace( 37fn load_workspace(
37 ws: ProjectWorkspace, 38 ws: ProjectWorkspace,
38 config: &LoadCargoConfig, 39 config: &LoadCargoConfig,
39 progress: &dyn Fn(String), 40 progress: &dyn Fn(String),
@@ -82,6 +83,10 @@ pub fn load_workspace(
82 log::debug!("crate graph: {:?}", crate_graph); 83 log::debug!("crate graph: {:?}", crate_graph);
83 let host = 84 let host =
84 load_crate_graph(crate_graph, project_folders.source_root_config, &mut vfs, &receiver); 85 load_crate_graph(crate_graph, project_folders.source_root_config, &mut vfs, &receiver);
86
87 if config.prefill_caches {
88 host.analysis().prime_caches(|_| {})?;
89 }
85 Ok((host, vfs, proc_macro_client)) 90 Ok((host, vfs, proc_macro_client))
86} 91}
87 92
@@ -144,6 +149,7 @@ mod tests {
144 load_out_dirs_from_check: false, 149 load_out_dirs_from_check: false,
145 wrap_rustc: false, 150 wrap_rustc: false,
146 with_proc_macro: false, 151 with_proc_macro: false,
152 prefill_caches: false,
147 }; 153 };
148 let (host, _vfs, _proc_macro) = 154 let (host, _vfs, _proc_macro) =
149 load_workspace_at(path, &cargo_config, &load_cargo_config, &|_| {})?; 155 load_workspace_at(path, &cargo_config, &load_cargo_config, &|_| {})?;
diff --git a/crates/rust-analyzer/src/cli/ssr.rs b/crates/rust-analyzer/src/cli/ssr.rs
index 1fd9b5a9b..0b3475e09 100644
--- a/crates/rust-analyzer/src/cli/ssr.rs
+++ b/crates/rust-analyzer/src/cli/ssr.rs
@@ -13,6 +13,7 @@ pub fn apply_ssr_rules(rules: Vec<SsrRule>) -> Result<()> {
13 load_out_dirs_from_check: true, 13 load_out_dirs_from_check: true,
14 wrap_rustc: false, 14 wrap_rustc: false,
15 with_proc_macro: true, 15 with_proc_macro: true,
16 prefill_caches: false,
16 }; 17 };
17 let (host, vfs, _proc_macro) = 18 let (host, vfs, _proc_macro) =
18 load_workspace_at(&std::env::current_dir()?, &cargo_config, &load_cargo_config, &|_| {})?; 19 load_workspace_at(&std::env::current_dir()?, &cargo_config, &load_cargo_config, &|_| {})?;
@@ -39,8 +40,12 @@ pub fn search_for_patterns(patterns: Vec<SsrPattern>, debug_snippet: Option<Stri
39 use ide_db::base_db::SourceDatabaseExt; 40 use ide_db::base_db::SourceDatabaseExt;
40 use ide_db::symbol_index::SymbolsDatabase; 41 use ide_db::symbol_index::SymbolsDatabase;
41 let cargo_config = Default::default(); 42 let cargo_config = Default::default();
42 let load_cargo_config = 43 let load_cargo_config = LoadCargoConfig {
43 LoadCargoConfig { load_out_dirs_from_check: true, wrap_rustc: true, with_proc_macro: true }; 44 load_out_dirs_from_check: true,
45 wrap_rustc: true,
46 with_proc_macro: true,
47 prefill_caches: false,
48 };
44 let (host, _vfs, _proc_macro) = 49 let (host, _vfs, _proc_macro) =
45 load_workspace_at(&std::env::current_dir()?, &cargo_config, &load_cargo_config, &|_| {})?; 50 load_workspace_at(&std::env::current_dir()?, &cargo_config, &load_cargo_config, &|_| {})?;
46 let db = host.raw_database(); 51 let db = host.raw_database();
diff --git a/crates/rust-analyzer/src/integrated_benchmarks.rs b/crates/rust-analyzer/src/integrated_benchmarks.rs
index ec36a5f5c..8ddeb59f7 100644
--- a/crates/rust-analyzer/src/integrated_benchmarks.rs
+++ b/crates/rust-analyzer/src/integrated_benchmarks.rs
@@ -37,6 +37,7 @@ fn integrated_highlighting_benchmark() {
37 load_out_dirs_from_check: true, 37 load_out_dirs_from_check: true,
38 wrap_rustc: false, 38 wrap_rustc: false,
39 with_proc_macro: false, 39 with_proc_macro: false,
40 prefill_caches: false,
40 }; 41 };
41 42
42 let (mut host, vfs, _proc_macro) = { 43 let (mut host, vfs, _proc_macro) = {
@@ -91,6 +92,7 @@ fn integrated_completion_benchmark() {
91 load_out_dirs_from_check: true, 92 load_out_dirs_from_check: true,
92 wrap_rustc: false, 93 wrap_rustc: false,
93 with_proc_macro: false, 94 with_proc_macro: false,
95 prefill_caches: true,
94 }; 96 };
95 97
96 let (mut host, vfs, _proc_macro) = { 98 let (mut host, vfs, _proc_macro) = {