aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorbors[bot] <26634292+bors[bot]@users.noreply.github.com>2020-06-11 11:18:53 +0100
committerGitHub <[email protected]>2020-06-11 11:18:53 +0100
commit32157d48f449125febaade6bda0184334b6da4fd (patch)
treea0694e32148d1e9d6bf2264ce38d5bf280dd1769
parentf320c38aec185de2a02e0febff133da1f6a3462b (diff)
parentfac7b0e252ab305f5c8d69b04c46c587ee021aa9 (diff)
Merge #4843
4843: Don't guess macro expansion crate r=matklad a=matklad bors r+ 🤖 Co-authored-by: Aleksey Kladov <[email protected]>
-rw-r--r--Cargo.lock1
-rw-r--r--crates/ra_db/src/input.rs8
-rw-r--r--crates/ra_db/src/lib.rs20
-rw-r--r--crates/ra_hir/src/semantics.rs3
-rw-r--r--crates/ra_hir/src/source_analyzer.rs3
-rw-r--r--crates/ra_hir_def/src/body.rs2
-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/test_db.rs3
-rw-r--r--crates/ra_hir_expand/Cargo.toml1
-rw-r--r--crates/ra_hir_expand/src/builtin_derive.rs31
-rw-r--r--crates/ra_hir_expand/src/builtin_macro.rs18
-rw-r--r--crates/ra_hir_expand/src/eager.rs32
-rw-r--r--crates/ra_hir_expand/src/lib.rs11
-rw-r--r--crates/ra_hir_expand/src/test_db.rs3
-rw-r--r--crates/ra_hir_ty/src/test_db.rs3
-rw-r--r--crates/ra_ide_db/src/lib.rs4
17 files changed, 116 insertions, 77 deletions
diff --git a/Cargo.lock b/Cargo.lock
index e6338e316..2cb34fa20 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -1013,6 +1013,7 @@ dependencies = [
1013 "ra_prof", 1013 "ra_prof",
1014 "ra_syntax", 1014 "ra_syntax",
1015 "ra_tt", 1015 "ra_tt",
1016 "rustc-hash",
1016 "test_utils", 1017 "test_utils",
1017] 1018]
1018 1019
diff --git a/crates/ra_db/src/input.rs b/crates/ra_db/src/input.rs
index a8d6466ea..bf26048f2 100644
--- a/crates/ra_db/src/input.rs
+++ b/crates/ra_db/src/input.rs
@@ -15,12 +15,10 @@ use std::{
15 15
16use ra_cfg::CfgOptions; 16use ra_cfg::CfgOptions;
17use ra_syntax::SmolStr; 17use ra_syntax::SmolStr;
18use rustc_hash::FxHashMap; 18use ra_tt::TokenExpander;
19use rustc_hash::FxHashSet; 19use rustc_hash::{FxHashMap, FxHashSet};
20 20
21use crate::{RelativePath, RelativePathBuf}; 21use crate::{RelativePath, RelativePathBuf};
22use fmt::Display;
23use ra_tt::TokenExpander;
24 22
25/// `FileId` is an integer which uniquely identifies a file. File paths are 23/// `FileId` is an integer which uniquely identifies a file. File paths are
26/// messy and system-dependent, so most of the code should work directly with 24/// messy and system-dependent, so most of the code should work directly with
@@ -111,7 +109,7 @@ impl CrateName {
111 } 109 }
112} 110}
113 111
114impl Display for CrateName { 112impl fmt::Display for CrateName {
115 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { 113 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
116 write!(f, "{}", self.0) 114 write!(f, "{}", self.0)
117 } 115 }
diff --git a/crates/ra_db/src/lib.rs b/crates/ra_db/src/lib.rs
index 2ab314884..80ddb6058 100644
--- a/crates/ra_db/src/lib.rs
+++ b/crates/ra_db/src/lib.rs
@@ -7,6 +7,7 @@ use std::{panic, sync::Arc};
7 7
8use ra_prof::profile; 8use ra_prof::profile;
9use ra_syntax::{ast, Parse, SourceFile, TextRange, TextSize}; 9use ra_syntax::{ast, Parse, SourceFile, TextRange, TextSize};
10use rustc_hash::FxHashSet;
10 11
11pub use crate::{ 12pub use crate::{
12 cancellation::Canceled, 13 cancellation::Canceled,
@@ -95,7 +96,7 @@ pub trait FileLoader {
95 /// `struct StrPath(str)` for clarity some day, but it's a bit messy, so we 96 /// `struct StrPath(str)` for clarity some day, but it's a bit messy, so we
96 /// get by with a `&str` for the time being. 97 /// get by with a `&str` for the time being.
97 fn resolve_path(&self, anchor: FileId, path: &str) -> Option<FileId>; 98 fn resolve_path(&self, anchor: FileId, path: &str) -> Option<FileId>;
98 fn relevant_crates(&self, file_id: FileId) -> Arc<Vec<CrateId>>; 99 fn relevant_crates(&self, file_id: FileId) -> Arc<FxHashSet<CrateId>>;
99} 100}
100 101
101/// Database which stores all significant input facts: source code and project 102/// Database which stores all significant input facts: source code and project
@@ -133,16 +134,21 @@ pub trait SourceDatabaseExt: SourceDatabase {
133 #[salsa::input] 134 #[salsa::input]
134 fn source_root(&self, id: SourceRootId) -> Arc<SourceRoot>; 135 fn source_root(&self, id: SourceRootId) -> Arc<SourceRoot>;
135 136
136 fn source_root_crates(&self, id: SourceRootId) -> Arc<Vec<CrateId>>; 137 fn source_root_crates(&self, id: SourceRootId) -> Arc<FxHashSet<CrateId>>;
137} 138}
138 139
139fn source_root_crates( 140fn source_root_crates(
140 db: &(impl SourceDatabaseExt + SourceDatabase), 141 db: &(impl SourceDatabaseExt + SourceDatabase),
141 id: SourceRootId, 142 id: SourceRootId,
142) -> Arc<Vec<CrateId>> { 143) -> Arc<FxHashSet<CrateId>> {
143 let root = db.source_root(id);
144 let graph = db.crate_graph(); 144 let graph = db.crate_graph();
145 let res = root.walk().filter_map(|it| graph.crate_id_for_crate_root(it)).collect::<Vec<_>>(); 145 let res = graph
146 .iter()
147 .filter(|&krate| {
148 let root_file = graph[krate].root_file_id;
149 db.file_source_root(root_file) == id
150 })
151 .collect::<FxHashSet<_>>();
146 Arc::new(res) 152 Arc::new(res)
147} 153}
148 154
@@ -156,7 +162,7 @@ impl<T: SourceDatabaseExt> FileLoader for FileLoaderDelegate<&'_ T> {
156 fn resolve_path(&self, anchor: FileId, path: &str) -> Option<FileId> { 162 fn resolve_path(&self, anchor: FileId, path: &str) -> Option<FileId> {
157 // FIXME: this *somehow* should be platform agnostic... 163 // FIXME: this *somehow* should be platform agnostic...
158 if std::path::Path::new(path).is_absolute() { 164 if std::path::Path::new(path).is_absolute() {
159 let krate = *self.relevant_crates(anchor).get(0)?; 165 let krate = *self.relevant_crates(anchor).iter().next()?;
160 let (extern_source_id, relative_file) = 166 let (extern_source_id, relative_file) =
161 self.0.crate_graph()[krate].extern_source.extern_path(path.as_ref())?; 167 self.0.crate_graph()[krate].extern_source.extern_path(path.as_ref())?;
162 168
@@ -175,7 +181,7 @@ impl<T: SourceDatabaseExt> FileLoader for FileLoaderDelegate<&'_ T> {
175 } 181 }
176 } 182 }
177 183
178 fn relevant_crates(&self, file_id: FileId) -> Arc<Vec<CrateId>> { 184 fn relevant_crates(&self, file_id: FileId) -> Arc<FxHashSet<CrateId>> {
179 let source_root = self.0.file_source_root(file_id); 185 let source_root = self.0.file_source_root(file_id);
180 self.0.source_root_crates(source_root) 186 self.0.source_root_crates(source_root)
181 } 187 }
diff --git a/crates/ra_hir/src/semantics.rs b/crates/ra_hir/src/semantics.rs
index 7c1f79f27..a232a5856 100644
--- a/crates/ra_hir/src/semantics.rs
+++ b/crates/ra_hir/src/semantics.rs
@@ -122,8 +122,9 @@ impl<'db, DB: HirDatabase> Semantics<'db, DB> {
122 let macro_call = 122 let macro_call =
123 self.find_file(actual_macro_call.syntax().clone()).with_value(actual_macro_call); 123 self.find_file(actual_macro_call.syntax().clone()).with_value(actual_macro_call);
124 let sa = self.analyze2(macro_call.map(|it| it.syntax()), None); 124 let sa = self.analyze2(macro_call.map(|it| it.syntax()), None);
125 let krate = sa.resolver.krate()?;
125 let macro_call_id = macro_call 126 let macro_call_id = macro_call
126 .as_call_id(self.db, |path| sa.resolver.resolve_path_as_macro(self.db, &path))?; 127 .as_call_id(self.db, krate, |path| sa.resolver.resolve_path_as_macro(self.db, &path))?;
127 hir_expand::db::expand_hypothetical(self.db, macro_call_id, hypothetical_args, token_to_map) 128 hir_expand::db::expand_hypothetical(self.db, macro_call_id, hypothetical_args, token_to_map)
128 } 129 }
129 130
diff --git a/crates/ra_hir/src/source_analyzer.rs b/crates/ra_hir/src/source_analyzer.rs
index 4b509f07c..7c6bbea13 100644
--- a/crates/ra_hir/src/source_analyzer.rs
+++ b/crates/ra_hir/src/source_analyzer.rs
@@ -307,7 +307,8 @@ impl SourceAnalyzer {
307 db: &dyn HirDatabase, 307 db: &dyn HirDatabase,
308 macro_call: InFile<&ast::MacroCall>, 308 macro_call: InFile<&ast::MacroCall>,
309 ) -> Option<HirFileId> { 309 ) -> Option<HirFileId> {
310 let macro_call_id = macro_call.as_call_id(db.upcast(), |path| { 310 let krate = self.resolver.krate()?;
311 let macro_call_id = macro_call.as_call_id(db.upcast(), krate, |path| {
311 self.resolver.resolve_path_as_macro(db.upcast(), &path) 312 self.resolver.resolve_path_as_macro(db.upcast(), &path)
312 })?; 313 })?;
313 Some(macro_call_id.as_file()) 314 Some(macro_call_id.as_file())
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/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/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}
diff --git a/crates/ra_hir_expand/Cargo.toml b/crates/ra_hir_expand/Cargo.toml
index 2cd522766..e5c9f3e99 100644
--- a/crates/ra_hir_expand/Cargo.toml
+++ b/crates/ra_hir_expand/Cargo.toml
@@ -10,6 +10,7 @@ doctest = false
10[dependencies] 10[dependencies]
11log = "0.4.8" 11log = "0.4.8"
12either = "1.5.3" 12either = "1.5.3"
13rustc-hash = "1.0.0"
13 14
14ra_arena = { path = "../ra_arena" } 15ra_arena = { path = "../ra_arena" }
15ra_db = { path = "../ra_db" } 16ra_db = { path = "../ra_db" }
diff --git a/crates/ra_hir_expand/src/builtin_derive.rs b/crates/ra_hir_expand/src/builtin_derive.rs
index 1dc9cac66..26b667b55 100644
--- a/crates/ra_hir_expand/src/builtin_derive.rs
+++ b/crates/ra_hir_expand/src/builtin_derive.rs
@@ -8,8 +8,7 @@ use ra_syntax::{
8 match_ast, 8 match_ast,
9}; 9};
10 10
11use crate::db::AstDatabase; 11use crate::{db::AstDatabase, name, quote, LazyMacroId, MacroDefId, MacroDefKind};
12use crate::{name, quote, LazyMacroId, MacroCallId, MacroDefId, MacroDefKind};
13 12
14macro_rules! register_builtin { 13macro_rules! register_builtin {
15 ( $($trait:ident => $expand:ident),* ) => { 14 ( $($trait:ident => $expand:ident),* ) => {
@@ -156,23 +155,13 @@ fn expand_simple_derive(
156fn find_builtin_crate(db: &dyn AstDatabase, id: LazyMacroId) -> tt::TokenTree { 155fn find_builtin_crate(db: &dyn AstDatabase, id: LazyMacroId) -> tt::TokenTree {
157 // FIXME: make hygiene works for builtin derive macro 156 // FIXME: make hygiene works for builtin derive macro
158 // such that $crate can be used here. 157 // such that $crate can be used here.
159
160 let m: MacroCallId = id.into();
161 let file_id = m.as_file().original_file(db);
162 let cg = db.crate_graph(); 158 let cg = db.crate_graph();
163 let krates = db.relevant_crates(file_id); 159 let krate = db.lookup_intern_macro(id).krate;
164 let krate = match krates.get(0) {
165 Some(krate) => krate,
166 None => {
167 let tt = quote! { core };
168 return tt.token_trees[0].clone();
169 }
170 };
171 160
172 // XXX 161 // XXX
173 // All crates except core itself should have a dependency on core, 162 // All crates except core itself should have a dependency on core,
174 // We detect `core` by seeing whether it doesn't have such a dependency. 163 // We detect `core` by seeing whether it doesn't have such a dependency.
175 let tt = if cg[*krate].dependencies.iter().any(|dep| dep.name == "core") { 164 let tt = if cg[krate].dependencies.iter().any(|dep| dep.name == "core") {
176 quote! { core } 165 quote! { core }
177 } else { 166 } else {
178 quote! { crate } 167 quote! { crate }
@@ -264,10 +253,12 @@ fn partial_ord_expand(
264 253
265#[cfg(test)] 254#[cfg(test)]
266mod tests { 255mod tests {
267 use super::*;
268 use crate::{test_db::TestDB, AstId, MacroCallId, MacroCallKind, MacroCallLoc};
269 use name::{known, Name}; 256 use name::{known, Name};
270 use ra_db::{fixture::WithFixture, SourceDatabase}; 257 use ra_db::{fixture::WithFixture, CrateId, SourceDatabase};
258
259 use crate::{test_db::TestDB, AstId, MacroCallId, MacroCallKind, MacroCallLoc};
260
261 use super::*;
271 262
272 fn expand_builtin_derive(s: &str, name: Name) -> String { 263 fn expand_builtin_derive(s: &str, name: Name) -> String {
273 let def = find_builtin_derive(&name).unwrap(); 264 let def = find_builtin_derive(&name).unwrap();
@@ -291,7 +282,11 @@ mod tests {
291 282
292 let attr_id = AstId::new(file_id.into(), ast_id_map.ast_id(&items[0])); 283 let attr_id = AstId::new(file_id.into(), ast_id_map.ast_id(&items[0]));
293 284
294 let loc = MacroCallLoc { def, kind: MacroCallKind::Attr(attr_id, name.to_string()) }; 285 let loc = MacroCallLoc {
286 def,
287 krate: CrateId(0),
288 kind: MacroCallKind::Attr(attr_id, name.to_string()),
289 };
295 290
296 let id: MacroCallId = db.intern_macro(loc).into(); 291 let id: MacroCallId = db.intern_macro(loc).into();
297 let parsed = db.parse_or_expand(id.as_file()).unwrap(); 292 let parsed = db.parse_or_expand(id.as_file()).unwrap();
diff --git a/crates/ra_hir_expand/src/builtin_macro.rs b/crates/ra_hir_expand/src/builtin_macro.rs
index 7579546d2..b50eb347c 100644
--- a/crates/ra_hir_expand/src/builtin_macro.rs
+++ b/crates/ra_hir_expand/src/builtin_macro.rs
@@ -1,15 +1,14 @@
1//! Builtin macro 1//! Builtin macro
2use crate::db::AstDatabase;
3use crate::{ 2use crate::{
4 ast::{self, AstToken, HasStringValue}, 3 db::AstDatabase, name, quote, AstId, CrateId, EagerMacroId, LazyMacroId, MacroCallId,
5 name, AstId, CrateId, MacroDefId, MacroDefKind, TextSize, 4 MacroDefId, MacroDefKind, TextSize,
6}; 5};
7 6
8use crate::{quote, EagerMacroId, LazyMacroId, MacroCallId};
9use either::Either; 7use either::Either;
10use mbe::parse_to_token_tree; 8use mbe::parse_to_token_tree;
11use ra_db::FileId; 9use ra_db::FileId;
12use ra_parser::FragmentKind; 10use ra_parser::FragmentKind;
11use ra_syntax::ast::{self, AstToken, HasStringValue};
13 12
14macro_rules! register_builtin { 13macro_rules! register_builtin {
15 ( LAZY: $(($name:ident, $kind: ident) => $expand:ident),* , EAGER: $(($e_name:ident, $e_kind: ident) => $e_expand:ident),* ) => { 14 ( LAZY: $(($name:ident, $kind: ident) => $expand:ident),* , EAGER: $(($e_name:ident, $e_kind: ident) => $e_expand:ident),* ) => {
@@ -333,10 +332,7 @@ fn include_expand(
333} 332}
334 333
335fn get_env_inner(db: &dyn AstDatabase, arg_id: EagerMacroId, key: &str) -> Option<String> { 334fn get_env_inner(db: &dyn AstDatabase, arg_id: EagerMacroId, key: &str) -> Option<String> {
336 let call_id: MacroCallId = arg_id.into(); 335 let krate = db.lookup_intern_eager_expansion(arg_id).krate;
337 let original_file = call_id.as_file().original_file(db);
338
339 let krate = *db.relevant_crates(original_file).get(0)?;
340 db.crate_graph()[krate].env.get(key) 336 db.crate_graph()[krate].env.get(key)
341} 337}
342 338
@@ -395,6 +391,7 @@ mod tests {
395 391
396 let expander = find_by_name(&macro_calls[0].name().unwrap().as_name()).unwrap(); 392 let expander = find_by_name(&macro_calls[0].name().unwrap().as_name()).unwrap();
397 393
394 let krate = CrateId(0);
398 let file_id = match expander { 395 let file_id = match expander {
399 Either::Left(expander) => { 396 Either::Left(expander) => {
400 // the first one should be a macro_rules 397 // the first one should be a macro_rules
@@ -407,6 +404,7 @@ mod tests {
407 404
408 let loc = MacroCallLoc { 405 let loc = MacroCallLoc {
409 def, 406 def,
407 krate,
410 kind: MacroCallKind::FnLike(AstId::new( 408 kind: MacroCallKind::FnLike(AstId::new(
411 file_id.into(), 409 file_id.into(),
412 ast_id_map.ast_id(&macro_calls[1]), 410 ast_id_map.ast_id(&macro_calls[1]),
@@ -419,7 +417,7 @@ mod tests {
419 Either::Right(expander) => { 417 Either::Right(expander) => {
420 // the first one should be a macro_rules 418 // the first one should be a macro_rules
421 let def = MacroDefId { 419 let def = MacroDefId {
422 krate: Some(CrateId(0)), 420 krate: Some(krate),
423 ast_id: Some(AstId::new(file_id.into(), ast_id_map.ast_id(&macro_calls[0]))), 421 ast_id: Some(AstId::new(file_id.into(), ast_id_map.ast_id(&macro_calls[0]))),
424 kind: MacroDefKind::BuiltInEager(expander), 422 kind: MacroDefKind::BuiltInEager(expander),
425 local_inner: false, 423 local_inner: false,
@@ -433,6 +431,7 @@ mod tests {
433 def, 431 def,
434 fragment: FragmentKind::Expr, 432 fragment: FragmentKind::Expr,
435 subtree: Arc::new(parsed_args.clone()), 433 subtree: Arc::new(parsed_args.clone()),
434 krate,
436 file_id: file_id.into(), 435 file_id: file_id.into(),
437 } 436 }
438 }); 437 });
@@ -442,6 +441,7 @@ mod tests {
442 def, 441 def,
443 fragment, 442 fragment,
444 subtree: Arc::new(subtree), 443 subtree: Arc::new(subtree),
444 krate,
445 file_id: file_id.into(), 445 file_id: file_id.into(),
446 }; 446 };
447 447
diff --git a/crates/ra_hir_expand/src/eager.rs b/crates/ra_hir_expand/src/eager.rs
index 932f47c30..302d2b3e0 100644
--- a/crates/ra_hir_expand/src/eager.rs
+++ b/crates/ra_hir_expand/src/eager.rs
@@ -25,12 +25,14 @@ use crate::{
25 EagerCallLoc, EagerMacroId, InFile, MacroCallId, MacroCallKind, MacroDefId, MacroDefKind, 25 EagerCallLoc, EagerMacroId, InFile, MacroCallId, MacroCallKind, MacroDefId, MacroDefKind,
26}; 26};
27 27
28use ra_db::CrateId;
28use ra_parser::FragmentKind; 29use ra_parser::FragmentKind;
29use ra_syntax::{algo::SyntaxRewriter, SyntaxNode}; 30use ra_syntax::{algo::SyntaxRewriter, SyntaxNode};
30use std::sync::Arc; 31use std::sync::Arc;
31 32
32pub fn expand_eager_macro( 33pub fn expand_eager_macro(
33 db: &dyn AstDatabase, 34 db: &dyn AstDatabase,
35 krate: CrateId,
34 macro_call: InFile<ast::MacroCall>, 36 macro_call: InFile<ast::MacroCall>,
35 def: MacroDefId, 37 def: MacroDefId,
36 resolver: &dyn Fn(ast::Path) -> Option<MacroDefId>, 38 resolver: &dyn Fn(ast::Path) -> Option<MacroDefId>,
@@ -47,6 +49,7 @@ pub fn expand_eager_macro(
47 def, 49 def,
48 fragment: FragmentKind::Expr, 50 fragment: FragmentKind::Expr,
49 subtree: Arc::new(parsed_args.clone()), 51 subtree: Arc::new(parsed_args.clone()),
52 krate,
50 file_id: macro_call.file_id, 53 file_id: macro_call.file_id,
51 } 54 }
52 }); 55 });
@@ -56,14 +59,20 @@ pub fn expand_eager_macro(
56 let result = eager_macro_recur( 59 let result = eager_macro_recur(
57 db, 60 db,
58 InFile::new(arg_file_id.as_file(), parsed_args.syntax_node()), 61 InFile::new(arg_file_id.as_file(), parsed_args.syntax_node()),
62 krate,
59 resolver, 63 resolver,
60 )?; 64 )?;
61 let subtree = to_subtree(&result)?; 65 let subtree = to_subtree(&result)?;
62 66
63 if let MacroDefKind::BuiltInEager(eager) = def.kind { 67 if let MacroDefKind::BuiltInEager(eager) = def.kind {
64 let (subtree, fragment) = eager.expand(db, arg_id, &subtree).ok()?; 68 let (subtree, fragment) = eager.expand(db, arg_id, &subtree).ok()?;
65 let eager = 69 let eager = EagerCallLoc {
66 EagerCallLoc { def, fragment, subtree: Arc::new(subtree), file_id: macro_call.file_id }; 70 def,
71 fragment,
72 subtree: Arc::new(subtree),
73 krate,
74 file_id: macro_call.file_id,
75 };
67 76
68 Some(db.intern_eager_expansion(eager)) 77 Some(db.intern_eager_expansion(eager))
69 } else { 78 } else {
@@ -81,11 +90,12 @@ fn lazy_expand(
81 db: &dyn AstDatabase, 90 db: &dyn AstDatabase,
82 def: &MacroDefId, 91 def: &MacroDefId,
83 macro_call: InFile<ast::MacroCall>, 92 macro_call: InFile<ast::MacroCall>,
93 krate: CrateId,
84) -> Option<InFile<SyntaxNode>> { 94) -> Option<InFile<SyntaxNode>> {
85 let ast_id = db.ast_id_map(macro_call.file_id).ast_id(&macro_call.value); 95 let ast_id = db.ast_id_map(macro_call.file_id).ast_id(&macro_call.value);
86 96
87 let id: MacroCallId = 97 let id: MacroCallId =
88 def.as_lazy_macro(db, MacroCallKind::FnLike(macro_call.with_value(ast_id))).into(); 98 def.as_lazy_macro(db, krate, MacroCallKind::FnLike(macro_call.with_value(ast_id))).into();
89 99
90 db.parse_or_expand(id.as_file()).map(|node| InFile::new(id.as_file(), node)) 100 db.parse_or_expand(id.as_file()).map(|node| InFile::new(id.as_file(), node))
91} 101}
@@ -93,6 +103,7 @@ fn lazy_expand(
93fn eager_macro_recur( 103fn eager_macro_recur(
94 db: &dyn AstDatabase, 104 db: &dyn AstDatabase,
95 curr: InFile<SyntaxNode>, 105 curr: InFile<SyntaxNode>,
106 krate: CrateId,
96 macro_resolver: &dyn Fn(ast::Path) -> Option<MacroDefId>, 107 macro_resolver: &dyn Fn(ast::Path) -> Option<MacroDefId>,
97) -> Option<SyntaxNode> { 108) -> Option<SyntaxNode> {
98 let original = curr.value.clone(); 109 let original = curr.value.clone();
@@ -105,18 +116,23 @@ fn eager_macro_recur(
105 let def: MacroDefId = macro_resolver(child.path()?)?; 116 let def: MacroDefId = macro_resolver(child.path()?)?;
106 let insert = match def.kind { 117 let insert = match def.kind {
107 MacroDefKind::BuiltInEager(_) => { 118 MacroDefKind::BuiltInEager(_) => {
108 let id: MacroCallId = 119 let id: MacroCallId = expand_eager_macro(
109 expand_eager_macro(db, curr.with_value(child.clone()), def, macro_resolver)? 120 db,
110 .into(); 121 krate,
122 curr.with_value(child.clone()),
123 def,
124 macro_resolver,
125 )?
126 .into();
111 db.parse_or_expand(id.as_file())? 127 db.parse_or_expand(id.as_file())?
112 } 128 }
113 MacroDefKind::Declarative 129 MacroDefKind::Declarative
114 | MacroDefKind::BuiltIn(_) 130 | MacroDefKind::BuiltIn(_)
115 | MacroDefKind::BuiltInDerive(_) 131 | MacroDefKind::BuiltInDerive(_)
116 | MacroDefKind::CustomDerive(_) => { 132 | MacroDefKind::CustomDerive(_) => {
117 let expanded = lazy_expand(db, &def, curr.with_value(child.clone()))?; 133 let expanded = lazy_expand(db, &def, curr.with_value(child.clone()), krate)?;
118 // replace macro inside 134 // replace macro inside
119 eager_macro_recur(db, expanded, macro_resolver)? 135 eager_macro_recur(db, expanded, krate, macro_resolver)?
120 } 136 }
121 }; 137 };
122 138
diff --git a/crates/ra_hir_expand/src/lib.rs b/crates/ra_hir_expand/src/lib.rs
index f440c073b..5eac2605b 100644
--- a/crates/ra_hir_expand/src/lib.rs
+++ b/crates/ra_hir_expand/src/lib.rs
@@ -209,8 +209,13 @@ pub struct MacroDefId {
209} 209}
210 210
211impl MacroDefId { 211impl MacroDefId {
212 pub fn as_lazy_macro(self, db: &dyn db::AstDatabase, kind: MacroCallKind) -> LazyMacroId { 212 pub fn as_lazy_macro(
213 db.intern_macro(MacroCallLoc { def: self, kind }) 213 self,
214 db: &dyn db::AstDatabase,
215 krate: CrateId,
216 kind: MacroCallKind,
217 ) -> LazyMacroId {
218 db.intern_macro(MacroCallLoc { def: self, krate, kind })
214 } 219 }
215} 220}
216 221
@@ -227,6 +232,7 @@ pub enum MacroDefKind {
227#[derive(Debug, Clone, PartialEq, Eq, Hash)] 232#[derive(Debug, Clone, PartialEq, Eq, Hash)]
228pub struct MacroCallLoc { 233pub struct MacroCallLoc {
229 pub(crate) def: MacroDefId, 234 pub(crate) def: MacroDefId,
235 pub(crate) krate: CrateId,
230 pub(crate) kind: MacroCallKind, 236 pub(crate) kind: MacroCallKind,
231} 237}
232 238
@@ -274,6 +280,7 @@ pub struct EagerCallLoc {
274 pub(crate) def: MacroDefId, 280 pub(crate) def: MacroDefId,
275 pub(crate) fragment: FragmentKind, 281 pub(crate) fragment: FragmentKind,
276 pub(crate) subtree: Arc<tt::Subtree>, 282 pub(crate) subtree: Arc<tt::Subtree>,
283 pub(crate) krate: CrateId,
277 pub(crate) file_id: HirFileId, 284 pub(crate) file_id: HirFileId,
278} 285}
279 286
diff --git a/crates/ra_hir_expand/src/test_db.rs b/crates/ra_hir_expand/src/test_db.rs
index fdf225f55..09fc18c36 100644
--- a/crates/ra_hir_expand/src/test_db.rs
+++ b/crates/ra_hir_expand/src/test_db.rs
@@ -6,6 +6,7 @@ use std::{
6}; 6};
7 7
8use ra_db::{salsa, CrateId, FileId, FileLoader, FileLoaderDelegate}; 8use ra_db::{salsa, CrateId, FileId, FileLoader, FileLoaderDelegate};
9use rustc_hash::FxHashSet;
9 10
10#[salsa::database( 11#[salsa::database(
11 ra_db::SourceDatabaseExtStorage, 12 ra_db::SourceDatabaseExtStorage,
@@ -44,7 +45,7 @@ impl FileLoader for TestDB {
44 fn resolve_path(&self, anchor: FileId, path: &str) -> Option<FileId> { 45 fn resolve_path(&self, anchor: FileId, path: &str) -> Option<FileId> {
45 FileLoaderDelegate(self).resolve_path(anchor, path) 46 FileLoaderDelegate(self).resolve_path(anchor, path)
46 } 47 }
47 fn relevant_crates(&self, file_id: FileId) -> Arc<Vec<CrateId>> { 48 fn relevant_crates(&self, file_id: FileId) -> Arc<FxHashSet<CrateId>> {
48 FileLoaderDelegate(self).relevant_crates(file_id) 49 FileLoaderDelegate(self).relevant_crates(file_id)
49 } 50 }
50} 51}
diff --git a/crates/ra_hir_ty/src/test_db.rs b/crates/ra_hir_ty/src/test_db.rs
index e484968a0..ad04e3e0f 100644
--- a/crates/ra_hir_ty/src/test_db.rs
+++ b/crates/ra_hir_ty/src/test_db.rs
@@ -8,6 +8,7 @@ use std::{
8use hir_def::{db::DefDatabase, AssocItemId, ModuleDefId, ModuleId}; 8use hir_def::{db::DefDatabase, AssocItemId, ModuleDefId, ModuleId};
9use hir_expand::{db::AstDatabase, diagnostics::DiagnosticSink}; 9use hir_expand::{db::AstDatabase, diagnostics::DiagnosticSink};
10use ra_db::{salsa, CrateId, FileId, FileLoader, FileLoaderDelegate, SourceDatabase, Upcast}; 10use ra_db::{salsa, CrateId, FileId, FileLoader, FileLoaderDelegate, SourceDatabase, Upcast};
11use rustc_hash::FxHashSet;
11use stdx::format_to; 12use stdx::format_to;
12 13
13use crate::{db::HirDatabase, diagnostics::Diagnostic, expr::ExprValidator}; 14use crate::{db::HirDatabase, diagnostics::Diagnostic, expr::ExprValidator};
@@ -73,7 +74,7 @@ impl FileLoader for TestDB {
73 fn resolve_path(&self, anchor: FileId, path: &str) -> Option<FileId> { 74 fn resolve_path(&self, anchor: FileId, path: &str) -> Option<FileId> {
74 FileLoaderDelegate(self).resolve_path(anchor, path) 75 FileLoaderDelegate(self).resolve_path(anchor, path)
75 } 76 }
76 fn relevant_crates(&self, file_id: FileId) -> Arc<Vec<CrateId>> { 77 fn relevant_crates(&self, file_id: FileId) -> Arc<FxHashSet<CrateId>> {
77 FileLoaderDelegate(self).relevant_crates(file_id) 78 FileLoaderDelegate(self).relevant_crates(file_id)
78 } 79 }
79} 80}
diff --git a/crates/ra_ide_db/src/lib.rs b/crates/ra_ide_db/src/lib.rs
index 727d743b5..480fd4576 100644
--- a/crates/ra_ide_db/src/lib.rs
+++ b/crates/ra_ide_db/src/lib.rs
@@ -19,7 +19,7 @@ use ra_db::{
19 Canceled, CheckCanceled, CrateId, FileId, FileLoader, FileLoaderDelegate, SourceDatabase, 19 Canceled, CheckCanceled, CrateId, FileId, FileLoader, FileLoaderDelegate, SourceDatabase,
20 SourceRootId, Upcast, 20 SourceRootId, Upcast,
21}; 21};
22use rustc_hash::FxHashMap; 22use rustc_hash::{FxHashMap, FxHashSet};
23 23
24use crate::{line_index::LineIndex, symbol_index::SymbolsDatabase}; 24use crate::{line_index::LineIndex, symbol_index::SymbolsDatabase};
25 25
@@ -60,7 +60,7 @@ impl FileLoader for RootDatabase {
60 fn resolve_path(&self, anchor: FileId, path: &str) -> Option<FileId> { 60 fn resolve_path(&self, anchor: FileId, path: &str) -> Option<FileId> {
61 FileLoaderDelegate(self).resolve_path(anchor, path) 61 FileLoaderDelegate(self).resolve_path(anchor, path)
62 } 62 }
63 fn relevant_crates(&self, file_id: FileId) -> Arc<Vec<CrateId>> { 63 fn relevant_crates(&self, file_id: FileId) -> Arc<FxHashSet<CrateId>> {
64 FileLoaderDelegate(self).relevant_crates(file_id) 64 FileLoaderDelegate(self).relevant_crates(file_id)
65 } 65 }
66} 66}