aboutsummaryrefslogtreecommitdiff
path: root/crates/ra_hir_def
diff options
context:
space:
mode:
Diffstat (limited to 'crates/ra_hir_def')
-rw-r--r--crates/ra_hir_def/Cargo.toml3
-rw-r--r--crates/ra_hir_def/src/body.rs2
-rw-r--r--crates/ra_hir_def/src/data.rs2
-rw-r--r--crates/ra_hir_def/src/import_map.rs355
-rw-r--r--crates/ra_hir_def/src/lib.rs11
-rw-r--r--crates/ra_hir_def/src/nameres/collector.rs39
-rw-r--r--crates/ra_hir_def/src/path.rs20
-rw-r--r--crates/ra_hir_def/src/test_db.rs3
8 files changed, 392 insertions, 43 deletions
diff --git a/crates/ra_hir_def/Cargo.toml b/crates/ra_hir_def/Cargo.toml
index b85358308..ef1f65ee0 100644
--- a/crates/ra_hir_def/Cargo.toml
+++ b/crates/ra_hir_def/Cargo.toml
@@ -14,6 +14,9 @@ rustc-hash = "1.1.0"
14either = "1.5.3" 14either = "1.5.3"
15anymap = "0.12.1" 15anymap = "0.12.1"
16drop_bomb = "0.1.4" 16drop_bomb = "0.1.4"
17fst = { version = "0.4", default-features = false }
18itertools = "0.9.0"
19indexmap = "1.4.0"
17 20
18stdx = { path = "../stdx" } 21stdx = { path = "../stdx" }
19 22
diff --git a/crates/ra_hir_def/src/body.rs b/crates/ra_hir_def/src/body.rs
index 273036cee..4f2350915 100644
--- a/crates/ra_hir_def/src/body.rs
+++ b/crates/ra_hir_def/src/body.rs
@@ -97,7 +97,7 @@ impl Expander {
97 97
98 let macro_call = InFile::new(self.current_file_id, &macro_call); 98 let macro_call = InFile::new(self.current_file_id, &macro_call);
99 99
100 if let Some(call_id) = macro_call.as_call_id(db, |path| { 100 if let Some(call_id) = macro_call.as_call_id(db, self.crate_def_map.krate, |path| {
101 if let Some(local_scope) = local_scope { 101 if let Some(local_scope) = local_scope {
102 if let Some(def) = path.as_ident().and_then(|n| local_scope.get_legacy_macro(n)) { 102 if let Some(def) = path.as_ident().and_then(|n| local_scope.get_legacy_macro(n)) {
103 return Some(def); 103 return Some(def);
diff --git a/crates/ra_hir_def/src/data.rs b/crates/ra_hir_def/src/data.rs
index 807195d25..53599e74a 100644
--- a/crates/ra_hir_def/src/data.rs
+++ b/crates/ra_hir_def/src/data.rs
@@ -99,7 +99,7 @@ impl FunctionData {
99} 99}
100 100
101fn desugar_future_path(orig: TypeRef) -> Path { 101fn desugar_future_path(orig: TypeRef) -> Path {
102 let path = path![std::future::Future]; 102 let path = path![core::future::Future];
103 let mut generic_args: Vec<_> = std::iter::repeat(None).take(path.segments.len() - 1).collect(); 103 let mut generic_args: Vec<_> = std::iter::repeat(None).take(path.segments.len() - 1).collect();
104 let mut last = GenericArgs::empty(); 104 let mut last = GenericArgs::empty();
105 last.bindings.push(AssociatedTypeBinding { 105 last.bindings.push(AssociatedTypeBinding {
diff --git a/crates/ra_hir_def/src/import_map.rs b/crates/ra_hir_def/src/import_map.rs
index 4284a0a91..36b4fdd81 100644
--- a/crates/ra_hir_def/src/import_map.rs
+++ b/crates/ra_hir_def/src/import_map.rs
@@ -1,9 +1,11 @@
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::{collections::hash_map::Entry, fmt, sync::Arc}; 3use std::{cmp::Ordering, fmt, hash::BuildHasherDefault, sync::Arc};
4 4
5use fst::{self, Streamer};
6use indexmap::{map::Entry, IndexMap};
5use ra_db::CrateId; 7use ra_db::CrateId;
6use rustc_hash::FxHashMap; 8use rustc_hash::FxHasher;
7 9
8use crate::{ 10use crate::{
9 db::DefDatabase, 11 db::DefDatabase,
@@ -13,6 +15,8 @@ use crate::{
13 ModuleDefId, ModuleId, 15 ModuleDefId, ModuleId,
14}; 16};
15 17
18type FxIndexMap<K, V> = IndexMap<K, V, BuildHasherDefault<FxHasher>>;
19
16/// A map from publicly exported items to the path needed to import/name them from a downstream 20/// A map from publicly exported items to the path needed to import/name them from a downstream
17/// crate. 21/// crate.
18/// 22///
@@ -21,16 +25,24 @@ use crate::{
21/// 25///
22/// Note that all paths are relative to the containing crate's root, so the crate name still needs 26/// Note that all paths are relative to the containing crate's root, so the crate name still needs
23/// to be prepended to the `ModPath` before the path is valid. 27/// to be prepended to the `ModPath` before the path is valid.
24#[derive(Eq, PartialEq)]
25pub struct ImportMap { 28pub struct ImportMap {
26 map: FxHashMap<ItemInNs, ModPath>, 29 map: FxIndexMap<ItemInNs, ModPath>,
30
31 /// List of keys stored in `map`, sorted lexicographically by their `ModPath`. Indexed by the
32 /// values returned by running `fst`.
33 ///
34 /// Since a path can refer to multiple items due to namespacing, we store all items with the
35 /// same path right after each other. This allows us to find all items after the FST gives us
36 /// the index of the first one.
37 importables: Vec<ItemInNs>,
38 fst: fst::Map<Vec<u8>>,
27} 39}
28 40
29impl ImportMap { 41impl ImportMap {
30 pub fn import_map_query(db: &dyn DefDatabase, krate: CrateId) -> Arc<Self> { 42 pub fn import_map_query(db: &dyn DefDatabase, krate: CrateId) -> Arc<Self> {
31 let _p = ra_prof::profile("import_map_query"); 43 let _p = ra_prof::profile("import_map_query");
32 let def_map = db.crate_def_map(krate); 44 let def_map = db.crate_def_map(krate);
33 let mut import_map = FxHashMap::with_capacity_and_hasher(64, Default::default()); 45 let mut import_map = FxIndexMap::with_capacity_and_hasher(64, Default::default());
34 46
35 // We look only into modules that are public(ly reexported), starting with the crate root. 47 // We look only into modules that are public(ly reexported), starting with the crate root.
36 let empty = ModPath { kind: PathKind::Plain, segments: vec![] }; 48 let empty = ModPath { kind: PathKind::Plain, segments: vec![] };
@@ -88,7 +100,34 @@ impl ImportMap {
88 } 100 }
89 } 101 }
90 102
91 Arc::new(Self { map: import_map }) 103 let mut importables = import_map.iter().collect::<Vec<_>>();
104
105 importables.sort_by(cmp);
106
107 // Build the FST, taking care not to insert duplicate values.
108
109 let mut builder = fst::MapBuilder::memory();
110 let mut last_batch_start = 0;
111
112 for idx in 0..importables.len() {
113 if let Some(next_item) = importables.get(idx + 1) {
114 if cmp(&importables[last_batch_start], next_item) == Ordering::Equal {
115 continue;
116 }
117 }
118
119 let start = last_batch_start;
120 last_batch_start = idx + 1;
121
122 let key = fst_path(&importables[start].1);
123
124 builder.insert(key, start as u64).unwrap();
125 }
126
127 let fst = fst::Map::new(builder.into_inner().unwrap()).unwrap();
128 let importables = importables.iter().map(|(item, _)| **item).collect();
129
130 Arc::new(Self { map: import_map, fst, importables })
92 } 131 }
93 132
94 /// Returns the `ModPath` needed to import/mention `item`, relative to this crate's root. 133 /// Returns the `ModPath` needed to import/mention `item`, relative to this crate's root.
@@ -97,6 +136,15 @@ impl ImportMap {
97 } 136 }
98} 137}
99 138
139impl PartialEq for ImportMap {
140 fn eq(&self, other: &Self) -> bool {
141 // `fst` and `importables` are built from `map`, so we don't need to compare them.
142 self.map == other.map
143 }
144}
145
146impl Eq for ImportMap {}
147
100impl fmt::Debug for ImportMap { 148impl fmt::Debug for ImportMap {
101 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { 149 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
102 let mut importable_paths: Vec<_> = self 150 let mut importable_paths: Vec<_> = self
@@ -117,19 +165,135 @@ impl fmt::Debug for ImportMap {
117 } 165 }
118} 166}
119 167
168fn fst_path(path: &ModPath) -> String {
169 let mut s = path.to_string();
170 s.make_ascii_lowercase();
171 s
172}
173
174fn cmp((_, lhs): &(&ItemInNs, &ModPath), (_, rhs): &(&ItemInNs, &ModPath)) -> Ordering {
175 let lhs_str = fst_path(lhs);
176 let rhs_str = fst_path(rhs);
177 lhs_str.cmp(&rhs_str)
178}
179
180#[derive(Debug)]
181pub struct Query {
182 query: String,
183 lowercased: String,
184 anchor_end: bool,
185 case_sensitive: bool,
186 limit: usize,
187}
188
189impl Query {
190 pub fn new(query: &str) -> Self {
191 Self {
192 lowercased: query.to_lowercase(),
193 query: query.to_string(),
194 anchor_end: false,
195 case_sensitive: false,
196 limit: usize::max_value(),
197 }
198 }
199
200 /// Only returns items whose paths end with the (case-insensitive) query string as their last
201 /// segment.
202 pub fn anchor_end(self) -> Self {
203 Self { anchor_end: true, ..self }
204 }
205
206 /// Limits the returned number of items to `limit`.
207 pub fn limit(self, limit: usize) -> Self {
208 Self { limit, ..self }
209 }
210
211 /// Respect casing of the query string when matching.
212 pub fn case_sensitive(self) -> Self {
213 Self { case_sensitive: true, ..self }
214 }
215}
216
217/// Searches dependencies of `krate` for an importable path matching `query`.
218///
219/// This returns a list of items that could be imported from dependencies of `krate`.
220pub fn search_dependencies<'a>(
221 db: &'a dyn DefDatabase,
222 krate: CrateId,
223 query: Query,
224) -> Vec<ItemInNs> {
225 let _p = ra_prof::profile("search_dependencies").detail(|| format!("{:?}", query));
226
227 let graph = db.crate_graph();
228 let import_maps: Vec<_> =
229 graph[krate].dependencies.iter().map(|dep| db.import_map(dep.crate_id)).collect();
230
231 let automaton = fst::automaton::Subsequence::new(&query.lowercased);
232
233 let mut op = fst::map::OpBuilder::new();
234 for map in &import_maps {
235 op = op.add(map.fst.search(&automaton));
236 }
237
238 let mut stream = op.union();
239 let mut res = Vec::new();
240 while let Some((_, indexed_values)) = stream.next() {
241 for indexed_value in indexed_values {
242 let import_map = &import_maps[indexed_value.index];
243 let importables = &import_map.importables[indexed_value.value as usize..];
244
245 // Path shared by the importable items in this group.
246 let path = &import_map.map[&importables[0]];
247
248 if query.anchor_end {
249 // Last segment must match query.
250 let last = path.segments.last().unwrap().to_string();
251 if last.to_lowercase() != query.lowercased {
252 continue;
253 }
254 }
255
256 // Add the items from this `ModPath` group. Those are all subsequent items in
257 // `importables` whose paths match `path`.
258 let iter = importables.iter().copied().take_while(|item| {
259 let item_path = &import_map.map[item];
260 fst_path(item_path) == fst_path(path)
261 });
262
263 if query.case_sensitive {
264 // FIXME: This does not do a subsequence match.
265 res.extend(iter.filter(|item| {
266 let item_path = &import_map.map[item];
267 item_path.to_string().contains(&query.query)
268 }));
269 } else {
270 res.extend(iter);
271 }
272
273 if res.len() >= query.limit {
274 res.truncate(query.limit);
275 return res;
276 }
277 }
278 }
279
280 res
281}
282
120#[cfg(test)] 283#[cfg(test)]
121mod tests { 284mod tests {
122 use super::*; 285 use super::*;
123 use crate::test_db::TestDB; 286 use crate::test_db::TestDB;
124 use insta::assert_snapshot; 287 use insta::assert_snapshot;
288 use itertools::Itertools;
125 use ra_db::fixture::WithFixture; 289 use ra_db::fixture::WithFixture;
126 use ra_db::SourceDatabase; 290 use ra_db::{SourceDatabase, Upcast};
127 291
128 fn import_map(ra_fixture: &str) -> String { 292 fn import_map(ra_fixture: &str) -> String {
129 let db = TestDB::with_files(ra_fixture); 293 let db = TestDB::with_files(ra_fixture);
130 let crate_graph = db.crate_graph(); 294 let crate_graph = db.crate_graph();
131 295
132 let import_maps: Vec<_> = crate_graph 296 let s = crate_graph
133 .iter() 297 .iter()
134 .filter_map(|krate| { 298 .filter_map(|krate| {
135 let cdata = &crate_graph[krate]; 299 let cdata = &crate_graph[krate];
@@ -139,9 +303,41 @@ mod tests {
139 303
140 Some(format!("{}:\n{:?}", name, map)) 304 Some(format!("{}:\n{:?}", name, map))
141 }) 305 })
142 .collect(); 306 .join("\n");
307 s
308 }
143 309
144 import_maps.join("\n") 310 fn search_dependencies_of(ra_fixture: &str, krate_name: &str, query: Query) -> String {
311 let db = TestDB::with_files(ra_fixture);
312 let crate_graph = db.crate_graph();
313 let krate = crate_graph
314 .iter()
315 .find(|krate| {
316 crate_graph[*krate].display_name.as_ref().map(|n| n.to_string())
317 == Some(krate_name.to_string())
318 })
319 .unwrap();
320
321 search_dependencies(db.upcast(), krate, query)
322 .into_iter()
323 .filter_map(|item| {
324 let mark = match item {
325 ItemInNs::Types(_) => "t",
326 ItemInNs::Values(_) => "v",
327 ItemInNs::Macros(_) => "m",
328 };
329 item.krate(db.upcast()).map(|krate| {
330 let map = db.import_map(krate);
331 let path = map.path_of(item).unwrap();
332 format!(
333 "{}::{} ({})",
334 crate_graph[krate].display_name.as_ref().unwrap(),
335 path,
336 mark
337 )
338 })
339 })
340 .join("\n")
145 } 341 }
146 342
147 #[test] 343 #[test]
@@ -328,4 +524,143 @@ mod tests {
328 lib: 524 lib:
329 "###); 525 "###);
330 } 526 }
527
528 #[test]
529 fn namespacing() {
530 let map = import_map(
531 r"
532 //- /lib.rs crate:lib
533 pub struct Thing; // t + v
534 #[macro_export]
535 macro_rules! Thing { // m
536 () => {};
537 }
538 ",
539 );
540
541 assert_snapshot!(map, @r###"
542 lib:
543 - Thing (m)
544 - Thing (t)
545 - Thing (v)
546 "###);
547
548 let map = import_map(
549 r"
550 //- /lib.rs crate:lib
551 pub mod Thing {} // t
552 #[macro_export]
553 macro_rules! Thing { // m
554 () => {};
555 }
556 ",
557 );
558
559 assert_snapshot!(map, @r###"
560 lib:
561 - Thing (m)
562 - Thing (t)
563 "###);
564 }
565
566 #[test]
567 fn search() {
568 let ra_fixture = r#"
569 //- /main.rs crate:main deps:dep
570 //- /dep.rs crate:dep deps:tdep
571 use tdep::fmt as fmt_dep;
572 pub mod fmt {
573 pub trait Display {
574 fn fmt();
575 }
576 }
577 #[macro_export]
578 macro_rules! Fmt {
579 () => {};
580 }
581 pub struct Fmt;
582
583 pub fn format() {}
584 pub fn no() {}
585
586 //- /tdep.rs crate:tdep
587 pub mod fmt {
588 pub struct NotImportableFromMain;
589 }
590 "#;
591
592 let res = search_dependencies_of(ra_fixture, "main", Query::new("fmt"));
593 assert_snapshot!(res, @r###"
594 dep::fmt (t)
595 dep::Fmt (t)
596 dep::Fmt (v)
597 dep::Fmt (m)
598 dep::fmt::Display (t)
599 dep::format (v)
600 "###);
601
602 let res = search_dependencies_of(ra_fixture, "main", Query::new("fmt").anchor_end());
603 assert_snapshot!(res, @r###"
604 dep::fmt (t)
605 dep::Fmt (t)
606 dep::Fmt (v)
607 dep::Fmt (m)
608 "###);
609 }
610
611 #[test]
612 fn search_casing() {
613 let ra_fixture = r#"
614 //- /main.rs crate:main deps:dep
615 //- /dep.rs crate:dep
616
617 pub struct fmt;
618 pub struct FMT;
619 "#;
620
621 let res = search_dependencies_of(ra_fixture, "main", Query::new("FMT"));
622
623 assert_snapshot!(res, @r###"
624 dep::fmt (t)
625 dep::fmt (v)
626 dep::FMT (t)
627 dep::FMT (v)
628 "###);
629
630 let res = search_dependencies_of(ra_fixture, "main", Query::new("FMT").case_sensitive());
631
632 assert_snapshot!(res, @r###"
633 dep::FMT (t)
634 dep::FMT (v)
635 "###);
636 }
637
638 #[test]
639 fn search_limit() {
640 let res = search_dependencies_of(
641 r#"
642 //- /main.rs crate:main deps:dep
643 //- /dep.rs crate:dep
644 pub mod fmt {
645 pub trait Display {
646 fn fmt();
647 }
648 }
649 #[macro_export]
650 macro_rules! Fmt {
651 () => {};
652 }
653 pub struct Fmt;
654
655 pub fn format() {}
656 pub fn no() {}
657 "#,
658 "main",
659 Query::new("").limit(2),
660 );
661 assert_snapshot!(res, @r###"
662 dep::fmt (t)
663 dep::Fmt (t)
664 "###);
665 }
331} 666}
diff --git a/crates/ra_hir_def/src/lib.rs b/crates/ra_hir_def/src/lib.rs
index de490fcc5..edc59e5a8 100644
--- a/crates/ra_hir_def/src/lib.rs
+++ b/crates/ra_hir_def/src/lib.rs
@@ -417,6 +417,7 @@ pub trait AsMacroCall {
417 fn as_call_id( 417 fn as_call_id(
418 &self, 418 &self,
419 db: &dyn db::DefDatabase, 419 db: &dyn db::DefDatabase,
420 krate: CrateId,
420 resolver: impl Fn(path::ModPath) -> Option<MacroDefId>, 421 resolver: impl Fn(path::ModPath) -> Option<MacroDefId>,
421 ) -> Option<MacroCallId>; 422 ) -> Option<MacroCallId>;
422} 423}
@@ -425,13 +426,14 @@ impl AsMacroCall for InFile<&ast::MacroCall> {
425 fn as_call_id( 426 fn as_call_id(
426 &self, 427 &self,
427 db: &dyn db::DefDatabase, 428 db: &dyn db::DefDatabase,
429 krate: CrateId,
428 resolver: impl Fn(path::ModPath) -> Option<MacroDefId>, 430 resolver: impl Fn(path::ModPath) -> Option<MacroDefId>,
429 ) -> Option<MacroCallId> { 431 ) -> Option<MacroCallId> {
430 let ast_id = AstId::new(self.file_id, db.ast_id_map(self.file_id).ast_id(self.value)); 432 let ast_id = AstId::new(self.file_id, db.ast_id_map(self.file_id).ast_id(self.value));
431 let h = Hygiene::new(db.upcast(), self.file_id); 433 let h = Hygiene::new(db.upcast(), self.file_id);
432 let path = path::ModPath::from_src(self.value.path()?, &h)?; 434 let path = path::ModPath::from_src(self.value.path()?, &h)?;
433 435
434 AstIdWithPath::new(ast_id.file_id, ast_id.value, path).as_call_id(db, resolver) 436 AstIdWithPath::new(ast_id.file_id, ast_id.value, path).as_call_id(db, krate, resolver)
435 } 437 }
436} 438}
437 439
@@ -452,6 +454,7 @@ impl AsMacroCall for AstIdWithPath<ast::MacroCall> {
452 fn as_call_id( 454 fn as_call_id(
453 &self, 455 &self,
454 db: &dyn db::DefDatabase, 456 db: &dyn db::DefDatabase,
457 krate: CrateId,
455 resolver: impl Fn(path::ModPath) -> Option<MacroDefId>, 458 resolver: impl Fn(path::ModPath) -> Option<MacroDefId>,
456 ) -> Option<MacroCallId> { 459 ) -> Option<MacroCallId> {
457 let def: MacroDefId = resolver(self.path.clone())?; 460 let def: MacroDefId = resolver(self.path.clone())?;
@@ -461,13 +464,13 @@ impl AsMacroCall for AstIdWithPath<ast::MacroCall> {
461 let hygiene = Hygiene::new(db.upcast(), self.ast_id.file_id); 464 let hygiene = Hygiene::new(db.upcast(), self.ast_id.file_id);
462 465
463 Some( 466 Some(
464 expand_eager_macro(db.upcast(), macro_call, def, &|path: ast::Path| { 467 expand_eager_macro(db.upcast(), krate, macro_call, def, &|path: ast::Path| {
465 resolver(path::ModPath::from_src(path, &hygiene)?) 468 resolver(path::ModPath::from_src(path, &hygiene)?)
466 })? 469 })?
467 .into(), 470 .into(),
468 ) 471 )
469 } else { 472 } else {
470 Some(def.as_lazy_macro(db.upcast(), MacroCallKind::FnLike(self.ast_id)).into()) 473 Some(def.as_lazy_macro(db.upcast(), krate, MacroCallKind::FnLike(self.ast_id)).into())
471 } 474 }
472 } 475 }
473} 476}
@@ -476,12 +479,14 @@ impl AsMacroCall for AstIdWithPath<ast::ModuleItem> {
476 fn as_call_id( 479 fn as_call_id(
477 &self, 480 &self,
478 db: &dyn db::DefDatabase, 481 db: &dyn db::DefDatabase,
482 krate: CrateId,
479 resolver: impl Fn(path::ModPath) -> Option<MacroDefId>, 483 resolver: impl Fn(path::ModPath) -> Option<MacroDefId>,
480 ) -> Option<MacroCallId> { 484 ) -> Option<MacroCallId> {
481 let def = resolver(self.path.clone())?; 485 let def = resolver(self.path.clone())?;
482 Some( 486 Some(
483 def.as_lazy_macro( 487 def.as_lazy_macro(
484 db.upcast(), 488 db.upcast(),
489 krate,
485 MacroCallKind::Attr(self.ast_id, self.path.segments.last()?.to_string()), 490 MacroCallKind::Attr(self.ast_id, self.path.segments.last()?.to_string()),
486 ) 491 )
487 .into(), 492 .into(),
diff --git a/crates/ra_hir_def/src/nameres/collector.rs b/crates/ra_hir_def/src/nameres/collector.rs
index 353a31ad4..976e5e585 100644
--- a/crates/ra_hir_def/src/nameres/collector.rs
+++ b/crates/ra_hir_def/src/nameres/collector.rs
@@ -571,16 +571,18 @@ impl DefCollector<'_> {
571 return false; 571 return false;
572 } 572 }
573 573
574 if let Some(call_id) = directive.ast_id.as_call_id(self.db, |path| { 574 if let Some(call_id) =
575 let resolved_res = self.def_map.resolve_path_fp_with_macro( 575 directive.ast_id.as_call_id(self.db, self.def_map.krate, |path| {
576 self.db, 576 let resolved_res = self.def_map.resolve_path_fp_with_macro(
577 ResolveMode::Other, 577 self.db,
578 directive.module_id, 578 ResolveMode::Other,
579 &path, 579 directive.module_id,
580 BuiltinShadowMode::Module, 580 &path,
581 ); 581 BuiltinShadowMode::Module,
582 resolved_res.resolved_def.take_macros() 582 );
583 }) { 583 resolved_res.resolved_def.take_macros()
584 })
585 {
584 resolved.push((directive.module_id, call_id, directive.depth)); 586 resolved.push((directive.module_id, call_id, directive.depth));
585 res = ReachedFixedPoint::No; 587 res = ReachedFixedPoint::No;
586 return false; 588 return false;
@@ -589,9 +591,10 @@ impl DefCollector<'_> {
589 true 591 true
590 }); 592 });
591 attribute_macros.retain(|directive| { 593 attribute_macros.retain(|directive| {
592 if let Some(call_id) = directive 594 if let Some(call_id) =
593 .ast_id 595 directive.ast_id.as_call_id(self.db, self.def_map.krate, |path| {
594 .as_call_id(self.db, |path| self.resolve_attribute_macro(&directive, &path)) 596 self.resolve_attribute_macro(&directive, &path)
597 })
595 { 598 {
596 resolved.push((directive.module_id, call_id, 0)); 599 resolved.push((directive.module_id, call_id, 0));
597 res = ReachedFixedPoint::No; 600 res = ReachedFixedPoint::No;
@@ -957,11 +960,13 @@ impl ModCollector<'_, '_> {
957 } 960 }
958 961
959 // Case 2: try to resolve in legacy scope and expand macro_rules 962 // Case 2: try to resolve in legacy scope and expand macro_rules
960 if let Some(macro_call_id) = ast_id.as_call_id(self.def_collector.db, |path| { 963 if let Some(macro_call_id) =
961 path.as_ident().and_then(|name| { 964 ast_id.as_call_id(self.def_collector.db, self.def_collector.def_map.krate, |path| {
962 self.def_collector.def_map[self.module_id].scope.get_legacy_macro(&name) 965 path.as_ident().and_then(|name| {
966 self.def_collector.def_map[self.module_id].scope.get_legacy_macro(&name)
967 })
963 }) 968 })
964 }) { 969 {
965 self.def_collector.unexpanded_macros.push(MacroDirective { 970 self.def_collector.unexpanded_macros.push(MacroDirective {
966 module_id: self.module_id, 971 module_id: self.module_id,
967 ast_id, 972 ast_id,
diff --git a/crates/ra_hir_def/src/path.rs b/crates/ra_hir_def/src/path.rs
index bfa921de2..ba16442bd 100644
--- a/crates/ra_hir_def/src/path.rs
+++ b/crates/ra_hir_def/src/path.rs
@@ -323,16 +323,16 @@ pub use hir_expand::name as __name;
323 323
324#[macro_export] 324#[macro_export]
325macro_rules! __known_path { 325macro_rules! __known_path {
326 (std::iter::IntoIterator) => {}; 326 (core::iter::IntoIterator) => {};
327 (std::result::Result) => {}; 327 (core::result::Result) => {};
328 (std::ops::Range) => {}; 328 (core::ops::Range) => {};
329 (std::ops::RangeFrom) => {}; 329 (core::ops::RangeFrom) => {};
330 (std::ops::RangeFull) => {}; 330 (core::ops::RangeFull) => {};
331 (std::ops::RangeTo) => {}; 331 (core::ops::RangeTo) => {};
332 (std::ops::RangeToInclusive) => {}; 332 (core::ops::RangeToInclusive) => {};
333 (std::ops::RangeInclusive) => {}; 333 (core::ops::RangeInclusive) => {};
334 (std::future::Future) => {}; 334 (core::future::Future) => {};
335 (std::ops::Try) => {}; 335 (core::ops::Try) => {};
336 ($path:path) => { 336 ($path:path) => {
337 compile_error!("Please register your known path in the path module") 337 compile_error!("Please register your known path in the path module")
338 }; 338 };
diff --git a/crates/ra_hir_def/src/test_db.rs b/crates/ra_hir_def/src/test_db.rs
index bcfa66ac9..4581d8745 100644
--- a/crates/ra_hir_def/src/test_db.rs
+++ b/crates/ra_hir_def/src/test_db.rs
@@ -7,6 +7,7 @@ use std::{
7 7
8use hir_expand::db::AstDatabase; 8use hir_expand::db::AstDatabase;
9use ra_db::{salsa, CrateId, FileId, FileLoader, FileLoaderDelegate, Upcast}; 9use ra_db::{salsa, CrateId, FileId, FileLoader, FileLoaderDelegate, Upcast};
10use rustc_hash::FxHashSet;
10 11
11use crate::db::DefDatabase; 12use crate::db::DefDatabase;
12 13
@@ -59,7 +60,7 @@ impl FileLoader for TestDB {
59 fn resolve_path(&self, anchor: FileId, path: &str) -> Option<FileId> { 60 fn resolve_path(&self, anchor: FileId, path: &str) -> Option<FileId> {
60 FileLoaderDelegate(self).resolve_path(anchor, path) 61 FileLoaderDelegate(self).resolve_path(anchor, path)
61 } 62 }
62 fn relevant_crates(&self, file_id: FileId) -> Arc<Vec<CrateId>> { 63 fn relevant_crates(&self, file_id: FileId) -> Arc<FxHashSet<CrateId>> {
63 FileLoaderDelegate(self).relevant_crates(file_id) 64 FileLoaderDelegate(self).relevant_crates(file_id)
64 } 65 }
65} 66}