aboutsummaryrefslogtreecommitdiff
path: root/crates/ra_hir/src
diff options
context:
space:
mode:
authorbors[bot] <bors[bot]@users.noreply.github.com>2019-05-14 07:12:09 +0100
committerbors[bot] <bors[bot]@users.noreply.github.com>2019-05-14 07:12:09 +0100
commitc417c77b681f10cc7585507bd874e9fd2cea63b8 (patch)
treed05cf30716a7791cfc0d8fcfe522a7132b5fff06 /crates/ra_hir/src
parentee0ab7c00b4b8c5375c14b44e3d7288ebf0d732d (diff)
parentcaa8663c08e1724af2abcde11fa937937d76aa14 (diff)
Merge #1267
1267: Macro expand to r=edwin0cheng a=matklad closes #1264 The core problem this PR is trying to wrangle is that macros can expand to different stuffs, depending on context. That is, `foo!()` on the top-level expands to a list of items, but the same `foo!()` in expression position expands to expression. Our current `hir_parse(HirFileId) -> TreeArc<SourceFile>` does not really support this. So, the plan is to change `hir_parse` to untyped inreface (`TreeArc<Syntaxnode>`), and add `expands_to` field to `MacroCallLoc`, such that the *target* of macro expansion is selected by the calling code and is part of macro id. This unfortunately looses some type-safety :( Moreover, this doesn't really fix #1264 by itself, because we die due to some other error inside macro expansion: expander fails to produce a tree with a single root, which trips assert inside rowan. Co-authored-by: Aleksey Kladov <[email protected]>
Diffstat (limited to 'crates/ra_hir/src')
-rw-r--r--crates/ra_hir/src/db.rs6
-rw-r--r--crates/ra_hir/src/diagnostics.rs6
-rw-r--r--crates/ra_hir/src/expr.rs12
-rw-r--r--crates/ra_hir/src/ids.rs59
-rw-r--r--crates/ra_hir/src/lib.rs1
-rw-r--r--crates/ra_hir/src/nameres/collector.rs4
-rw-r--r--crates/ra_hir/src/nameres/raw.rs7
-rw-r--r--crates/ra_hir/src/source_id.rs14
8 files changed, 67 insertions, 42 deletions
diff --git a/crates/ra_hir/src/db.rs b/crates/ra_hir/src/db.rs
index 8f98ca3a5..8e827d4f5 100644
--- a/crates/ra_hir/src/db.rs
+++ b/crates/ra_hir/src/db.rs
@@ -1,6 +1,6 @@
1use std::sync::{Arc, Mutex}; 1use std::sync::{Arc, Mutex};
2 2
3use ra_syntax::{SyntaxNode, TreeArc, SourceFile, SmolStr, ast}; 3use ra_syntax::{SyntaxNode, TreeArc, SmolStr, ast};
4use ra_db::{SourceDatabase, salsa}; 4use ra_db::{SourceDatabase, salsa};
5 5
6use crate::{ 6use crate::{
@@ -54,8 +54,8 @@ pub trait DefDatabase: SourceDatabase {
54 #[salsa::invoke(crate::ids::macro_expand_query)] 54 #[salsa::invoke(crate::ids::macro_expand_query)]
55 fn macro_expand(&self, macro_call: ids::MacroCallId) -> Result<Arc<tt::Subtree>, String>; 55 fn macro_expand(&self, macro_call: ids::MacroCallId) -> Result<Arc<tt::Subtree>, String>;
56 56
57 #[salsa::invoke(crate::ids::HirFileId::hir_parse_query)] 57 #[salsa::invoke(crate::ids::HirFileId::parse_or_expand_query)]
58 fn hir_parse(&self, file_id: HirFileId) -> TreeArc<SourceFile>; 58 fn parse_or_expand(&self, file_id: HirFileId) -> Option<TreeArc<SyntaxNode>>;
59 59
60 #[salsa::invoke(crate::adt::StructData::struct_data_query)] 60 #[salsa::invoke(crate::adt::StructData::struct_data_query)]
61 fn struct_data(&self, s: Struct) -> Arc<StructData>; 61 fn struct_data(&self, s: Struct) -> Arc<StructData>;
diff --git a/crates/ra_hir/src/diagnostics.rs b/crates/ra_hir/src/diagnostics.rs
index d41525779..4b7b2dbee 100644
--- a/crates/ra_hir/src/diagnostics.rs
+++ b/crates/ra_hir/src/diagnostics.rs
@@ -1,6 +1,6 @@
1use std::{fmt, any::Any}; 1use std::{fmt, any::Any};
2 2
3use ra_syntax::{SyntaxNodePtr, TreeArc, AstPtr, TextRange, ast, SyntaxNode, AstNode}; 3use ra_syntax::{SyntaxNodePtr, TreeArc, AstPtr, TextRange, ast, SyntaxNode};
4use relative_path::RelativePathBuf; 4use relative_path::RelativePathBuf;
5 5
6use crate::{HirFileId, HirDatabase, Name}; 6use crate::{HirFileId, HirDatabase, Name};
@@ -29,8 +29,8 @@ pub trait Diagnostic: Any + Send + Sync + fmt::Debug + 'static {
29 29
30impl dyn Diagnostic { 30impl dyn Diagnostic {
31 pub fn syntax_node(&self, db: &impl HirDatabase) -> TreeArc<SyntaxNode> { 31 pub fn syntax_node(&self, db: &impl HirDatabase) -> TreeArc<SyntaxNode> {
32 let source_file = db.hir_parse(self.file()); 32 let node = db.parse_or_expand(self.file()).unwrap();
33 self.syntax_node_ptr().to_node(source_file.syntax()).to_owned() 33 self.syntax_node_ptr().to_node(&*node).to_owned()
34 } 34 }
35 pub fn downcast_ref<D: Diagnostic>(&self) -> Option<&D> { 35 pub fn downcast_ref<D: Diagnostic>(&self) -> Option<&D> {
36 self.as_any().downcast_ref() 36 self.as_any().downcast_ref()
diff --git a/crates/ra_hir/src/expr.rs b/crates/ra_hir/src/expr.rs
index a2b5db1a1..9618236e5 100644
--- a/crates/ra_hir/src/expr.rs
+++ b/crates/ra_hir/src/expr.rs
@@ -6,11 +6,11 @@ use rustc_hash::FxHashMap;
6use ra_arena::{Arena, RawId, impl_arena_id, map::ArenaMap}; 6use ra_arena::{Arena, RawId, impl_arena_id, map::ArenaMap};
7use ra_syntax::{ 7use ra_syntax::{
8 SyntaxNodePtr, AstPtr, AstNode, 8 SyntaxNodePtr, AstPtr, AstNode,
9 ast::{self, LoopBodyOwner, ArgListOwner, NameOwner, LiteralKind,ArrayExprKind, TypeAscriptionOwner} 9 ast::{self, LoopBodyOwner, ArgListOwner, NameOwner, LiteralKind,ArrayExprKind, TypeAscriptionOwner},
10}; 10};
11 11
12use crate::{ 12use crate::{
13 Path, Name, HirDatabase, Resolver,DefWithBody, Either, HirFileId, MacroCallLoc, 13 Path, Name, HirDatabase, Resolver,DefWithBody, Either, HirFileId, MacroCallLoc, MacroFileKind,
14 name::AsName, 14 name::AsName,
15 type_ref::{Mutability, TypeRef}, 15 type_ref::{Mutability, TypeRef},
16}; 16};
@@ -830,11 +830,11 @@ where
830 830
831 if let Some(def) = self.resolver.resolve_macro_call(path) { 831 if let Some(def) = self.resolver.resolve_macro_call(path) {
832 let call_id = MacroCallLoc { def, ast_id }.id(self.db); 832 let call_id = MacroCallLoc { def, ast_id }.id(self.db);
833 if let Some(tt) = self.db.macro_expand(call_id).ok() { 833 let file_id = call_id.as_file(MacroFileKind::Expr);
834 if let Some(expr) = mbe::token_tree_to_expr(&tt).ok() { 834 if let Some(node) = self.db.parse_or_expand(file_id) {
835 if let Some(expr) = ast::Expr::cast(&*node) {
835 log::debug!("macro expansion {}", expr.syntax().debug_dump()); 836 log::debug!("macro expansion {}", expr.syntax().debug_dump());
836 let old_file_id = 837 let old_file_id = std::mem::replace(&mut self.current_file_id, file_id);
837 std::mem::replace(&mut self.current_file_id, call_id.into());
838 let id = self.collect_expr(&expr); 838 let id = self.collect_expr(&expr);
839 self.current_file_id = old_file_id; 839 self.current_file_id = old_file_id;
840 return id; 840 return id;
diff --git a/crates/ra_hir/src/ids.rs b/crates/ra_hir/src/ids.rs
index ff4a81e59..f901a7432 100644
--- a/crates/ra_hir/src/ids.rs
+++ b/crates/ra_hir/src/ids.rs
@@ -4,7 +4,7 @@ use std::{
4}; 4};
5 5
6use ra_db::{FileId, salsa}; 6use ra_db::{FileId, salsa};
7use ra_syntax::{TreeArc, SourceFile, AstNode, ast}; 7use ra_syntax::{TreeArc, AstNode, ast, SyntaxNode};
8use mbe::MacroRules; 8use mbe::MacroRules;
9 9
10use crate::{ 10use crate::{
@@ -39,8 +39,8 @@ impl HirFileId {
39 pub fn original_file(self, db: &impl DefDatabase) -> FileId { 39 pub fn original_file(self, db: &impl DefDatabase) -> FileId {
40 match self.0 { 40 match self.0 {
41 HirFileIdRepr::File(file_id) => file_id, 41 HirFileIdRepr::File(file_id) => file_id,
42 HirFileIdRepr::Macro(macro_call_id) => { 42 HirFileIdRepr::Macro(macro_file) => {
43 let loc = macro_call_id.loc(db); 43 let loc = macro_file.macro_call_id.loc(db);
44 loc.ast_id.file_id().original_file(db) 44 loc.ast_id.file_id().original_file(db)
45 } 45 }
46 } 46 }
@@ -56,16 +56,17 @@ impl HirFileId {
56 } 56 }
57 } 57 }
58 58
59 pub(crate) fn hir_parse_query( 59 pub(crate) fn parse_or_expand_query(
60 db: &impl DefDatabase, 60 db: &impl DefDatabase,
61 file_id: HirFileId, 61 file_id: HirFileId,
62 ) -> TreeArc<SourceFile> { 62 ) -> Option<TreeArc<SyntaxNode>> {
63 match file_id.0 { 63 match file_id.0 {
64 HirFileIdRepr::File(file_id) => db.parse(file_id), 64 HirFileIdRepr::File(file_id) => Some(db.parse(file_id).syntax().to_owned()),
65 HirFileIdRepr::Macro(macro_call_id) => { 65 HirFileIdRepr::Macro(macro_file) => {
66 match db.macro_expand(macro_call_id) { 66 let macro_call_id = macro_file.macro_call_id;
67 Ok(tt) => mbe::token_tree_to_ast_item_list(&tt), 67 let tt = db
68 Err(err) => { 68 .macro_expand(macro_call_id)
69 .map_err(|err| {
69 // Note: 70 // Note:
70 // The final goal we would like to make all parse_macro success, 71 // The final goal we would like to make all parse_macro success,
71 // such that the following log will not call anyway. 72 // such that the following log will not call anyway.
@@ -74,9 +75,14 @@ impl HirFileId {
74 err, 75 err,
75 macro_call_id.debug_dump(db) 76 macro_call_id.debug_dump(db)
76 ); 77 );
77 78 })
78 // returning an empty string looks fishy... 79 .ok()?;
79 SourceFile::parse("") 80 match macro_file.macro_file_kind {
81 MacroFileKind::Items => {
82 Some(mbe::token_tree_to_ast_item_list(&tt).syntax().to_owned())
83 }
84 MacroFileKind::Expr => {
85 mbe::token_tree_to_expr(&tt).ok().map(|it| it.syntax().to_owned())
80 } 86 }
81 } 87 }
82 } 88 }
@@ -87,7 +93,19 @@ impl HirFileId {
87#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] 93#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
88enum HirFileIdRepr { 94enum HirFileIdRepr {
89 File(FileId), 95 File(FileId),
90 Macro(MacroCallId), 96 Macro(MacroFile),
97}
98
99#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
100struct MacroFile {
101 macro_call_id: MacroCallId,
102 macro_file_kind: MacroFileKind,
103}
104
105#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
106pub(crate) enum MacroFileKind {
107 Items,
108 Expr,
91} 109}
92 110
93impl From<FileId> for HirFileId { 111impl From<FileId> for HirFileId {
@@ -96,12 +114,6 @@ impl From<FileId> for HirFileId {
96 } 114 }
97} 115}
98 116
99impl From<MacroCallId> for HirFileId {
100 fn from(macro_call_id: MacroCallId) -> HirFileId {
101 HirFileId(HirFileIdRepr::Macro(macro_call_id))
102 }
103}
104
105#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] 117#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
106pub struct MacroDefId(pub(crate) AstId<ast::MacroCall>); 118pub struct MacroDefId(pub(crate) AstId<ast::MacroCall>);
107 119
@@ -173,6 +185,11 @@ impl MacroCallId {
173 pub(crate) fn loc(self, db: &impl DefDatabase) -> MacroCallLoc { 185 pub(crate) fn loc(self, db: &impl DefDatabase) -> MacroCallLoc {
174 db.lookup_intern_macro(self) 186 db.lookup_intern_macro(self)
175 } 187 }
188
189 pub(crate) fn as_file(self, kind: MacroFileKind) -> HirFileId {
190 let macro_file = MacroFile { macro_call_id: self, macro_file_kind: kind };
191 HirFileId(HirFileIdRepr::Macro(macro_file))
192 }
176} 193}
177 194
178impl MacroCallLoc { 195impl MacroCallLoc {
@@ -342,7 +359,7 @@ impl MacroCallId {
342 let syntax_str = node.syntax().text().chunks().collect::<Vec<_>>().join(" "); 359 let syntax_str = node.syntax().text().chunks().collect::<Vec<_>>().join(" ");
343 360
344 // dump the file name 361 // dump the file name
345 let file_id: HirFileId = self.clone().into(); 362 let file_id: HirFileId = self.loc(db).ast_id.file_id();
346 let original = file_id.original_file(db); 363 let original = file_id.original_file(db);
347 let macro_rules = db.macro_def(loc.def); 364 let macro_rules = db.macro_def(loc.def);
348 365
diff --git a/crates/ra_hir/src/lib.rs b/crates/ra_hir/src/lib.rs
index 03b1063b6..0c6d7c2b7 100644
--- a/crates/ra_hir/src/lib.rs
+++ b/crates/ra_hir/src/lib.rs
@@ -53,6 +53,7 @@ use crate::{
53 name::{AsName, KnownName}, 53 name::{AsName, KnownName},
54 source_id::{FileAstId, AstId}, 54 source_id::{FileAstId, AstId},
55 resolve::Resolver, 55 resolve::Resolver,
56 ids::MacroFileKind,
56}; 57};
57 58
58pub use self::{ 59pub use self::{
diff --git a/crates/ra_hir/src/nameres/collector.rs b/crates/ra_hir/src/nameres/collector.rs
index 4640b3b74..c615d80c3 100644
--- a/crates/ra_hir/src/nameres/collector.rs
+++ b/crates/ra_hir/src/nameres/collector.rs
@@ -15,7 +15,7 @@ use crate::{
15 diagnostics::DefDiagnostic, 15 diagnostics::DefDiagnostic,
16 raw, 16 raw,
17 }, 17 },
18 ids::{AstItemDef, LocationCtx, MacroCallLoc, MacroCallId, MacroDefId}, 18 ids::{AstItemDef, LocationCtx, MacroCallLoc, MacroCallId, MacroDefId, MacroFileKind},
19 AstId, 19 AstId,
20}; 20};
21 21
@@ -371,7 +371,7 @@ where
371 self.macro_stack_monitor.increase(macro_def_id); 371 self.macro_stack_monitor.increase(macro_def_id);
372 372
373 if !self.macro_stack_monitor.is_poison(macro_def_id) { 373 if !self.macro_stack_monitor.is_poison(macro_def_id) {
374 let file_id: HirFileId = macro_call_id.into(); 374 let file_id: HirFileId = macro_call_id.as_file(MacroFileKind::Items);
375 let raw_items = self.db.raw_items(file_id); 375 let raw_items = self.db.raw_items(file_id);
376 ModCollector { def_collector: &mut *self, file_id, module_id, raw_items: &raw_items } 376 ModCollector { def_collector: &mut *self, file_id, module_id, raw_items: &raw_items }
377 .collect(raw_items.items()); 377 .collect(raw_items.items());
diff --git a/crates/ra_hir/src/nameres/raw.rs b/crates/ra_hir/src/nameres/raw.rs
index 211e02068..bd32b264b 100644
--- a/crates/ra_hir/src/nameres/raw.rs
+++ b/crates/ra_hir/src/nameres/raw.rs
@@ -75,8 +75,11 @@ impl RawItems {
75 source_ast_id_map: db.ast_id_map(file_id.into()), 75 source_ast_id_map: db.ast_id_map(file_id.into()),
76 source_map: ImportSourceMap::default(), 76 source_map: ImportSourceMap::default(),
77 }; 77 };
78 let source_file = db.hir_parse(file_id); 78 if let Some(node) = db.parse_or_expand(file_id) {
79 collector.process_module(None, &*source_file); 79 if let Some(source_file) = ast::SourceFile::cast(&node) {
80 collector.process_module(None, &*source_file);
81 }
82 }
80 (Arc::new(collector.raw_items), Arc::new(collector.source_map)) 83 (Arc::new(collector.raw_items), Arc::new(collector.source_map))
81 } 84 }
82 85
diff --git a/crates/ra_hir/src/source_id.rs b/crates/ra_hir/src/source_id.rs
index 7a39be779..13f548eaf 100644
--- a/crates/ra_hir/src/source_id.rs
+++ b/crates/ra_hir/src/source_id.rs
@@ -81,15 +81,19 @@ pub struct ErasedFileAstId(RawId);
81impl_arena_id!(ErasedFileAstId); 81impl_arena_id!(ErasedFileAstId);
82 82
83/// Maps items' `SyntaxNode`s to `ErasedFileAstId`s and back. 83/// Maps items' `SyntaxNode`s to `ErasedFileAstId`s and back.
84#[derive(Debug, PartialEq, Eq)] 84#[derive(Debug, PartialEq, Eq, Default)]
85pub struct AstIdMap { 85pub struct AstIdMap {
86 arena: Arena<ErasedFileAstId, SyntaxNodePtr>, 86 arena: Arena<ErasedFileAstId, SyntaxNodePtr>,
87} 87}
88 88
89impl AstIdMap { 89impl AstIdMap {
90 pub(crate) fn ast_id_map_query(db: &impl DefDatabase, file_id: HirFileId) -> Arc<AstIdMap> { 90 pub(crate) fn ast_id_map_query(db: &impl DefDatabase, file_id: HirFileId) -> Arc<AstIdMap> {
91 let source_file = db.hir_parse(file_id); 91 let map = if let Some(node) = db.parse_or_expand(file_id) {
92 Arc::new(AstIdMap::from_source(source_file.syntax())) 92 AstIdMap::from_source(&*node)
93 } else {
94 AstIdMap::default()
95 };
96 Arc::new(map)
93 } 97 }
94 98
95 pub(crate) fn file_item_query( 99 pub(crate) fn file_item_query(
@@ -97,8 +101,8 @@ impl AstIdMap {
97 file_id: HirFileId, 101 file_id: HirFileId,
98 ast_id: ErasedFileAstId, 102 ast_id: ErasedFileAstId,
99 ) -> TreeArc<SyntaxNode> { 103 ) -> TreeArc<SyntaxNode> {
100 let source_file = db.hir_parse(file_id); 104 let node = db.parse_or_expand(file_id).unwrap();
101 db.ast_id_map(file_id).arena[ast_id].to_node(source_file.syntax()).to_owned() 105 db.ast_id_map(file_id).arena[ast_id].to_node(&*node).to_owned()
102 } 106 }
103 107
104 pub(crate) fn ast_id<N: AstNode>(&self, item: &N) -> FileAstId<N> { 108 pub(crate) fn ast_id<N: AstNode>(&self, item: &N) -> FileAstId<N> {