]> git.lizzy.rs Git - rust.git/commitdiff
Don't guess macro expansion crate
authorAleksey Kladov <aleksey.kladov@gmail.com>
Thu, 11 Jun 2020 10:08:24 +0000 (12:08 +0200)
committerAleksey Kladov <aleksey.kladov@gmail.com>
Thu, 11 Jun 2020 10:13:14 +0000 (12:13 +0200)
crates/ra_hir/src/semantics.rs
crates/ra_hir/src/source_analyzer.rs
crates/ra_hir_def/src/body.rs
crates/ra_hir_def/src/lib.rs
crates/ra_hir_def/src/nameres/collector.rs
crates/ra_hir_expand/src/builtin_derive.rs
crates/ra_hir_expand/src/builtin_macro.rs
crates/ra_hir_expand/src/eager.rs
crates/ra_hir_expand/src/lib.rs

index 7c1f79f279b655a83c39524f22bf14c58375b3bb..a232a58567ce65aa6099124f9d299ec03866026f 100644 (file)
@@ -122,8 +122,9 @@ pub fn expand_hypothetical(
         let macro_call =
             self.find_file(actual_macro_call.syntax().clone()).with_value(actual_macro_call);
         let sa = self.analyze2(macro_call.map(|it| it.syntax()), None);
+        let krate = sa.resolver.krate()?;
         let macro_call_id = macro_call
-            .as_call_id(self.db, |path| sa.resolver.resolve_path_as_macro(self.db, &path))?;
+            .as_call_id(self.db, krate, |path| sa.resolver.resolve_path_as_macro(self.db, &path))?;
         hir_expand::db::expand_hypothetical(self.db, macro_call_id, hypothetical_args, token_to_map)
     }
 
