Skip to content

Commit 8d667bb

Browse files
Merge #3692
3692: Introduce `MacroDefKind::CustomDerive` r=matklad a=edwin0cheng This PR introduce a new `MacroDefKind` `CustomDerive`. And use a new `ProcMacroExpander` for its expanding. And the expander is a dummy for now. Related: #3654 Co-authored-by: Edwin Cheng <edwin0cheng@gmail.com>
2 parents e2dd17f + 2adc9a8 commit 8d667bb

File tree

10 files changed

+144
-28
lines changed

10 files changed

+144
-28
lines changed

crates/ra_hir_def/src/lib.rs

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -475,6 +475,12 @@ impl AsMacroCall for AstIdWithPath<ast::ModuleItem> {
475475
resolver: impl Fn(path::ModPath) -> Option<MacroDefId>,
476476
) -> Option<MacroCallId> {
477477
let def = resolver(self.path.clone())?;
478-
Some(def.as_lazy_macro(db.upcast(), MacroCallKind::Attr(self.ast_id)).into())
478+
Some(
479+
def.as_lazy_macro(
480+
db.upcast(),
481+
MacroCallKind::Attr(self.ast_id, self.path.segments.last()?.to_string()),
482+
)
483+
.into(),
484+
)
479485
}
480486
}

crates/ra_hir_def/src/nameres/collector.rs

Lines changed: 53 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ use hir_expand::{
77
builtin_derive::find_builtin_derive,
88
builtin_macro::find_builtin_macro,
99
name::{name, AsName, Name},
10+
proc_macro::ProcMacroExpander,
1011
HirFileId, MacroCallId, MacroDefId, MacroDefKind,
1112
};
1213
use ra_cfg::CfgOptions;
@@ -64,6 +65,9 @@ pub(super) fn collect_defs(db: &dyn DefDatabase, mut def_map: CrateDefMap) -> Cr
6465
unexpanded_attribute_macros: Vec::new(),
6566
mod_dirs: FxHashMap::default(),
6667
cfg_options,
68+
69+
// FIXME: pass proc-macro from crate-graph
70+
proc_macros: Default::default(),
6771
};
6872
collector.collect();
6973
collector.finish()
@@ -122,6 +126,7 @@ struct DefCollector<'a> {
122126
unexpanded_attribute_macros: Vec<DeriveDirective>,
123127
mod_dirs: FxHashMap<LocalModuleId, ModDir>,
124128
cfg_options: &'a CfgOptions,
129+
proc_macros: Vec<(Name, ProcMacroExpander)>,
125130
}
126131

127132
impl DefCollector<'_> {
@@ -177,6 +182,24 @@ impl DefCollector<'_> {
177182
for directive in unresolved_imports {
178183
self.record_resolved_import(&directive)
179184
}
185+
186+
// Record proc-macros
187+
self.collect_proc_macro();
188+
}
189+
190+
fn collect_proc_macro(&mut self) {
191+
let proc_macros = std::mem::take(&mut self.proc_macros);
192+
for (name, expander) in proc_macros {
193+
let krate = self.def_map.krate;
194+
195+
let macro_id = MacroDefId {
196+
ast_id: None,
197+
krate: Some(krate),
198+
kind: MacroDefKind::CustomDerive(expander),
199+
};
200+
201+
self.define_proc_macro(name.clone(), macro_id);
202+
}
180203
}
181204

182205
/// Define a macro with `macro_rules`.
@@ -238,6 +261,18 @@ impl DefCollector<'_> {
238261
self.def_map.modules[module_id].scope.define_legacy_macro(name, mac);
239262
}
240263

