diff options
author | bors[bot] <26634292+bors[bot]@users.noreply.github.com> | 2020-12-16 16:52:46 +0000 |
---|---|---|
committer | GitHub <[email protected]> | 2020-12-16 16:52:46 +0000 |
commit | 63bbdb31e5148c804bbf940963c9c8f3481ad258 (patch) | |
tree | 2732cd2c3878257d9b55447830bc824447332c98 /crates/hir_expand/src | |
parent | 423f3872246f1a67b49e248f3437cb46fdfc8138 (diff) | |
parent | d34611633b3b2404188b9e12b08c5def589808c2 (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.rs | 40 | ||||
-rw-r--r-- | crates/hir_expand/src/builtin_macro.rs | 27 | ||||
-rw-r--r-- | crates/hir_expand/src/db.rs | 5 | ||||
-rw-r--r-- | crates/hir_expand/src/hygiene.rs | 4 | ||||
-rw-r--r-- | crates/hir_expand/src/lib.rs | 15 |
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 | ||
11 | use crate::{db::AstDatabase, name, quote, LazyMacroId, MacroDefId, MacroDefKind}; | 11 | use crate::{db::AstDatabase, name, quote, AstId, CrateId, LazyMacroId, MacroDefId, MacroDefKind}; |
12 | 12 | ||
13 | macro_rules! register_builtin { | 13 | macro_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 | ||
56 | pub 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 | |||
57 | struct BasicAdtInfo { | 70 | struct 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 { | |||
63 | pub fn find_builtin_macro( | 63 | pub 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(¯o_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(¯o_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(¯o_rules[0]))), | 538 | ast_id: Some(AstId::new(file_id.into(), ast_id_map.ast_id(¯o_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(¯o_calls[0]), | 548 | ast_id_map.ast_id(¯o_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(¯o_rules[0]))), | 559 | ast_id: Some(AstId::new(file_id.into(), ast_id_map.ast_id(¯o_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> { | |||
129 | fn macro_def(db: &dyn AstDatabase, id: MacroDefId) -> Option<Arc<(TokenExpander, mbe::TokenMap)>> { | 129 | fn 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)] |
223 | pub struct MacroDefId { | 226 | pub 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, |