index 4b509f07c6b73303c0d3a53161f33ae147b1df0e..7c6bbea13c2941a29c226ff7a61b4a16a7cb46a5 100644 (file)
@@ -307,7 +307,8 @@ pub(crate) fn expand(
         db: &dyn HirDatabase,
         macro_call: InFile<&ast::MacroCall>,
     ) -> Option<HirFileId> {
-        let macro_call_id = macro_call.as_call_id(db.upcast(), |path| {
+        let krate = self.resolver.krate()?;
+        let macro_call_id = macro_call.as_call_id(db.upcast(), krate, |path| {
             self.resolver.resolve_path_as_macro(db.upcast(), &path)
         })?;
         Some(macro_call_id.as_file())
index 273036cee1cfec60fee9b4398055fdfc45731519..4f2350915dcb76ec3ce6009b6e3a792f8aacacfa 100644 (file)
@@ -97,7 +97,7 @@ pub(crate) fn enter_expand<T: ast::AstNode>(
 
         let macro_call = InFile::new(self.current_file_id, &macro_call);
 
-        if let Some(call_id) = macro_call.as_call_id(db, |path| {
+        if let Some(call_id) = macro_call.as_call_id(db, self.crate_def_map.krate, |path| {
             if let Some(local_scope) = local_scope {
                 if let Some(def) = path.as_ident().and_then(|n| local_scope.get_legacy_macro(n)) {
                     return Some(def);
index de490fcc58af295ec07d424046ebc7ba1e1c9e48..edc59e5a80f4ca549f590b36ebddb04771d19710 100644 (file)
@@ -417,6 +417,7 @@ pub trait AsMacroCall {
     fn as_call_id(
         &self,
         db: &dyn db::DefDatabase,
+        krate: CrateId,
         resolver: impl Fn(path::ModPath) -> Option<MacroDefId>,
     ) -> Option<MacroCallId>;
 }
@@ -425,13 +426,14 @@ impl AsMacroCall for InFile<&ast::MacroCall> {
     fn as_call_id(
         &self,
         db: &dyn db::DefDatabase,
+        krate: CrateId,
         resolver: impl Fn(path::ModPath) -> Option<MacroDefId>,
     ) -> Option<MacroCallId> {
         let ast_id = AstId::new(self.file_id, db.ast_id_map(self.file_id).ast_id(self.value));
         let h = Hygiene::new(db.upcast(), self.file_id);
         let path = path::ModPath::from_src(self.value.path()?, &h)?;
 
-        AstIdWithPath::new(ast_id.file_id, ast_id.value, path).as_call_id(db, resolver)
+        AstIdWithPath::new(ast_id.file_id, ast_id.value, path).as_call_id(db, krate, resolver)
     }
 }
 
@@ -452,6 +454,7 @@ impl AsMacroCall for AstIdWithPath<ast::MacroCall> {
     fn as_call_id(
         &self,
         db: &dyn db::DefDatabase,
+        krate: CrateId,
         resolver: impl Fn(path::ModPath) -> Option<MacroDefId>,
     ) -> Option<MacroCallId> {
         let def: MacroDefId = resolver(self.path.clone())?;
@@ -461,13 +464,13 @@ fn as_call_id(
             let hygiene = Hygiene::new(db.upcast(), self.ast_id.file_id);
 
             Some(
-                expand_eager_macro(db.upcast(), macro_call, def, &|path: ast::Path| {
+                expand_eager_macro(db.upcast(), krate, macro_call, def, &|path: ast::Path| {
                     resolver(path::ModPath::from_src(path, &hygiene)?)
                 })?
                 .into(),
             )
         } else {
-            Some(def.as_lazy_macro(db.upcast(), MacroCallKind::FnLike(self.ast_id)).into())
+            Some(def.as_lazy_macro(db.upcast(), krate, MacroCallKind::FnLike(self.ast_id)).into())
         }
     }
 }
@@ -476,12 +479,14 @@ impl AsMacroCall for AstIdWithPath<ast::ModuleItem> {
     fn as_call_id(
         &self,
         db: &dyn db::DefDatabase,
+        krate: CrateId,
         resolver: impl Fn(path::ModPath) -> Option<MacroDefId>,
     ) -> Option<MacroCallId> {
         let def = resolver(self.path.clone())?;
         Some(
             def.as_lazy_macro(
                 db.upcast(),
+                krate,
                 MacroCallKind::Attr(self.ast_id, self.path.segments.last()?.to_string()),
             )
             .into(),
index 353a31ad47a153cc6b717de468deb9e4b20594f9..976e5e5850f14e721deae0f802c8c3a898221bc3 100644 (file)
@@ -571,16 +571,18 @@ fn resolve_macros(&mut self) -> ReachedFixedPoint {
                 return false;
             }
 
-            if let Some(call_id) = directive.ast_id.as_call_id(self.db, |path| {
-                let resolved_res = self.def_map.resolve_path_fp_with_macro(
-                    self.db,
-                    ResolveMode::Other,
-                    directive.module_id,
-                    &path,
-                    BuiltinShadowMode::Module,
-                );
-                resolved_res.resolved_def.take_macros()
-            }) {
+            if let Some(call_id) =
+                directive.ast_id.as_call_id(self.db, self.def_map.krate, |path| {
+                    let resolved_res = self.def_map.resolve_path_fp_with_macro(
+                        self.db,
+                        ResolveMode::Other,
+                        directive.module_id,
+                        &path,
+                        BuiltinShadowMode::Module,
+                    );
+                    resolved_res.resolved_def.take_macros()
+                })
+            {
                 resolved.push((directive.module_id, call_id, directive.depth));
                 res = ReachedFixedPoint::No;
                 return false;
@@ -589,9 +591,10 @@ fn resolve_macros(&mut self) -> ReachedFixedPoint {
             true
         });
         attribute_macros.retain(|directive| {
-            if let Some(call_id) = directive
-                .ast_id
-                .as_call_id(self.db, |path| self.resolve_attribute_macro(&directive, &path))
+            if let Some(call_id) =
+                directive.ast_id.as_call_id(self.db, self.def_map.krate, |path| {
+                    self.resolve_attribute_macro(&directive, &path)
+                })
             {
                 resolved.push((directive.module_id, call_id, 0));
                 res = ReachedFixedPoint::No;
@@ -957,11 +960,13 @@ fn collect_macro(&mut self, mac: &raw::MacroData) {
         }
 
         // Case 2: try to resolve in legacy scope and expand macro_rules
-        if let Some(macro_call_id) = ast_id.as_call_id(self.def_collector.db, |path| {
-            path.as_ident().and_then(|name| {
-                self.def_collector.def_map[self.module_id].scope.get_legacy_macro(&name)
+        if let Some(macro_call_id) =
+            ast_id.as_call_id(self.def_collector.db, self.def_collector.def_map.krate, |path| {
+                path.as_ident().and_then(|name| {
+                    self.def_collector.def_map[self.module_id].scope.get_legacy_macro(&name)
+                })
             })
-        }) {
+        {
             self.def_collector.unexpanded_macros.push(MacroDirective {
                 module_id: self.module_id,
                 ast_id,
index 967d1f3a16ee4143785e67c1b22434c1649e4e12..26b667b55715e791c0bc9bd020e3027c42989ea8 100644 (file)
@@ -8,8 +8,7 @@
     match_ast,
 };
 
-use crate::db::AstDatabase;
-use crate::{guess_crate, name, quote, LazyMacroId, MacroCallId, MacroDefId, MacroDefKind};
+use crate::{db::AstDatabase, name, quote, LazyMacroId, MacroDefId, MacroDefKind};
 
 macro_rules! register_builtin {
     ( $($trait:ident => $expand:ident),* ) => {
@@ -156,17 +155,8 @@ impl ##type_params ##trait_path for #name ##type_args {}
 fn find_builtin_crate(db: &dyn AstDatabase, id: LazyMacroId) -> tt::TokenTree {
     // FIXME: make hygiene works for builtin derive macro
     // such that $crate can be used here.
-
-    let m: MacroCallId = id.into();
-    let file_id = m.as_file().original_file(db);
     let cg = db.crate_graph();
-    let krate = match guess_crate(db, file_id) {
-        Some(krate) => krate,
-        None => {
-            let tt = quote! { core };
-            return tt.token_trees[0].clone();
-        }
-    };
+    let krate = db.lookup_intern_macro(id).krate;
 
     // XXX
     //  All crates except core itself should have a dependency on core,
@@ -263,10 +253,12 @@ fn partial_ord_expand(
 
 #[cfg(test)]
 mod tests {
-    use super::*;
-    use crate::{test_db::TestDB, AstId, MacroCallId, MacroCallKind, MacroCallLoc};
     use name::{known, Name};
-    use ra_db::{fixture::WithFixture, SourceDatabase};
+    use ra_db::{fixture::WithFixture, CrateId, SourceDatabase};
+
+    use crate::{test_db::TestDB, AstId, MacroCallId, MacroCallKind, MacroCallLoc};
+
+    use super::*;
 
     fn expand_builtin_derive(s: &str, name: Name) -> String {
         let def = find_builtin_derive(&name).unwrap();
@@ -290,7 +282,11 @@ fn expand_builtin_derive(s: &str, name: Name) -> String {
 
         let attr_id = AstId::new(file_id.into(), ast_id_map.ast_id(&items[0]));
 
-        let loc = MacroCallLoc { def, kind: MacroCallKind::Attr(attr_id, name.to_string()) };
+        let loc = MacroCallLoc {
+            def,
+            krate: CrateId(0),
+            kind: MacroCallKind::Attr(attr_id, name.to_string()),
+        };
 
         let id: MacroCallId = db.intern_macro(loc).into();
         let parsed = db.parse_or_expand(id.as_file()).unwrap();
index 93da3f149d27cae95625db9b50d907a41b12ad53..b50eb347c8e42b3e021f3a21e4684d3d59d89cb6 100644 (file)
@@ -1,15 +1,14 @@
 //! Builtin macro
-use crate::db::AstDatabase;
 use crate::{
-    ast::{self, AstToken, HasStringValue},
-    name, AstId, CrateId, MacroDefId, MacroDefKind, TextSize,
+    db::AstDatabase, name, quote, AstId, CrateId, EagerMacroId, LazyMacroId, MacroCallId,
+    MacroDefId, MacroDefKind, TextSize,
 };
 
-use crate::{guess_crate, quote, EagerMacroId, LazyMacroId, MacroCallId};
 use either::Either;
 use mbe::parse_to_token_tree;
 use ra_db::FileId;
 use ra_parser::FragmentKind;
+use ra_syntax::ast::{self, AstToken, HasStringValue};
 
 macro_rules! register_builtin {
     ( LAZY: $(($name:ident, $kind: ident) => $expand:ident),* , EAGER: $(($e_name:ident, $e_kind: ident) => $e_expand:ident),*  ) => {
@@ -333,9 +332,7 @@ fn include_expand(
 }
 
 fn get_env_inner(db: &dyn AstDatabase, arg_id: EagerMacroId, key: &str) -> Option<String> {
-    let call_id: MacroCallId = arg_id.into();
-    let original_file = call_id.as_file().original_file(db);
-    let krate = guess_crate(db, original_file)?;
+    let krate = db.lookup_intern_eager_expansion(arg_id).krate;
     db.crate_graph()[krate].env.get(key)
 }
 
@@ -394,6 +391,7 @@ fn expand_builtin_macro(ra_fixture: &str) -> String {
 
         let expander = find_by_name(&macro_calls[0].name().unwrap().as_name()).unwrap();
 
+        let krate = CrateId(0);
         let file_id = match expander {
             Either::Left(expander) => {
                 // the first one should be a macro_rules
@@ -406,6 +404,7 @@ fn expand_builtin_macro(ra_fixture: &str) -> String {
 
                 let loc = MacroCallLoc {
                     def,
+                    krate,
                     kind: MacroCallKind::FnLike(AstId::new(
                         file_id.into(),
                         ast_id_map.ast_id(&macro_calls[1]),
@@ -418,7 +417,7 @@ fn expand_builtin_macro(ra_fixture: &str) -> String {
             Either::Right(expander) => {
                 // the first one should be a macro_rules
                 let def = MacroDefId {
-                    krate: Some(CrateId(0)),
+                    krate: Some(krate),
                     ast_id: Some(AstId::new(file_id.into(), ast_id_map.ast_id(&macro_calls[0]))),
                     kind: MacroDefKind::BuiltInEager(expander),
                     local_inner: false,
@@ -432,6 +431,7 @@ fn expand_builtin_macro(ra_fixture: &str) -> String {
                         def,
                         fragment: FragmentKind::Expr,
                         subtree: Arc::new(parsed_args.clone()),
+                        krate,
                         file_id: file_id.into(),
                     }
                 });
@@ -441,6 +441,7 @@ fn expand_builtin_macro(ra_fixture: &str) -> String {
                     def,
                     fragment,
                     subtree: Arc::new(subtree),
+                    krate,
                     file_id: file_id.into(),
                 };
 
index 932f47c309898f18d34d5136ae3da4727cdbcdd9..302d2b3e099c67afd2c2eb46beda4b0b142ef59c 100644 (file)
     EagerCallLoc, EagerMacroId, InFile, MacroCallId, MacroCallKind, MacroDefId, MacroDefKind,
 };
 
+use ra_db::CrateId;
 use ra_parser::FragmentKind;
 use ra_syntax::{algo::SyntaxRewriter, SyntaxNode};
 use std::sync::Arc;
 
 pub fn expand_eager_macro(
     db: &dyn AstDatabase,
+    krate: CrateId,
     macro_call: InFile<ast::MacroCall>,
     def: MacroDefId,
     resolver: &dyn Fn(ast::Path) -> Option<MacroDefId>,
@@ -47,6 +49,7 @@ pub fn expand_eager_macro(
             def,
             fragment: FragmentKind::Expr,
             subtree: Arc::new(parsed_args.clone()),
+            krate,
             file_id: macro_call.file_id,
         }
     });
@@ -56,14 +59,20 @@ pub fn expand_eager_macro(
     let result = eager_macro_recur(
         db,
         InFile::new(arg_file_id.as_file(), parsed_args.syntax_node()),
+        krate,
         resolver,
     )?;
     let subtree = to_subtree(&result)?;
 
     if let MacroDefKind::BuiltInEager(eager) = def.kind {
         let (subtree, fragment) = eager.expand(db, arg_id, &subtree).ok()?;
-        let eager =
-            EagerCallLoc { def, fragment, subtree: Arc::new(subtree), file_id: macro_call.file_id };
+        let eager = EagerCallLoc {
+            def,
+            fragment,
+            subtree: Arc::new(subtree),
+            krate,
+            file_id: macro_call.file_id,
+        };
 
         Some(db.intern_eager_expansion(eager))
     } else {
@@ -81,11 +90,12 @@ fn lazy_expand(
     db: &dyn AstDatabase,
     def: &MacroDefId,
     macro_call: InFile<ast::MacroCall>,
+    krate: CrateId,
 ) -> Option<InFile<SyntaxNode>> {
     let ast_id = db.ast_id_map(macro_call.file_id).ast_id(&macro_call.value);
 
     let id: MacroCallId =
-        def.as_lazy_macro(db, MacroCallKind::FnLike(macro_call.with_value(ast_id))).into();
+        def.as_lazy_macro(db, krate, MacroCallKind::FnLike(macro_call.with_value(ast_id))).into();
 
     db.parse_or_expand(id.as_file()).map(|node| InFile::new(id.as_file(), node))
 }
@@ -93,6 +103,7 @@ fn lazy_expand(
 fn eager_macro_recur(
     db: &dyn AstDatabase,
     curr: InFile<SyntaxNode>,
+    krate: CrateId,
     macro_resolver: &dyn Fn(ast::Path) -> Option<MacroDefId>,
 ) -> Option<SyntaxNode> {
     let original = curr.value.clone();
@@ -105,18 +116,23 @@ fn eager_macro_recur(
         let def: MacroDefId = macro_resolver(child.path()?)?;
         let insert = match def.kind {
             MacroDefKind::BuiltInEager(_) => {
-                let id: MacroCallId =
-                    expand_eager_macro(db, curr.with_value(child.clone()), def, macro_resolver)?
-                        .into();
+                let id: MacroCallId = expand_eager_macro(
+                    db,
+                    krate,
+                    curr.with_value(child.clone()),
+                    def,
+                    macro_resolver,
+                )?
+                .into();
                 db.parse_or_expand(id.as_file())?
             }
             MacroDefKind::Declarative
             | MacroDefKind::BuiltIn(_)
             | MacroDefKind::BuiltInDerive(_)
             | MacroDefKind::CustomDerive(_) => {
-                let expanded = lazy_expand(db, &def, curr.with_value(child.clone()))?;
+                let expanded = lazy_expand(db, &def, curr.with_value(child.clone()), krate)?;
                 // replace macro inside
-                eager_macro_recur(db, expanded, macro_resolver)?
+                eager_macro_recur(db, expanded, krate, macro_resolver)?
             }
         };
 
index dc4d7f000e1eca6379f4c641463aa8d6c7545789..5eac2605b9c10e36eccc8e7e3e9e9e74e24c1e89 100644 (file)
@@ -209,8 +209,13 @@ pub struct MacroDefId {
 }
 
 impl MacroDefId {
-    pub fn as_lazy_macro(self, db: &dyn db::AstDatabase, kind: MacroCallKind) -> LazyMacroId {
-        db.intern_macro(MacroCallLoc { def: self, kind })
+    pub fn as_lazy_macro(
+        self,
+        db: &dyn db::AstDatabase,
+        krate: CrateId,
+        kind: MacroCallKind,
+    ) -> LazyMacroId {
+        db.intern_macro(MacroCallLoc { def: self, krate, kind })
     }
 }
 
@@ -227,6 +232,7 @@ pub enum MacroDefKind {
 #[derive(Debug, Clone, PartialEq, Eq, Hash)]
 pub struct MacroCallLoc {
     pub(crate) def: MacroDefId,
+    pub(crate) krate: CrateId,
     pub(crate) kind: MacroCallKind,
 }
 
@@ -274,6 +280,7 @@ pub struct EagerCallLoc {
     pub(crate) def: MacroDefId,
     pub(crate) fragment: FragmentKind,
     pub(crate) subtree: Arc<tt::Subtree>,
+    pub(crate) krate: CrateId,
     pub(crate) file_id: HirFileId,
 }
 
@@ -424,8 +431,3 @@ pub fn syntax(&self) -> InFile<&SyntaxNode> {
         self.with_value(self.value.syntax())
     }
 }
-
-// FIXME: this is obviously wrong, there shouldn't be any guesing here
-fn guess_crate(db: &dyn db::AstDatabase, file_id: FileId) -> Option<CrateId> {
-    db.relevant_crates(file_id).iter().next().copied()
-}