264+
/// Define a proc macro
265+
///
266+
/// A proc macro is similar to normal macro scope, but it would not visiable in legacy textual scoped.
267+
/// And unconditionally exported.
268+
fn define_proc_macro(&mut self, name: Name, macro_: MacroDefId) {
269+
self.update(
270+
self.def_map.root,
271+
&[(name, PerNs::macros(macro_, Visibility::Public))],
272+
Visibility::Public,
273+
);
274+
}
275+
241276
/// Import macros from `#[macro_use] extern crate`.
242277
fn import_macros_from_extern_crate(
243278
&mut self,
@@ -537,8 +572,9 @@ impl DefCollector<'_> {
537572
true
538573
});
539574
attribute_macros.retain(|directive| {
540-
if let Some(call_id) =
541-
directive.ast_id.as_call_id(self.db, |path| self.resolve_attribute_macro(&path))
575+
if let Some(call_id) = directive
576+
.ast_id
577+
.as_call_id(self.db, |path| self.resolve_attribute_macro(&directive, &path))
542578
{
543579
resolved.push((directive.module_id, call_id, 0));
544580
res = ReachedFixedPoint::No;
@@ -562,9 +598,11 @@ impl DefCollector<'_> {
562598
res
563599
}
564600

565-
fn resolve_attribute_macro(&self, path: &ModPath) -> Option<MacroDefId> {
566-
// FIXME this is currently super hacky, just enough to support the
567-
// built-in derives
601+
fn resolve_attribute_macro(
602+
&self,
603+
directive: &DeriveDirective,
604+
path: &ModPath,
605+
) -> Option<MacroDefId> {
568606
if let Some(name) = path.as_ident() {
569607
// FIXME this should actually be handled with the normal name
570608
// resolution; the std lib defines built-in stubs for the derives,
@@ -573,7 +611,15 @@ impl DefCollector<'_> {
573611
return Some(def_id);
574612
}
575613
}
576-
None
614+
let resolved_res = self.def_map.resolve_path_fp_with_macro(
615+
self.db,
616+
ResolveMode::Other,
617+
directive.module_id,
618+
&path,
619+
BuiltinShadowMode::Module,
620+
);
621+
622+
resolved_res.resolved_def.take_macros()
577623
}
578624

579625
fn collect_macro_expansion(
@@ -776,7 +822,6 @@ impl ModCollector<'_, '_> {
776822
// FIXME: check attrs to see if this is an attribute macro invocation;
777823
// in which case we don't add the invocation, just a single attribute
778824
// macro invocation
779-
780825
self.collect_derives(attrs, def);
781826

782827
let name = def.name.clone();
@@ -955,6 +1000,7 @@ mod tests {
9551000
unexpanded_attribute_macros: Vec::new(),
9561001
mod_dirs: FxHashMap::default(),
9571002
cfg_options: &CfgOptions::default(),
1003+
proc_macros: Default::default(),
9581004
};
9591005
collector.collect();
9601006
collector.def_map

crates/ra_hir_expand/src/builtin_derive.rs

Lines changed: 10 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -229,24 +229,22 @@ fn partial_ord_expand(
229229
mod tests {
230230
use super::*;
231231
use crate::{test_db::TestDB, AstId, MacroCallId, MacroCallKind, MacroCallLoc};
232+
use name::{known, Name};
232233
use ra_db::{fixture::WithFixture, SourceDatabase};
233234

234-
fn expand_builtin_derive(s: &str, expander: BuiltinDeriveExpander) -> String {
235+
fn expand_builtin_derive(s: &str, name: Name) -> String {
236+
let def = find_builtin_derive(&name).unwrap();
237+
235238
let (db, file_id) = TestDB::with_single_file(&s);
236239
let parsed = db.parse(file_id);
237240
let items: Vec<_> =
238241
parsed.syntax_node().descendants().filter_map(ast::ModuleItem::cast).collect();
239242

240243
let ast_id_map = db.ast_id_map(file_id.into());
241244

242-
// the first one should be a macro_rules
243-
let def =
244-
MacroDefId { krate: None, ast_id: None, kind: MacroDefKind::BuiltInDerive(expander) };
245+
let attr_id = AstId::new(file_id.into(), ast_id_map.ast_id(&items[0]));
245246

246-
let loc = MacroCallLoc {
247-
def,
248-
kind: MacroCallKind::Attr(AstId::new(file_id.into(), ast_id_map.ast_id(&items[0]))),
249-
};
247+
let loc = MacroCallLoc { def, kind: MacroCallKind::Attr(attr_id, name.to_string()) };
250248

251249
let id: MacroCallId = db.intern_macro(loc).into();
252250
let parsed = db.parse_or_expand(id.as_file()).unwrap();
@@ -263,7 +261,7 @@ mod tests {
263261
#[derive(Copy)]
264262
struct Foo;
265263
"#,
266-
BuiltinDeriveExpander::Copy,
264+
known::Copy,
267265
);
268266

269267
assert_eq!(expanded, "impl< >std::marker::CopyforFoo< >{}");
@@ -276,7 +274,7 @@ mod tests {
276274
#[derive(Copy)]
277275
struct Foo<A, B>;
278276
"#,
279-
BuiltinDeriveExpander::Copy,
277+
known::Copy,
280278
);
281279

282280
assert_eq!(
@@ -292,7 +290,7 @@ mod tests {
292290
#[derive(Copy)]
293291
struct Foo<A, B, 'a, 'b>;
294292
"#,
295-
BuiltinDeriveExpander::Copy,
293+
known::Copy,
296294
);
297295

298296
// We currently just ignore lifetimes
@@ -310,7 +308,7 @@ mod tests {
310308
#[derive(Clone)]
311309
struct Foo<A, B>;
312310
"#,
313-
BuiltinDeriveExpander::Clone,
311+
known::Clone,
314312
);
315313

316314
assert_eq!(

crates/ra_hir_expand/src/db.rs

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -11,14 +11,15 @@ use ra_syntax::{algo::diff, AstNode, Parse, SyntaxKind::*, SyntaxNode};
1111
use crate::{
1212
ast_id_map::AstIdMap, BuiltinDeriveExpander, BuiltinFnLikeExpander, EagerCallLoc, EagerMacroId,
1313
HirFileId, HirFileIdRepr, LazyMacroId, MacroCallId, MacroCallLoc, MacroDefId, MacroDefKind,
14-
MacroFile,
14+
MacroFile, ProcMacroExpander,
1515
};
1616

1717
#[derive(Debug, Clone, Eq, PartialEq)]
1818
pub enum TokenExpander {
1919
MacroRules(mbe::MacroRules),
2020
Builtin(BuiltinFnLikeExpander),
2121
BuiltinDerive(BuiltinDeriveExpander),
22+
ProcMacro(ProcMacroExpander),
2223
}
2324

2425
impl TokenExpander {
@@ -33,6 +34,7 @@ impl TokenExpander {
3334
// FIXME switch these to ExpandResult as well
3435
TokenExpander::Builtin(it) => it.expand(db, id, tt).into(),
3536
TokenExpander::BuiltinDerive(it) => it.expand(db, id, tt).into(),
37+
TokenExpander::ProcMacro(it) => it.expand(db, id, tt).into(),
3638
}
3739
}
3840

@@ -41,6 +43,7 @@ impl TokenExpander {
4143
TokenExpander::MacroRules(it) => it.map_id_down(id),
4244
TokenExpander::Builtin(..) => id,
4345
TokenExpander::BuiltinDerive(..) => id,
46+
TokenExpander::ProcMacro(..) => id,
4447
}
4548
}
4649

@@ -49,6 +52,7 @@ impl TokenExpander {
4952
TokenExpander::MacroRules(it) => it.map_id_up(id),
5053
TokenExpander::Builtin(..) => (id, mbe::Origin::Call),
5154
TokenExpander::BuiltinDerive(..) => (id, mbe::Origin::Call),
55+
TokenExpander::ProcMacro(..) => (id, mbe::Origin::Call),
5256
}
5357
}
5458
}
@@ -130,7 +134,10 @@ pub(crate) fn macro_def(
130134
MacroDefKind::BuiltInDerive(expander) => {
131135
Some(Arc::new((TokenExpander::BuiltinDerive(expander), mbe::TokenMap::default())))
132136
}
133-
MacroDefKind::BuiltInEager(_expander) => None,
137+
MacroDefKind::BuiltInEager(_) => None,
138+
MacroDefKind::CustomDerive(expander) => {
139+
Some(Arc::new((TokenExpander::ProcMacro(expander), mbe::TokenMap::default())))
140+
}
134141
}
135142
}
136143

crates/ra_hir_expand/src/eager.rs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -112,7 +112,8 @@ fn eager_macro_recur(
112112
}
113113
MacroDefKind::Declarative
114114
| MacroDefKind::BuiltIn(_)
115-
| MacroDefKind::BuiltInDerive(_) => {
115+
| MacroDefKind::BuiltInDerive(_)
116+
| MacroDefKind::CustomDerive(_) => {
116117
let expanded = lazy_expand(db, &def, curr.with_value(child.clone()))?;
117118
// replace macro inside
118119
eager_macro_recur(db, expanded, macro_resolver)?

crates/ra_hir_expand/src/hygiene.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,7 @@ impl Hygiene {
3030
MacroDefKind::BuiltIn(_) => None,
3131
MacroDefKind::BuiltInDerive(_) => None,
3232
MacroDefKind::BuiltInEager(_) => None,
33+
MacroDefKind::CustomDerive(_) => None,
3334
}
3435
}
3536
MacroCallId::EagerMacro(_id) => None,

crates/ra_hir_expand/src/lib.rs

Lines changed: 9 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ pub mod hygiene;
1111
pub mod diagnostics;
1212
pub mod builtin_derive;
1313
pub mod builtin_macro;
14+
pub mod proc_macro;
1415
pub mod quote;
1516
pub mod eager;
1617

@@ -27,6 +28,7 @@ use ra_syntax::{
2728
use crate::ast_id_map::FileAstId;
2829
use crate::builtin_derive::BuiltinDeriveExpander;
2930
use crate::builtin_macro::{BuiltinFnLikeExpander, EagerExpander};
31+
use crate::proc_macro::ProcMacroExpander;
3032

3133
#[cfg(test)]
3234
mod test_db;
@@ -217,6 +219,7 @@ pub enum MacroDefKind {
217219
// FIXME: maybe just Builtin and rename BuiltinFnLikeExpander to BuiltinExpander
218220
BuiltInDerive(BuiltinDeriveExpander),
219221
BuiltInEager(EagerExpander),
222+
CustomDerive(ProcMacroExpander),
220223
}
221224

222225
#[derive(Debug, Clone, PartialEq, Eq, Hash)]
@@ -228,21 +231,23 @@ pub struct MacroCallLoc {
228231
#[derive(Debug, Clone, PartialEq, Eq, Hash)]
229232
pub enum MacroCallKind {
230233
FnLike(AstId<ast::MacroCall>),
231-
Attr(AstId<ast::ModuleItem>),
234+
Attr(AstId<ast::ModuleItem>, String),
232235
}
233236

234237
impl MacroCallKind {
235238
pub fn file_id(&self) -> HirFileId {
236239
match self {
237240
MacroCallKind::FnLike(ast_id) => ast_id.file_id,
238-
MacroCallKind::Attr(ast_id) => ast_id.file_id,
241+
MacroCallKind::Attr(ast_id, _) => ast_id.file_id,
239242
}
240243
}
241244

242245
pub fn node(&self, db: &dyn db::AstDatabase) -> InFile<SyntaxNode> {
243246
match self {
244247
MacroCallKind::FnLike(ast_id) => ast_id.with_value(ast_id.to_node(db).syntax().clone()),
245-
MacroCallKind::Attr(ast_id) => ast_id.with_value(ast_id.to_node(db).syntax().clone()),
248+
MacroCallKind::Attr(ast_id, _) => {
249+
ast_id.with_value(ast_id.to_node(db).syntax().clone())
250+
}
246251
}
247252
}
248253

@@ -251,7 +256,7 @@ impl MacroCallKind {
251256
MacroCallKind::FnLike(ast_id) => {
252257
Some(ast_id.to_node(db).token_tree()?.syntax().clone())
253258
}
254-
MacroCallKind::Attr(ast_id) => Some(ast_id.to_node(db).syntax().clone()),
259+
MacroCallKind::Attr(ast_id, _) => Some(ast_id.to_node(db).syntax().clone()),
255260
}
256261
}
257262
}
Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
//! Proc Macro Expander stub
2+
3+
use crate::{db::AstDatabase, LazyMacroId, MacroCallKind, MacroCallLoc};
4+
use ra_db::CrateId;
5+
6+
#[derive(Debug, Clone, Copy, Eq, PartialEq, Hash)]
7+
pub struct ProcMacroExpander {
8+
krate: CrateId,
9+
}
10+
11+
impl ProcMacroExpander {
12+
pub fn new(krate: CrateId) -> ProcMacroExpander {
13+
ProcMacroExpander { krate }
14+
}
15+
16+
pub fn expand(
17+
&self,
18+
db: &dyn AstDatabase,
19+
id: LazyMacroId,
20+
_tt: &tt::Subtree,
21+
) -> Result<tt::Subtree, mbe::ExpandError> {
22+
let loc: MacroCallLoc = db.lookup_intern_macro(id);
23+
let name = match loc.kind {
24+
MacroCallKind::FnLike(_) => return Err(mbe::ExpandError::ConversionError),
25+
MacroCallKind::Attr(_, name) => name,
26+
};
27+
28+
log::debug!("Proc-macro-expanding name = {}", name);
29+
30+
// Return nothing for now
31+
return Ok(tt::Subtree::default());
32+
}
33+
}

crates/ra_hir_ty/src/tests/macros.rs

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -639,3 +639,22 @@ mod clone {
639639
);
640640
assert_eq!("(Wrapper<S>, {unknown})", type_at_pos(&db, pos));
641641
}
642+
643+
#[test]
644+
fn infer_custom_derive_simple() {
645+
// FIXME: this test current now do nothing
646+
let (db, pos) = TestDB::with_position(
647+
r#"
648+
//- /main.rs crate:main
649+
use foo::Foo;
650+
651+
#[derive(Foo)]
652+
struct S{}
653+
654+
fn test() {
655+
S{}<|>;
656+
}
657+
"#,
658+
);
659+
assert_eq!("S", type_at_pos(&db, pos));
660+
}

0 commit comments

Comments
 (0)