aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--crates/hir/src/lib.rs1
-rw-r--r--crates/hir_def/src/nameres/collector.rs4
-rw-r--r--crates/hir_expand/src/builtin_attr.rs115
-rw-r--r--crates/hir_expand/src/db.rs14
-rw-r--r--crates/hir_expand/src/eager.rs1
-rw-r--r--crates/hir_expand/src/hygiene.rs1
-rw-r--r--crates/hir_expand/src/lib.rs4
-rw-r--r--crates/hir_expand/src/name.rs9
-rw-r--r--crates/ide_completion/src/completions/qualified_path.rs26
-rw-r--r--crates/ide_completion/src/completions/unqualified_path.rs12
10 files changed, 176 insertions, 11 deletions
diff --git a/crates/hir/src/lib.rs b/crates/hir/src/lib.rs
index dba46df04..debc3ee62 100644
--- a/crates/hir/src/lib.rs
+++ b/crates/hir/src/lib.rs
@@ -1344,6 +1344,7 @@ impl MacroDef {
1344 MacroDefKind::Declarative(_) => MacroKind::Declarative, 1344 MacroDefKind::Declarative(_) => MacroKind::Declarative,
1345 MacroDefKind::BuiltIn(_, _) | MacroDefKind::BuiltInEager(_, _) => MacroKind::BuiltIn, 1345 MacroDefKind::BuiltIn(_, _) | MacroDefKind::BuiltInEager(_, _) => MacroKind::BuiltIn,
1346 MacroDefKind::BuiltInDerive(_, _) => MacroKind::Derive, 1346 MacroDefKind::BuiltInDerive(_, _) => MacroKind::Derive,
1347 MacroDefKind::BuiltInAttr(_, _) => MacroKind::Attr,
1347 MacroDefKind::ProcMacro(_, base_db::ProcMacroKind::CustomDerive, _) => { 1348 MacroDefKind::ProcMacro(_, base_db::ProcMacroKind::CustomDerive, _) => {
1348 MacroKind::Derive 1349 MacroKind::Derive
1349 } 1350 }
diff --git a/crates/hir_def/src/nameres/collector.rs b/crates/hir_def/src/nameres/collector.rs
index d019ba3a9..93f30f23d 100644
--- a/crates/hir_def/src/nameres/collector.rs
+++ b/crates/hir_def/src/nameres/collector.rs
@@ -9,6 +9,7 @@ use base_db::{CrateId, Edition, FileId, ProcMacroId};
9use cfg::{CfgExpr, CfgOptions}; 9use cfg::{CfgExpr, CfgOptions};
10use hir_expand::{ 10use hir_expand::{
11 ast_id_map::FileAstId, 11 ast_id_map::FileAstId,
12 builtin_attr::find_builtin_attr,
12 builtin_derive::find_builtin_derive, 13 builtin_derive::find_builtin_derive,
13 builtin_macro::find_builtin_macro, 14 builtin_macro::find_builtin_macro,
14 name::{name, AsName, Name}, 15 name::{name, AsName, Name},
@@ -1836,7 +1837,8 @@ impl ModCollector<'_, '_> {
1836 let attrs = self.item_tree.attrs(self.def_collector.db, krate, ModItem::from(id).into()); 1837 let attrs = self.item_tree.attrs(self.def_collector.db, krate, ModItem::from(id).into());
1837 if attrs.by_key("rustc_builtin_macro").exists() { 1838 if attrs.by_key("rustc_builtin_macro").exists() {
1838 let macro_id = find_builtin_macro(&mac.name, krate, ast_id) 1839 let macro_id = find_builtin_macro(&mac.name, krate, ast_id)
1839 .or_else(|| find_builtin_derive(&mac.name, krate, ast_id)); 1840 .or_else(|| find_builtin_derive(&mac.name, krate, ast_id))
1841 .or_else(|| find_builtin_attr(&mac.name, krate, ast_id));
1840 1842
1841 match macro_id { 1843 match macro_id {
1842 Some(macro_id) => { 1844 Some(macro_id) => {
diff --git a/crates/hir_expand/src/builtin_attr.rs b/crates/hir_expand/src/builtin_attr.rs
new file mode 100644
index 000000000..3024410fb
--- /dev/null
+++ b/crates/hir_expand/src/builtin_attr.rs
@@ -0,0 +1,115 @@
1//! Builtin derives.
2
3use syntax::ast;
4
5use crate::{db::AstDatabase, name, AstId, CrateId, MacroCallId, MacroDefId, MacroDefKind};
6
7macro_rules! register_builtin {
8 ( $(($name:ident, $variant:ident) => $expand:ident),* ) => {
9 #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
10 pub enum BuiltinAttrExpander {
11 $($variant),*
12 }
13
14 impl BuiltinAttrExpander {
15 pub fn expand(
16 &self,
17 db: &dyn AstDatabase,
18 id: MacroCallId,
19 tt: &tt::Subtree,
20 ) -> Result<tt::Subtree, mbe::ExpandError> {
21 let expander = match *self {
22 $( BuiltinAttrExpander::$variant => $expand, )*
23 };
24 expander(db, id, tt)
25 }
26
27 fn find_by_name(name: &name::Name) -> Option<Self> {
28 match name {
29 $( id if id == &name::name![$name] => Some(BuiltinAttrExpander::$variant), )*
30 _ => None,
31 }
32 }
33 }
34
35 };
36}
37
38register_builtin! {
39 (bench, Bench) => bench_expand,
40 (cfg_accessible, CfgAccessible) => cfg_accessible_expand,
41 (cfg_eval, CfgEval) => cfg_eval_expand,
42 (derive, Derive) => derive_expand,
43 (global_allocator, GlobalAllocator) => global_allocator_expand,
44 (test, Test) => test_expand,
45 (test_case, TestCase) => test_case_expand
46}
47
48pub fn find_builtin_attr(
49 ident: &name::Name,
50 krate: CrateId,
51 ast_id: AstId<ast::Macro>,
52) -> Option<MacroDefId> {
53 let expander = BuiltinAttrExpander::find_by_name(ident)?;
54 Some(MacroDefId {
55 krate,
56 kind: MacroDefKind::BuiltInAttr(expander, ast_id),
57 local_inner: false,
58 })
59}
60
61fn bench_expand(
62 _db: &dyn AstDatabase,
63 _id: MacroCallId,
64 tt: &tt::Subtree,
65) -> Result<tt::Subtree, mbe::ExpandError> {
66 Ok(tt.clone())
67}
68
69fn cfg_accessible_expand(
70 _db: &dyn AstDatabase,
71 _id: MacroCallId,
72 tt: &tt::Subtree,
73) -> Result<tt::Subtree, mbe::ExpandError> {
74 Ok(tt.clone())
75}
76
77fn cfg_eval_expand(
78 _db: &dyn AstDatabase,
79 _id: MacroCallId,
80 tt: &tt::Subtree,
81) -> Result<tt::Subtree, mbe::ExpandError> {
82 Ok(tt.clone())
83}
84
85fn derive_expand(
86 _db: &dyn AstDatabase,
87 _id: MacroCallId,
88 tt: &tt::Subtree,
89) -> Result<tt::Subtree, mbe::ExpandError> {
90 Ok(tt.clone())
91}
92
93fn global_allocator_expand(
94 _db: &dyn AstDatabase,
95 _id: MacroCallId,
96 tt: &tt::Subtree,
97) -> Result<tt::Subtree, mbe::ExpandError> {
98 Ok(tt.clone())
99}
100
101fn test_expand(
102 _db: &dyn AstDatabase,
103 _id: MacroCallId,
104 tt: &tt::Subtree,
105) -> Result<tt::Subtree, mbe::ExpandError> {
106 Ok(tt.clone())
107}
108
109fn test_case_expand(
110 _db: &dyn AstDatabase,
111 _id: MacroCallId,
112 tt: &tt::Subtree,
113) -> Result<tt::Subtree, mbe::ExpandError> {
114 Ok(tt.clone())
115}
diff --git a/crates/hir_expand/src/db.rs b/crates/hir_expand/src/db.rs
index 18a05579f..45e6e446a 100644
--- a/crates/hir_expand/src/db.rs
+++ b/crates/hir_expand/src/db.rs
@@ -12,9 +12,9 @@ use syntax::{
12}; 12};
13 13
14use crate::{ 14use crate::{
15 ast_id_map::AstIdMap, hygiene::HygieneFrame, input::process_macro_input, BuiltinDeriveExpander, 15 ast_id_map::AstIdMap, hygiene::HygieneFrame, input::process_macro_input, BuiltinAttrExpander,
16 BuiltinFnLikeExpander, HirFileId, HirFileIdRepr, MacroCallId, MacroCallKind, MacroCallLoc, 16 BuiltinDeriveExpander, BuiltinFnLikeExpander, HirFileId, HirFileIdRepr, MacroCallId,
17 MacroDefId, MacroDefKind, MacroFile, ProcMacroExpander, 17 MacroCallKind, MacroCallLoc, MacroDefId, MacroDefKind, MacroFile, ProcMacroExpander,
18}; 18};
19 19
20/// Total limit on the number of tokens produced by any macro invocation. 20/// Total limit on the number of tokens produced by any macro invocation.
@@ -31,6 +31,8 @@ pub enum TokenExpander {
31 MacroDef { mac: mbe::MacroDef, def_site_token_map: mbe::TokenMap }, 31 MacroDef { mac: mbe::MacroDef, def_site_token_map: mbe::TokenMap },
32 /// Stuff like `line!` and `file!`. 32 /// Stuff like `line!` and `file!`.
33 Builtin(BuiltinFnLikeExpander), 33 Builtin(BuiltinFnLikeExpander),
34 /// `global_allocator` and such.
35 BuiltinAttr(BuiltinAttrExpander),
34 /// `derive(Copy)` and such. 36 /// `derive(Copy)` and such.
35 BuiltinDerive(BuiltinDeriveExpander), 37 BuiltinDerive(BuiltinDeriveExpander),
36 /// The thing we love the most here in rust-analyzer -- procedural macros. 38 /// The thing we love the most here in rust-analyzer -- procedural macros.
@@ -49,6 +51,7 @@ impl TokenExpander {
49 TokenExpander::MacroDef { mac, .. } => mac.expand(tt), 51 TokenExpander::MacroDef { mac, .. } => mac.expand(tt),
50 TokenExpander::Builtin(it) => it.expand(db, id, tt), 52 TokenExpander::Builtin(it) => it.expand(db, id, tt),
51 // FIXME switch these to ExpandResult as well 53 // FIXME switch these to ExpandResult as well
54 TokenExpander::BuiltinAttr(it) => it.expand(db, id, tt).into(),
52 TokenExpander::BuiltinDerive(it) => it.expand(db, id, tt).into(), 55 TokenExpander::BuiltinDerive(it) => it.expand(db, id, tt).into(),
53 TokenExpander::ProcMacro(_) => { 56 TokenExpander::ProcMacro(_) => {
54 // We store the result in salsa db to prevent non-deterministic behavior in 57 // We store the result in salsa db to prevent non-deterministic behavior in
@@ -64,6 +67,7 @@ impl TokenExpander {
64 TokenExpander::MacroRules { mac, .. } => mac.map_id_down(id), 67 TokenExpander::MacroRules { mac, .. } => mac.map_id_down(id),
65 TokenExpander::MacroDef { mac, .. } => mac.map_id_down(id), 68 TokenExpander::MacroDef { mac, .. } => mac.map_id_down(id),
66 TokenExpander::Builtin(..) 69 TokenExpander::Builtin(..)
70 | TokenExpander::BuiltinAttr(..)
67 | TokenExpander::BuiltinDerive(..) 71 | TokenExpander::BuiltinDerive(..)
68 | TokenExpander::ProcMacro(..) => id, 72 | TokenExpander::ProcMacro(..) => id,
69 } 73 }
@@ -74,6 +78,7 @@ impl TokenExpander {
74 TokenExpander::MacroRules { mac, .. } => mac.map_id_up(id), 78 TokenExpander::MacroRules { mac, .. } => mac.map_id_up(id),
75 TokenExpander::MacroDef { mac, .. } => mac.map_id_up(id), 79 TokenExpander::MacroDef { mac, .. } => mac.map_id_up(id),
76 TokenExpander::Builtin(..) 80 TokenExpander::Builtin(..)
81 | TokenExpander::BuiltinAttr(..)
77 | TokenExpander::BuiltinDerive(..) 82 | TokenExpander::BuiltinDerive(..)
78 | TokenExpander::ProcMacro(..) => (id, mbe::Origin::Call), 83 | TokenExpander::ProcMacro(..) => (id, mbe::Origin::Call),
79 } 84 }
@@ -299,6 +304,9 @@ fn macro_def(db: &dyn AstDatabase, id: MacroDefId) -> Option<Arc<TokenExpander>>
299 } 304 }
300 }, 305 },
301 MacroDefKind::BuiltIn(expander, _) => Some(Arc::new(TokenExpander::Builtin(expander))), 306 MacroDefKind::BuiltIn(expander, _) => Some(Arc::new(TokenExpander::Builtin(expander))),
307 MacroDefKind::BuiltInAttr(expander, _) => {
308 Some(Arc::new(TokenExpander::BuiltinAttr(expander)))
309 }
302 MacroDefKind::BuiltInDerive(expander, _) => { 310 MacroDefKind::BuiltInDerive(expander, _) => {
303 Some(Arc::new(TokenExpander::BuiltinDerive(expander))) 311 Some(Arc::new(TokenExpander::BuiltinDerive(expander)))
304 } 312 }
diff --git a/crates/hir_expand/src/eager.rs b/crates/hir_expand/src/eager.rs
index 14af628a1..9093255f4 100644
--- a/crates/hir_expand/src/eager.rs
+++ b/crates/hir_expand/src/eager.rs
@@ -224,6 +224,7 @@ fn eager_macro_recur(
224 } 224 }
225 MacroDefKind::Declarative(_) 225 MacroDefKind::Declarative(_)
226 | MacroDefKind::BuiltIn(..) 226 | MacroDefKind::BuiltIn(..)
227 | MacroDefKind::BuiltInAttr(..)
227 | MacroDefKind::BuiltInDerive(..) 228 | MacroDefKind::BuiltInDerive(..)
228 | MacroDefKind::ProcMacro(..) => { 229 | MacroDefKind::ProcMacro(..) => {
229 let res = lazy_expand(db, &def, curr.with_value(child.clone()), krate); 230 let res = lazy_expand(db, &def, curr.with_value(child.clone()), krate);
diff --git a/crates/hir_expand/src/hygiene.rs b/crates/hir_expand/src/hygiene.rs
index d98913907..05c6c3fb1 100644
--- a/crates/hir_expand/src/hygiene.rs
+++ b/crates/hir_expand/src/hygiene.rs
@@ -192,6 +192,7 @@ impl HygieneFrame {
192 (info, Some(loc.def.krate), loc.def.local_inner) 192 (info, Some(loc.def.krate), loc.def.local_inner)
193 } 193 }
194 MacroDefKind::BuiltIn(..) => (info, Some(loc.def.krate), false), 194 MacroDefKind::BuiltIn(..) => (info, Some(loc.def.krate), false),
195 MacroDefKind::BuiltInAttr(..) => (info, None, false),
195 MacroDefKind::BuiltInDerive(..) => (info, None, false), 196 MacroDefKind::BuiltInDerive(..) => (info, None, false),
196 MacroDefKind::BuiltInEager(..) => (info, None, false), 197 MacroDefKind::BuiltInEager(..) => (info, None, false),
197 MacroDefKind::ProcMacro(..) => (info, None, false), 198 MacroDefKind::ProcMacro(..) => (info, None, false),
diff --git a/crates/hir_expand/src/lib.rs b/crates/hir_expand/src/lib.rs
index 618f26b95..623791b58 100644
--- a/crates/hir_expand/src/lib.rs
+++ b/crates/hir_expand/src/lib.rs
@@ -8,6 +8,7 @@ pub mod db;
8pub mod ast_id_map; 8pub mod ast_id_map;
9pub mod name; 9pub mod name;
10pub mod hygiene; 10pub mod hygiene;
11pub mod builtin_attr;
11pub mod builtin_derive; 12pub mod builtin_derive;
12pub mod builtin_macro; 13pub mod builtin_macro;
13pub mod proc_macro; 14pub mod proc_macro;
@@ -32,6 +33,7 @@ use syntax::{
32}; 33};
33 34
34use crate::ast_id_map::FileAstId; 35use crate::ast_id_map::FileAstId;
36use crate::builtin_attr::BuiltinAttrExpander;
35use crate::builtin_derive::BuiltinDeriveExpander; 37use crate::builtin_derive::BuiltinDeriveExpander;
36use crate::builtin_macro::{BuiltinFnLikeExpander, EagerExpander}; 38use crate::builtin_macro::{BuiltinFnLikeExpander, EagerExpander};
37use crate::proc_macro::ProcMacroExpander; 39use crate::proc_macro::ProcMacroExpander;
@@ -206,6 +208,7 @@ impl MacroDefId {
206 let id = match &self.kind { 208 let id = match &self.kind {
207 MacroDefKind::Declarative(id) => id, 209 MacroDefKind::Declarative(id) => id,
208 MacroDefKind::BuiltIn(_, id) => id, 210 MacroDefKind::BuiltIn(_, id) => id,
211 MacroDefKind::BuiltInAttr(_, id) => id,
209 MacroDefKind::BuiltInDerive(_, id) => id, 212 MacroDefKind::BuiltInDerive(_, id) => id,
210 MacroDefKind::BuiltInEager(_, id) => id, 213 MacroDefKind::BuiltInEager(_, id) => id,
211 MacroDefKind::ProcMacro(.., id) => return Either::Right(*id), 214 MacroDefKind::ProcMacro(.., id) => return Either::Right(*id),
@@ -223,6 +226,7 @@ pub enum MacroDefKind {
223 Declarative(AstId<ast::Macro>), 226 Declarative(AstId<ast::Macro>),
224 BuiltIn(BuiltinFnLikeExpander, AstId<ast::Macro>), 227 BuiltIn(BuiltinFnLikeExpander, AstId<ast::Macro>),
225 // FIXME: maybe just Builtin and rename BuiltinFnLikeExpander to BuiltinExpander 228 // FIXME: maybe just Builtin and rename BuiltinFnLikeExpander to BuiltinExpander
229 BuiltInAttr(BuiltinAttrExpander, AstId<ast::Macro>),
226 BuiltInDerive(BuiltinDeriveExpander, AstId<ast::Macro>), 230 BuiltInDerive(BuiltinDeriveExpander, AstId<ast::Macro>),
227 BuiltInEager(EagerExpander, AstId<ast::Macro>), 231 BuiltInEager(EagerExpander, AstId<ast::Macro>),
228 ProcMacro(ProcMacroExpander, ProcMacroKind, AstId<ast::Fn>), 232 ProcMacro(ProcMacroExpander, ProcMacroKind, AstId<ast::Fn>),
diff --git a/crates/hir_expand/src/name.rs b/crates/hir_expand/src/name.rs
index 00b8adc1e..376fe130f 100644
--- a/crates/hir_expand/src/name.rs
+++ b/crates/hir_expand/src/name.rs
@@ -160,7 +160,6 @@ pub mod known {
160 str, 160 str,
161 // Special names 161 // Special names
162 macro_rules, 162 macro_rules,
163 derive,
164 doc, 163 doc,
165 cfg, 164 cfg,
166 cfg_attr, 165 cfg_attr,
@@ -240,6 +239,14 @@ pub mod known {
240 PartialOrd, 239 PartialOrd,
241 Eq, 240 Eq,
242 PartialEq, 241 PartialEq,
242 // Builtin attributes
243 bench,
244 cfg_accessible,
245 cfg_eval,
246 derive,
247 global_allocator,
248 test,
249 test_case,
243 // Safe intrinsics 250 // Safe intrinsics
244 abort, 251 abort,
245 size_of, 252 size_of,
diff --git a/crates/ide_completion/src/completions/qualified_path.rs b/crates/ide_completion/src/completions/qualified_path.rs
index 0b0a81410..58d4dd9ee 100644
--- a/crates/ide_completion/src/completions/qualified_path.rs
+++ b/crates/ide_completion/src/completions/qualified_path.rs
@@ -657,6 +657,32 @@ fn main() { let _ = crate::$0 }
657 } 657 }
658 658
659 #[test] 659 #[test]
660 fn does_not_complete_non_fn_macros() {
661 check(
662 r#"
663mod m {
664 #[rustc_builtin_macro]
665 pub macro Clone {}
666}
667
668fn f() {m::$0}
669"#,
670 expect![[r#""#]],
671 );
672 check(
673 r#"
674mod m {
675 #[rustc_builtin_macro]
676 pub macro bench {}
677}
678
679fn f() {m::$0}
680"#,
681 expect![[r#""#]],
682 );
683 }
684
685 #[test]
660 fn completes_in_assoc_item_list() { 686 fn completes_in_assoc_item_list() {
661 check( 687 check(
662 r#" 688 r#"
diff --git a/crates/ide_completion/src/completions/unqualified_path.rs b/crates/ide_completion/src/completions/unqualified_path.rs
index 1f6c4069f..b1e6b2b77 100644
--- a/crates/ide_completion/src/completions/unqualified_path.rs
+++ b/crates/ide_completion/src/completions/unqualified_path.rs
@@ -481,14 +481,14 @@ impl S {
481 ); 481 );
482 check( 482 check(
483 r#" 483 r#"
484mod m { 484#[rustc_builtin_macro]
485 #[rustc_builtin_macro] 485pub macro bench {}
486 pub macro Clone {}
487}
488 486
489fn f() {m::$0} 487fn f() {$0}
490"#, 488"#,
491 expect![[r#""#]], 489 expect![[r#"
490 fn f() fn()
491 "#]],
492 ); 492 );
493 } 493 }
494 494