Skip to content

Commit fe1469e

Browse files
committed
Basic support for declarative attribute/derive macros
1 parent ac46f23 commit fe1469e

File tree

22 files changed

+372
-110
lines changed

22 files changed

+372
-110
lines changed

Cargo.lock

Lines changed: 1 addition & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

crates/hir-def/src/db.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -338,7 +338,7 @@ fn macro_def(db: &dyn DefDatabase, id: MacroId) -> MacroDefId {
338338
let kind = |expander, file_id, m| {
339339
let in_file = InFile::new(file_id, m);
340340
match expander {
341-
MacroExpander::Declarative => MacroDefKind::Declarative(in_file),
341+
MacroExpander::Declarative { styles } => MacroDefKind::Declarative(in_file, styles),
342342
MacroExpander::BuiltIn(it) => MacroDefKind::BuiltIn(in_file, it),
343343
MacroExpander::BuiltInAttr(it) => MacroDefKind::BuiltInAttr(in_file, it),
344344
MacroExpander::BuiltInDerive(it) => MacroDefKind::BuiltInDerive(in_file, it),

crates/hir-def/src/item_scope.rs

Lines changed: 10 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -17,9 +17,8 @@ use thin_vec::ThinVec;
1717

1818
use crate::{
1919
AdtId, BuiltinType, ConstId, ExternBlockId, ExternCrateId, FxIndexMap, HasModule, ImplId,
20-
LocalModuleId, Lookup, MacroId, ModuleDefId, ModuleId, TraitId, UseId,
20+
LocalModuleId, Lookup, MacroCallStyles, MacroId, ModuleDefId, ModuleId, TraitId, UseId,
2121
db::DefDatabase,
22-
nameres::MacroSubNs,
2322
per_ns::{Item, MacrosItem, PerNs, TypesItem, ValuesItem},
2423
visibility::Visibility,
2524
};
@@ -740,11 +739,15 @@ impl ItemScope {
740739
let mut entries: Vec<_> = self.resolutions().collect();
741740
entries.sort_by_key(|(name, _)| name.clone());
742741

743-
let print_macro_sub_ns =
744-
|buf: &mut String, macro_id: MacroId| match MacroSubNs::from_id(db, macro_id) {
745-
MacroSubNs::Bang => buf.push('!'),
746-
MacroSubNs::Attr => buf.push('#'),
747-
};
742+
let print_macro_sub_ns = |buf: &mut String, macro_id: MacroId| {
743+
let styles = crate::nameres::macro_styles_from_id(db, macro_id);
744+
if styles.contains(MacroCallStyles::FN_LIKE) {
745+
buf.push('!');
746+
}
747+
if styles.contains(MacroCallStyles::ATTR) || styles.contains(MacroCallStyles::DERIVE) {
748+
buf.push('#');
749+
}
750+
};
748751

749752
for (name, def) in entries {
750753
let display_name: &dyn fmt::Display = match &name {

crates/hir-def/src/lib.rs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -61,8 +61,8 @@ use std::hash::{Hash, Hasher};
6161

6262
use base_db::{Crate, impl_intern_key};
6363
use hir_expand::{
64-
AstId, ExpandResult, ExpandTo, HirFileId, InFile, MacroCallId, MacroCallKind, MacroDefId,
65-
MacroDefKind,
64+
AstId, ExpandResult, ExpandTo, HirFileId, InFile, MacroCallId, MacroCallKind, MacroCallStyles,
65+
MacroDefId, MacroDefKind,
6666
builtin::{BuiltinAttrExpander, BuiltinDeriveExpander, BuiltinFnLikeExpander, EagerExpander},
6767
db::ExpandDatabase,
6868
eager::expand_eager_macro_input,
@@ -403,7 +403,7 @@ bitflags::bitflags! {
403403

404404
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
405405
pub enum MacroExpander {
406-
Declarative,
406+
Declarative { styles: MacroCallStyles },
407407
BuiltIn(BuiltinFnLikeExpander),
408408
BuiltInAttr(BuiltinAttrExpander),
409409
BuiltInDerive(BuiltinDeriveExpander),

crates/hir-def/src/nameres.rs

Lines changed: 25 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -77,7 +77,7 @@ use tt::TextRange;
7777

7878
use crate::{
7979
AstId, BlockId, BlockLoc, CrateRootModuleId, ExternCrateId, FunctionId, FxIndexMap,
80-
LocalModuleId, Lookup, MacroExpander, MacroId, ModuleId, ProcMacroId, UseId,
80+
LocalModuleId, Lookup, MacroCallStyles, MacroExpander, MacroId, ModuleId, ProcMacroId, UseId,
8181
db::DefDatabase,
8282
item_scope::{BuiltinShadowMode, ItemScope},
8383
item_tree::TreeId,
@@ -813,26 +813,25 @@ pub enum MacroSubNs {
813813
Attr,
814814
}
815815

816-
impl MacroSubNs {
817-
pub(crate) fn from_id(db: &dyn DefDatabase, macro_id: MacroId) -> Self {
818-
let expander = match macro_id {
819-
MacroId::Macro2Id(it) => it.lookup(db).expander,
820-
MacroId::MacroRulesId(it) => it.lookup(db).expander,
821-
MacroId::ProcMacroId(it) => {
822-
return match it.lookup(db).kind {
823-
ProcMacroKind::CustomDerive | ProcMacroKind::Attr => Self::Attr,
824-
ProcMacroKind::Bang => Self::Bang,
825-
};
826-
}
827-
};
816+
pub(crate) fn macro_styles_from_id(db: &dyn DefDatabase, macro_id: MacroId) -> MacroCallStyles {
817+
let expander = match macro_id {
818+
MacroId::Macro2Id(it) => it.lookup(db).expander,
819+
MacroId::MacroRulesId(it) => it.lookup(db).expander,
820+
MacroId::ProcMacroId(it) => {
821+
return match it.lookup(db).kind {
822+
ProcMacroKind::CustomDerive => MacroCallStyles::DERIVE,
823+
ProcMacroKind::Bang => MacroCallStyles::FN_LIKE,
824+
ProcMacroKind::Attr => MacroCallStyles::ATTR,
825+
};
826+
}
827+
};
828828

829+
match expander {
830+
MacroExpander::Declarative { styles } => styles,
829831
// Eager macros aren't *guaranteed* to be bang macros, but they *are* all bang macros currently.
830-
match expander {
831-
MacroExpander::Declarative
832-
| MacroExpander::BuiltIn(_)
833-
| MacroExpander::BuiltInEager(_) => Self::Bang,
834-
MacroExpander::BuiltInAttr(_) | MacroExpander::BuiltInDerive(_) => Self::Attr,
835-
}
832+
MacroExpander::BuiltIn(_) | MacroExpander::BuiltInEager(_) => MacroCallStyles::FN_LIKE,
833+
MacroExpander::BuiltInAttr(_) => MacroCallStyles::ATTR,
834+
MacroExpander::BuiltInDerive(_) => MacroCallStyles::DERIVE,
836835
}
837836
}
838837

@@ -847,9 +846,14 @@ fn sub_namespace_match(
847846
macro_id: MacroId,
848847
expected: Option<MacroSubNs>,
849848
) -> bool {
850-
let candidate = MacroSubNs::from_id(db, macro_id);
849+
let candidate = macro_styles_from_id(db, macro_id);
851850
match expected {
852-
Some(expected) => candidate == expected,
851+
Some(MacroSubNs::Bang) => candidate.contains(MacroCallStyles::FN_LIKE),
852+
Some(MacroSubNs::Attr) => {
853+
candidate.contains(MacroCallStyles::ATTR) || candidate.contains(MacroCallStyles::DERIVE)
854+
}
855+
// If we aren't expecting a specific sub-namespace
856+
// (e.g. in `use` declarations), match any macro.
853857
None => true,
854858
}
855859
}

crates/hir-def/src/nameres/collector.rs

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2300,7 +2300,10 @@ impl ModCollector<'_, '_> {
23002300
}
23012301
} else {
23022302
// Case 2: normal `macro_rules!` macro
2303-
MacroExpander::Declarative
2303+
let id = InFile::new(self.file_id(), ast_id);
2304+
let decl_expander = self.def_collector.db.decl_macro_expander(krate, id.upcast());
2305+
let styles = decl_expander.mac.rule_styles();
2306+
MacroExpander::Declarative { styles }
23042307
};
23052308
let allow_internal_unsafe = attrs.by_key(sym::allow_internal_unsafe).exists();
23062309

@@ -2369,7 +2372,10 @@ impl ModCollector<'_, '_> {
23692372
}
23702373
} else {
23712374
// Case 2: normal `macro`
2372-
MacroExpander::Declarative
2375+
let id = InFile::new(self.file_id(), ast_id);
2376+
let decl_expander = self.def_collector.db.decl_macro_expander(krate, id.upcast());
2377+
let styles = decl_expander.mac.rule_styles();
2378+
MacroExpander::Declarative { styles }
23732379
};
23742380
let allow_internal_unsafe = attrs.by_key(sym::allow_internal_unsafe).exists();
23752381

crates/hir-def/src/nameres/tests/incremental.rs

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -222,6 +222,7 @@ pub struct S {}
222222
"ast_id_map_shim",
223223
"parse_shim",
224224
"real_span_map_shim",
225+
"decl_macro_expander_shim",
225226
"file_item_tree_query",
226227
"ast_id_map_shim",
227228
"parse_shim",
@@ -235,7 +236,6 @@ pub struct S {}
235236
"ast_id_map_shim",
236237
"parse_macro_expansion_shim",
237238
"macro_arg_shim",
238-
"decl_macro_expander_shim",
239239
]
240240
"#]],
241241
expect![[r#"
@@ -404,6 +404,7 @@ pub struct S {}
404404
"ast_id_map_shim",
405405
"parse_shim",
406406
"real_span_map_shim",
407+
"decl_macro_expander_shim",
407408
"file_item_tree_query",
408409
"ast_id_map_shim",
409410
"parse_shim",
@@ -423,7 +424,6 @@ pub struct S {}
423424
"ast_id_map_shim",
424425
"parse_macro_expansion_shim",
425426
"macro_arg_shim",
426-
"decl_macro_expander_shim",
427427
"crate_local_def_map",
428428
"proc_macros_for_crate_shim",
429429
"file_item_tree_query",
@@ -446,9 +446,9 @@ pub struct S {}
446446
"file_item_tree_query",
447447
"real_span_map_shim",
448448
"macro_arg_shim",
449-
"macro_arg_shim",
450449
"decl_macro_expander_shim",
451450
"macro_arg_shim",
451+
"macro_arg_shim",
452452
]
453453
"#]],
454454
);
@@ -520,6 +520,7 @@ m!(Z);
520520
"ast_id_map_shim",
521521
"parse_shim",
522522
"real_span_map_shim",
523+
"decl_macro_expander_shim",
523524
"file_item_tree_query",
524525
"ast_id_map_shim",
525526
"parse_shim",
@@ -533,7 +534,6 @@ m!(Z);
533534
"ast_id_map_shim",
534535
"parse_macro_expansion_shim",
535536
"macro_arg_shim",
536-
"decl_macro_expander_shim",
537537
"file_item_tree_query",
538538
"ast_id_map_shim",
539539
"parse_macro_expansion_shim",

crates/hir-def/src/nameres/tests/macros.rs

Lines changed: 129 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1651,3 +1651,132 @@ pub mod prelude {
16511651
"#]],
16521652
);
16531653
}
1654+
1655+
#[test]
1656+
fn macro_rules_mixed_style() {
1657+
check(
1658+
r#"
1659+
1660+
macro_rules! foo {
1661+
() => {};
1662+
attr() () => {};
1663+
derive() () => {};
1664+
}
1665+
1666+
use foo;
1667+
"#,
1668+
expect![[r#"
1669+
crate
1670+
- foo : macro!# (import)
1671+
- (legacy) foo : macro!#
1672+
"#]],
1673+
);
1674+
}
1675+
1676+
#[test]
1677+
fn macro_2_mixed_style() {
1678+
check(
1679+
r#"
1680+
1681+
macro foo {
1682+
() => {};
1683+
attr() () => {};
1684+
derive() () => {};
1685+
}
1686+
1687+
use foo;
1688+
"#,
1689+
expect![[r#"
1690+
crate
1691+
- foo : macro!#
1692+
"#]],
1693+
);
1694+
}
1695+
1696+
#[test]
1697+
fn macro_rules_attr() {
1698+
check(
1699+
r#"
1700+
1701+
macro_rules! my_attr {
1702+
attr() ($($tt:tt)*) => { fn attr_fn() {} }
1703+
}
1704+
1705+
#[my_attr]
1706+
enum MyEnum {}
1707+
1708+
"#,
1709+
expect![[r#"
1710+
crate
1711+
- attr_fn : value
1712+
- (legacy) my_attr : macro#
1713+
"#]],
1714+
);
1715+
}
1716+
1717+
#[test]
1718+
fn macro_2_attr() {
1719+
check(
1720+
r#"
1721+
1722+
macro my_attr {
1723+
attr() ($($tt:tt)*) => { fn attr_fn() {} }
1724+
}
1725+
1726+
#[my_attr]
1727+
enum MyEnum {}
1728+
1729+
"#,
1730+
expect![[r#"
1731+
crate
1732+
- attr_fn : value
1733+
- my_attr : macro#
1734+
"#]],
1735+
);
1736+
}
1737+
1738+
#[test]
1739+
fn macro_rules_derive() {
1740+
check(
1741+
r#"
1742+
//- minicore: derive
1743+
1744+
macro_rules! MyDerive {
1745+
derive() ($($tt:tt)*) => { fn derived_fn() {} }
1746+
}
1747+
1748+
#[derive(MyDerive)]
1749+
enum MyEnum {}
1750+
1751+
"#,
1752+
expect![[r#"
1753+
crate
1754+
- MyEnum : type
1755+
- derived_fn : value
1756+
- (legacy) MyDerive : macro#
1757+
"#]],
1758+
);
1759+
}
1760+
1761+
#[test]
1762+
fn macro_2_derive() {
1763+
check(
1764+
r#"
1765+
//- minicore: derive
1766+
1767+
macro MyDerive {
1768+
derive() ($($tt:tt)*) => { fn derived_fn() {} }
1769+
}
1770+
1771+
#[derive(MyDerive)]
1772+
enum MyEnum {}
1773+
1774+
"#,
1775+
expect![[r#"
1776+
crate
1777+
- MyDerive : macro#
1778+
- MyEnum : type
1779+
- derived_fn : value
1780+
"#]],
1781+
);
1782+
}

0 commit comments

Comments
 (0)