aboutsummaryrefslogtreecommitdiff
path: root/crates/hir_expand/src
diff options
context:
space:
mode:
authorbors[bot] <26634292+bors[bot]@users.noreply.github.com>2020-12-16 16:52:46 +0000
committerGitHub <[email protected]>2020-12-16 16:52:46 +0000
commit63bbdb31e5148c804bbf940963c9c8f3481ad258 (patch)
tree2732cd2c3878257d9b55447830bc824447332c98 /crates/hir_expand/src
parent423f3872246f1a67b49e248f3437cb46fdfc8138 (diff)
parentd34611633b3b2404188b9e12b08c5def589808c2 (diff)
Merge #6897
6897: Basic support for macros 2.0 r=jonas-schievink a=jonas-schievink This adds support for (built-in-only) macros 2.0, and removes some hacks used for builtin derives, which are declared via macros 2.0 in libcore. First steps for https://github.com/rust-analyzer/rust-analyzer/issues/2248. Blocked on https://github.com/rust-analyzer/ungrammar/pull/16. Co-authored-by: Jonas Schievink <[email protected]> Co-authored-by: Jonas Schievink <[email protected]>
Diffstat (limited to 'crates/hir_expand/src')
-rw-r--r--crates/hir_expand/src/builtin_derive.rs40
-rw-r--r--crates/hir_expand/src/builtin_macro.rs27
-rw-r--r--crates/hir_expand/src/db.rs5
-rw-r--r--crates/hir_expand/src/hygiene.rs4
-rw-r--r--crates/hir_expand/src/lib.rs15
5 files changed, 56 insertions, 35 deletions
diff --git a/crates/hir_expand/src/builtin_derive.rs b/crates/hir_expand/src/builtin_derive.rs
index 988a60d56..ad378762a 100644
--- a/crates/hir_expand/src/builtin_derive.rs
+++ b/crates/hir_expand/src/builtin_derive.rs
@@ -8,7 +8,7 @@ use syntax::{
8 match_ast, 8 match_ast,
9}; 9};
10 10
11use crate::{db::AstDatabase, name, quote, LazyMacroId, MacroDefId, MacroDefKind}; 11use crate::{db::AstDatabase, name, quote, AstId, CrateId, LazyMacroId, MacroDefId, MacroDefKind};
12 12
13macro_rules! register_builtin { 13macro_rules! register_builtin {
14 ( $($trait:ident => $expand:ident),* ) => { 14 ( $($trait:ident => $expand:ident),* ) => {
@@ -29,16 +29,15 @@ macro_rules! register_builtin {
29 }; 29 };
30 expander(db, id, tt) 30 expander(db, id, tt)
31 } 31 }
32 }
33
34 pub fn find_builtin_derive(ident: &name::Name) -> Option<MacroDefId> {
35 let kind = match ident {
36 $( id if id == &name::name![$trait] => BuiltinDeriveExpander::$trait, )*
37 _ => return None,
38 };
39 32
40 Some(MacroDefId { krate: None, ast_id: None, kind: MacroDefKind::BuiltInDerive(kind), local_inner: false }) 33 fn find_by_name(name: &name::Name) -> Option<Self> {
34 match name {
35 $( id if id == &name::name![$trait] => Some(BuiltinDeriveExpander::$trait), )*
36 _ => None,
37 }
38 }
41 } 39 }
40
42 }; 41 };
43} 42}
44 43
@@ -54,6 +53,20 @@ register_builtin! {
54 PartialEq => partial_eq_expand 53 PartialEq => partial_eq_expand
55} 54}
56 55
56pub fn find_builtin_derive(
57 ident: &name::Name,
58 krate: CrateId,
59 ast_id: AstId<ast::Macro>,
60) -> Option<MacroDefId> {
61 let expander = BuiltinDeriveExpander::find_by_name(ident)?;
62 Some(MacroDefId {
63 krate,
64 ast_id: Some(ast_id),
65 kind: MacroDefKind::BuiltInDerive(expander),
66 local_inner: false,
67 })
68}
69
57struct BasicAdtInfo { 70struct BasicAdtInfo {
58 name: tt::Ident, 71 name: tt::Ident,
59 type_params: usize, 72 type_params: usize,
@@ -261,7 +274,7 @@ mod tests {
261 use super::*; 274 use super::*;
262 275
263 fn expand_builtin_derive(s: &str, name: Name) -> String { 276 fn expand_builtin_derive(s: &str, name: Name) -> String {
264 let def = find_builtin_derive(&name).unwrap(); 277 let expander = BuiltinDeriveExpander::find_by_name(&name).unwrap();
265 let fixture = format!( 278 let fixture = format!(
266 r#"//- /main.rs crate:main deps:core 279 r#"//- /main.rs crate:main deps:core
267<|> 280<|>
@@ -283,7 +296,12 @@ mod tests {
283 let attr_id = AstId::new(file_id.into(), ast_id_map.ast_id(&items[0])); 296 let attr_id = AstId::new(file_id.into(), ast_id_map.ast_id(&items[0]));
284 297
285 let loc = MacroCallLoc { 298 let loc = MacroCallLoc {
286 def, 299 def: MacroDefId {
300 krate: CrateId(0),
301 ast_id: None,
302 kind: MacroDefKind::BuiltInDerive(expander),
303 local_inner: false,
304 },
287 krate: CrateId(0), 305 krate: CrateId(0),
288 kind: MacroCallKind::Attr(attr_id, name.to_string()), 306 kind: MacroCallKind::Attr(attr_id, name.to_string()),
289 }; 307 };
diff --git a/crates/hir_expand/src/builtin_macro.rs b/crates/hir_expand/src/builtin_macro.rs
index bd9223825..dddbbcdac 100644
--- a/crates/hir_expand/src/builtin_macro.rs
+++ b/crates/hir_expand/src/builtin_macro.rs
@@ -63,19 +63,19 @@ macro_rules! register_builtin {
63pub fn find_builtin_macro( 63pub fn find_builtin_macro(
64 ident: &name::Name, 64 ident: &name::Name,
65 krate: CrateId, 65 krate: CrateId,
66 ast_id: AstId<ast::MacroRules>, 66 ast_id: AstId<ast::Macro>,
67) -> Option<MacroDefId> { 67) -> Option<MacroDefId> {
68 let kind = find_by_name(ident)?; 68 let kind = find_by_name(ident)?;
69 69
70 match kind { 70 match kind {
71 Either::Left(kind) => Some(MacroDefId { 71 Either::Left(kind) => Some(MacroDefId {
72 krate: Some(krate), 72 krate,
73 ast_id: Some(ast_id), 73 ast_id: Some(ast_id),
74 kind: MacroDefKind::BuiltIn(kind), 74 kind: MacroDefKind::BuiltIn(kind),
75 local_inner: false, 75 local_inner: false,
76 }), 76 }),
77 Either::Right(kind) => Some(MacroDefId { 77 Either::Right(kind) => Some(MacroDefId {
78 krate: Some(krate), 78 krate,
79 ast_id: Some(ast_id), 79 ast_id: Some(ast_id),
80 kind: MacroDefKind::BuiltInEager(kind), 80 kind: MacroDefKind::BuiltInEager(kind),
81 local_inner: false, 81 local_inner: false,
@@ -515,24 +515,27 @@ mod tests {
515 fn expand_builtin_macro(ra_fixture: &str) -> String { 515 fn expand_builtin_macro(ra_fixture: &str) -> String {
516 let (db, file_id) = TestDB::with_single_file(&ra_fixture); 516 let (db, file_id) = TestDB::with_single_file(&ra_fixture);
517 let parsed = db.parse(file_id); 517 let parsed = db.parse(file_id);
518 let macro_rules: Vec<_> = 518 let mut macro_rules: Vec<_> =
519 parsed.syntax_node().descendants().filter_map(ast::MacroRules::cast).collect(); 519 parsed.syntax_node().descendants().filter_map(ast::MacroRules::cast).collect();
520 let macro_calls: Vec<_> = 520 let mut macro_calls: Vec<_> =
521 parsed.syntax_node().descendants().filter_map(ast::MacroCall::cast).collect(); 521 parsed.syntax_node().descendants().filter_map(ast::MacroCall::cast).collect();
522 522
523 let ast_id_map = db.ast_id_map(file_id.into()); 523 let ast_id_map = db.ast_id_map(file_id.into());
524 524
525 assert_eq!(macro_rules.len(), 1, "test must contain exactly 1 `macro_rules!`"); 525 assert_eq!(macro_rules.len(), 1, "test must contain exactly 1 `macro_rules!`");
526 assert_eq!(macro_calls.len(), 1, "test must contain exactly 1 macro call"); 526 assert_eq!(macro_calls.len(), 1, "test must contain exactly 1 macro call");
527 let expander = find_by_name(&macro_rules[0].name().unwrap().as_name()).unwrap(); 527 let macro_rules = ast::Macro::from(macro_rules.pop().unwrap());
528 let macro_call = macro_calls.pop().unwrap();
529
530 let expander = find_by_name(&macro_rules.name().unwrap().as_name()).unwrap();
528 531
529 let krate = CrateId(0); 532 let krate = CrateId(0);
530 let file_id = match expander { 533 let file_id = match expander {
531 Either::Left(expander) => { 534 Either::Left(expander) => {
532 // the first one should be a macro_rules 535 // the first one should be a macro_rules
533 let def = MacroDefId { 536 let def = MacroDefId {
534 krate: Some(CrateId(0)), 537 krate: CrateId(0),
535 ast_id: Some(AstId::new(file_id.into(), ast_id_map.ast_id(&macro_rules[0]))), 538 ast_id: Some(AstId::new(file_id.into(), ast_id_map.ast_id(&macro_rules))),
536 kind: MacroDefKind::BuiltIn(expander), 539 kind: MacroDefKind::BuiltIn(expander),
537 local_inner: false, 540 local_inner: false,
538 }; 541 };
@@ -542,7 +545,7 @@ mod tests {
542 krate, 545 krate,
543 kind: MacroCallKind::FnLike(AstId::new( 546 kind: MacroCallKind::FnLike(AstId::new(
544 file_id.into(), 547 file_id.into(),
545 ast_id_map.ast_id(&macro_calls[0]), 548 ast_id_map.ast_id(&macro_call),
546 )), 549 )),
547 }; 550 };
548 551
@@ -552,13 +555,13 @@ mod tests {
552 Either::Right(expander) => { 555 Either::Right(expander) => {
553 // the first one should be a macro_rules 556 // the first one should be a macro_rules
554 let def = MacroDefId { 557 let def = MacroDefId {
555 krate: Some(krate), 558 krate,
556 ast_id: Some(AstId::new(file_id.into(), ast_id_map.ast_id(&macro_rules[0]))), 559 ast_id: Some(AstId::new(file_id.into(), ast_id_map.ast_id(&macro_rules))),
557 kind: MacroDefKind::BuiltInEager(expander), 560 kind: MacroDefKind::BuiltInEager(expander),
558 local_inner: false, 561 local_inner: false,
559 }; 562 };
560 563
561 let args = macro_calls[0].token_tree().unwrap(); 564 let args = macro_call.token_tree().unwrap();
562 let parsed_args = mbe::ast_to_token_tree(&args).unwrap().0; 565 let parsed_args = mbe::ast_to_token_tree(&args).unwrap().0;
563 566
564 let arg_id = db.intern_eager_expansion({ 567 let arg_id = db.intern_eager_expansion({
diff --git a/crates/hir_expand/src/db.rs b/crates/hir_expand/src/db.rs
index 11b5b98c8..4477d867f 100644
--- a/crates/hir_expand/src/db.rs
+++ b/crates/hir_expand/src/db.rs
@@ -129,7 +129,10 @@ fn ast_id_map(db: &dyn AstDatabase, file_id: HirFileId) -> Arc<AstIdMap> {
129fn macro_def(db: &dyn AstDatabase, id: MacroDefId) -> Option<Arc<(TokenExpander, mbe::TokenMap)>> { 129fn macro_def(db: &dyn AstDatabase, id: MacroDefId) -> Option<Arc<(TokenExpander, mbe::TokenMap)>> {
130 match id.kind { 130 match id.kind {
131 MacroDefKind::Declarative => { 131 MacroDefKind::Declarative => {
132 let macro_call = id.ast_id?.to_node(db); 132 let macro_call = match id.ast_id?.to_node(db) {
133 syntax::ast::Macro::MacroRules(mac) => mac,
134 syntax::ast::Macro::MacroDef(_) => return None,
135 };
133 let arg = macro_call.token_tree()?; 136 let arg = macro_call.token_tree()?;
134 let (tt, tmap) = mbe::ast_to_token_tree(&arg).or_else(|| { 137 let (tt, tmap) = mbe::ast_to_token_tree(&arg).or_else(|| {
135 log::warn!("fail on macro_def to token tree: {:#?}", arg); 138 log::warn!("fail on macro_def to token tree: {:#?}", arg);
diff --git a/crates/hir_expand/src/hygiene.rs b/crates/hir_expand/src/hygiene.rs
index 5d3fa0518..7ab0a5e52 100644
--- a/crates/hir_expand/src/hygiene.rs
+++ b/crates/hir_expand/src/hygiene.rs
@@ -29,8 +29,8 @@ impl Hygiene {
29 MacroCallId::LazyMacro(id) => { 29 MacroCallId::LazyMacro(id) => {
30 let loc = db.lookup_intern_macro(id); 30 let loc = db.lookup_intern_macro(id);
31 match loc.def.kind { 31 match loc.def.kind {
32 MacroDefKind::Declarative => (loc.def.krate, loc.def.local_inner), 32 MacroDefKind::Declarative => (Some(loc.def.krate), loc.def.local_inner),
33 MacroDefKind::BuiltIn(_) => (loc.def.krate, false), 33 MacroDefKind::BuiltIn(_) => (Some(loc.def.krate), false),
34 MacroDefKind::BuiltInDerive(_) => (None, false), 34 MacroDefKind::BuiltInDerive(_) => (None, false),
35 MacroDefKind::BuiltInEager(_) => (None, false), 35 MacroDefKind::BuiltInEager(_) => (None, false),
36 MacroDefKind::ProcMacro(_) => (None, false), 36 MacroDefKind::ProcMacro(_) => (None, false),
diff --git a/crates/hir_expand/src/lib.rs b/crates/hir_expand/src/lib.rs
index ae3086a95..d486186e5 100644
--- a/crates/hir_expand/src/lib.rs
+++ b/crates/hir_expand/src/lib.rs
@@ -145,7 +145,10 @@ impl HirFileId {
145 let arg_tt = loc.kind.arg(db)?; 145 let arg_tt = loc.kind.arg(db)?;
146 146
147 let def = loc.def.ast_id.and_then(|id| { 147 let def = loc.def.ast_id.and_then(|id| {
148 let def_tt = id.to_node(db).token_tree()?; 148 let def_tt = match id.to_node(db) {
149 ast::Macro::MacroRules(mac) => mac.token_tree()?,
150 ast::Macro::MacroDef(_) => return None,
151 };
149 Some(InFile::new(id.file_id, def_tt)) 152 Some(InFile::new(id.file_id, def_tt))
150 }); 153 });
151 154
@@ -221,14 +224,8 @@ impl From<EagerMacroId> for MacroCallId {
221 224
222#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] 225#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
223pub struct MacroDefId { 226pub struct MacroDefId {
224 // FIXME: krate and ast_id are currently optional because we don't have a 227 pub krate: CrateId,
225 // definition location for built-in derives. There is one, though: the 228 pub ast_id: Option<AstId<ast::Macro>>,
226 // standard library defines them. The problem is that it uses the new
227 // `macro` syntax for this, which we don't support yet. As soon as we do
228 // (which will probably require touching this code), we can instead use
229 // that (and also remove the hacks for resolving built-in derives).
230 pub krate: Option<CrateId>,
231 pub ast_id: Option<AstId<ast::MacroRules>>,
232 pub kind: MacroDefKind, 229 pub kind: MacroDefKind,
233 230
234 pub local_inner: bool, 231 pub local_inner: bool,