Skip to content

Commit 9cf8d32

Browse files
Precompute macro fragment kind
1 parent cf4d4f6 commit 9cf8d32

File tree

9 files changed

+113
-74
lines changed

9 files changed

+113
-74
lines changed

crates/hir_def/src/item_tree.rs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@ use hir_expand::{
1818
ast_id_map::FileAstId,
1919
hygiene::Hygiene,
2020
name::{name, AsName, Name},
21-
HirFileId, InFile,
21+
FragmentKind, HirFileId, InFile,
2222
};
2323
use la_arena::{Arena, Idx, RawIdx};
2424
use profile::Count;
@@ -656,6 +656,7 @@ pub struct MacroCall {
656656
/// Path to the called macro.
657657
pub path: Interned<ModPath>,
658658
pub ast_id: FileAstId<ast::MacroCall>,
659+
pub fragment: FragmentKind,
659660
}
660661

661662
#[derive(Debug, Clone, Eq, PartialEq)]

crates/hir_def/src/item_tree/lower.rs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -624,7 +624,8 @@ impl<'a> Ctx<'a> {
624624
fn lower_macro_call(&mut self, m: &ast::MacroCall) -> Option<FileItemTreeId<MacroCall>> {
625625
let path = Interned::new(ModPath::from_src(self.db, m.path()?, &self.hygiene)?);
626626
let ast_id = self.source_ast_id_map.ast_id(m);
627-
let res = MacroCall { path, ast_id };
627+
let fragment = hir_expand::to_fragment_kind(m);
628+
let res = MacroCall { path, ast_id, fragment };
628629
Some(id(self.data().macro_calls.alloc(res)))
629630
}
630631

crates/hir_def/src/lib.rs

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -62,7 +62,8 @@ use hir_expand::{
6262
ast_id_map::FileAstId,
6363
eager::{expand_eager_macro, ErrorEmitted, ErrorSink},
6464
hygiene::Hygiene,
65-
AstId, AttrId, HirFileId, InFile, MacroCallId, MacroCallKind, MacroDefId, MacroDefKind,
65+
AstId, AttrId, FragmentKind, HirFileId, InFile, MacroCallId, MacroCallKind, MacroDefId,
66+
MacroDefKind,
6667
};
6768
use la_arena::Idx;
6869
use nameres::DefMap;
@@ -652,6 +653,7 @@ impl AsMacroCall for InFile<&ast::MacroCall> {
652653
resolver: impl Fn(path::ModPath) -> Option<MacroDefId>,
653654
mut error_sink: &mut dyn FnMut(mbe::ExpandError),
654655
) -> Result<Result<MacroCallId, ErrorEmitted>, UnresolvedMacro> {
656+
let fragment = hir_expand::to_fragment_kind(self.value);
655657
let ast_id = AstId::new(self.file_id, db.ast_id_map(self.file_id).ast_id(self.value));
656658
let h = Hygiene::new(db.upcast(), self.file_id);
657659
let path = self.value.path().and_then(|path| path::ModPath::from_src(db, path, &h));
@@ -667,6 +669,7 @@ impl AsMacroCall for InFile<&ast::MacroCall> {
667669

668670
macro_call_as_call_id(
669671
&AstIdWithPath::new(ast_id.file_id, ast_id.value, path),
672+
fragment,
670673
db,
671674
krate,
672675
resolver,
@@ -695,6 +698,7 @@ pub struct UnresolvedMacro {
695698

696699
fn macro_call_as_call_id(
697700
call: &AstIdWithPath<ast::MacroCall>,
701+
fragment: FragmentKind,
698702
db: &dyn db::DefDatabase,
699703
krate: CrateId,
700704
resolver: impl Fn(path::ModPath) -> Option<MacroDefId>,
@@ -718,7 +722,11 @@ fn macro_call_as_call_id(
718722
.map(MacroCallId::from)
719723
} else {
720724
Ok(def
721-
.as_lazy_macro(db.upcast(), krate, MacroCallKind::FnLike { ast_id: call.ast_id })
725+
.as_lazy_macro(
726+
db.upcast(),
727+
krate,
728+
MacroCallKind::FnLike { ast_id: call.ast_id, fragment },
729+
)
722730
.into())
723731
};
724732
Ok(res)

crates/hir_def/src/nameres.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -629,7 +629,7 @@ mod diagnostics {
629629
DiagnosticKind::UnresolvedProcMacro { ast } => {
630630
let mut precise_location = None;
631631
let (file, ast, name) = match ast {
632-
MacroCallKind::FnLike { ast_id } => {
632+
MacroCallKind::FnLike { ast_id, .. } => {
633633
let node = ast_id.to_node(db.upcast());
634634
(ast_id.file_id, SyntaxNodePtr::from(AstPtr::new(&node)), None)
635635
}

crates/hir_def/src/nameres/collector.rs

Lines changed: 14 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ use hir_expand::{
1313
builtin_macro::find_builtin_macro,
1414
name::{AsName, Name},
1515
proc_macro::ProcMacroExpander,
16-
AttrId, HirFileId, MacroCallId, MacroCallKind, MacroDefId, MacroDefKind,
16+
AttrId, FragmentKind, HirFileId, MacroCallId, MacroCallKind, MacroDefId, MacroDefKind,
1717
};
1818
use hir_expand::{InFile, MacroCallLoc};
1919
use rustc_hash::{FxHashMap, FxHashSet};
@@ -215,7 +215,7 @@ struct MacroDirective {
215215

216216
#[derive(Clone, Debug, Eq, PartialEq)]
217217
enum MacroDirectiveKind {
218-
FnLike { ast_id: AstIdWithPath<ast::MacroCall> },
218+
FnLike { ast_id: AstIdWithPath<ast::MacroCall>, fragment: FragmentKind },
219219
Derive { ast_id: AstIdWithPath<ast::Item>, derive_attr: AttrId },
220220
}
221221

@@ -807,9 +807,10 @@ impl DefCollector<'_> {
807807
let mut res = ReachedFixedPoint::Yes;
808808
macros.retain(|directive| {
809809
match &directive.kind {
810-
MacroDirectiveKind::FnLike { ast_id } => {
810+
MacroDirectiveKind::FnLike { ast_id, fragment } => {
811811
match macro_call_as_call_id(
812812
ast_id,
813+
*fragment,
813814
self.db,
814815
self.def_map.krate,
815816
|path| {
@@ -926,8 +927,9 @@ impl DefCollector<'_> {
926927

927928
for directive in &self.unexpanded_macros {
928929
match &directive.kind {
929-
MacroDirectiveKind::FnLike { ast_id, .. } => match macro_call_as_call_id(
930+
MacroDirectiveKind::FnLike { ast_id, fragment } => match macro_call_as_call_id(
930931
ast_id,
932+
*fragment,
931933
self.db,
932934
self.def_map.krate,
933935
|path| {
@@ -1496,6 +1498,7 @@ impl ModCollector<'_, '_> {
14961498
let mut error = None;
14971499
match macro_call_as_call_id(
14981500
&ast_id,
1501+
mac.fragment,
14991502
self.def_collector.db,
15001503
self.def_collector.def_map.krate,
15011504
|path| {
@@ -1524,9 +1527,14 @@ impl ModCollector<'_, '_> {
15241527
}
15251528
Ok(Err(_)) => {
15261529
// Built-in macro failed eager expansion.
1530+
1531+
// FIXME: don't parse the file here
1532+
let fragment = hir_expand::to_fragment_kind(
1533+
&ast_id.ast_id.to_node(self.def_collector.db.upcast()),
1534+
);
15271535
self.def_collector.def_map.diagnostics.push(DefDiagnostic::macro_error(
15281536
self.module_id,
1529-
MacroCallKind::FnLike { ast_id: ast_id.ast_id },
1537+
MacroCallKind::FnLike { ast_id: ast_id.ast_id, fragment },
15301538
error.unwrap().to_string(),
15311539
));
15321540
return;
@@ -1543,7 +1551,7 @@ impl ModCollector<'_, '_> {
15431551
self.def_collector.unexpanded_macros.push(MacroDirective {
15441552
module_id: self.module_id,
15451553
depth: self.macro_depth + 1,
1546-
kind: MacroDirectiveKind::FnLike { ast_id },
1554+
kind: MacroDirectiveKind::FnLike { ast_id, fragment: mac.fragment },
15471555
});
15481556
}
15491557

crates/hir_expand/src/builtin_macro.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -578,6 +578,7 @@ mod tests {
578578
krate,
579579
kind: MacroCallKind::FnLike {
580580
ast_id: AstId::new(file_id.into(), ast_id_map.ast_id(&macro_call)),
581+
fragment: FragmentKind::Expr,
581582
},
582583
};
583584

crates/hir_expand/src/db.rs

Lines changed: 11 additions & 60 deletions
Original file line numberDiff line numberDiff line change
@@ -8,9 +8,7 @@ use parser::FragmentKind;
88
use syntax::{
99
algo::diff,
1010
ast::{self, NameOwner},
11-
AstNode, GreenNode, Parse,
12-
SyntaxKind::*,
13-
SyntaxNode, SyntaxToken,
11+
AstNode, GreenNode, Parse, SyntaxNode, SyntaxToken,
1412
};
1513

1614
use crate::{
@@ -160,7 +158,7 @@ pub fn expand_hypothetical(
160158

161159
let hypothetical_expansion = macro_def.expand(db, lazy_id, &tt);
162160

163-
let fragment_kind = to_fragment_kind(db, actual_macro_call);
161+
let fragment_kind = macro_fragment_kind(db, actual_macro_call);
164162

165163
let (node, tmap_2) =
166164
mbe::token_tree_to_syntax_node(&hypothetical_expansion.value, fragment_kind).ok()?;
@@ -226,7 +224,7 @@ fn parse_macro_expansion(
226224
None => return ExpandResult { value: None, err: result.err },
227225
};
228226

229-
let fragment_kind = to_fragment_kind(db, macro_file.macro_call_id);
227+
let fragment_kind = macro_fragment_kind(db, macro_file.macro_call_id);
230228

231229
log::debug!("expanded = {}", tt.as_debug_string());
232230
log::debug!("kind = {:?}", fragment_kind);
@@ -427,62 +425,15 @@ fn hygiene_frame(db: &dyn AstDatabase, file_id: HirFileId) -> Arc<HygieneFrame>
427425
Arc::new(HygieneFrame::new(db, file_id))
428426
}
429427

430-
/// Given a `MacroCallId`, return what `FragmentKind` it belongs to.
431-
/// FIXME: Not completed
432-
fn to_fragment_kind(db: &dyn AstDatabase, id: MacroCallId) -> FragmentKind {
433-
let lazy_id = match id {
434-
MacroCallId::LazyMacro(id) => id,
435-
MacroCallId::EagerMacro(id) => {
436-
return db.lookup_intern_eager_expansion(id).fragment;
437-
}
438-
};
439-
let syn = db.lookup_intern_macro(lazy_id).kind.node(db).value;
440-
441-
let parent = match syn.parent() {
442-
Some(it) => it,
443-
None => return FragmentKind::Statements,
444-
};
445-
446-
match parent.kind() {
447-
MACRO_ITEMS | SOURCE_FILE => FragmentKind::Items,
448-
MACRO_STMTS => FragmentKind::Statements,
449-
MACRO_PAT => FragmentKind::Pattern,
450-
MACRO_TYPE => FragmentKind::Type,
451-
ITEM_LIST => FragmentKind::Items,
452-
LET_STMT => {
453-
// FIXME: Handle LHS Pattern
454-
FragmentKind::Expr
428+
fn macro_fragment_kind(db: &dyn AstDatabase, id: MacroCallId) -> FragmentKind {
429+
match id {
430+
MacroCallId::LazyMacro(id) => {
431+
let loc: MacroCallLoc = db.lookup_intern_macro(id);
432+
loc.kind.fragment_kind()
455433
}
456-
EXPR_STMT => FragmentKind::Statements,
457-
BLOCK_EXPR => FragmentKind::Statements,
458-
ARG_LIST => FragmentKind::Expr,
459-
TRY_EXPR => FragmentKind::Expr,
460-
TUPLE_EXPR => FragmentKind::Expr,
461-
PAREN_EXPR => FragmentKind::Expr,
462-
ARRAY_EXPR => FragmentKind::Expr,
463-
FOR_EXPR => FragmentKind::Expr,
464-
PATH_EXPR => FragmentKind::Expr,
465-
CLOSURE_EXPR => FragmentKind::Expr,
466-
CONDITION => FragmentKind::Expr,
467-
BREAK_EXPR => FragmentKind::Expr,
468-
RETURN_EXPR => FragmentKind::Expr,
469-
MATCH_EXPR => FragmentKind::Expr,
470-
MATCH_ARM => FragmentKind::Expr,
471-
MATCH_GUARD => FragmentKind::Expr,
472-
RECORD_EXPR_FIELD => FragmentKind::Expr,
473-
CALL_EXPR => FragmentKind::Expr,
474-
INDEX_EXPR => FragmentKind::Expr,
475-
METHOD_CALL_EXPR => FragmentKind::Expr,
476-
FIELD_EXPR => FragmentKind::Expr,
477-
AWAIT_EXPR => FragmentKind::Expr,
478-
CAST_EXPR => FragmentKind::Expr,
479-
REF_EXPR => FragmentKind::Expr,
480-
PREFIX_EXPR => FragmentKind::Expr,
481-
RANGE_EXPR => FragmentKind::Expr,
482-
BIN_EXPR => FragmentKind::Expr,
483-
_ => {
484-
// Unknown , Just guess it is `Items`
485-
FragmentKind::Items
434+
MacroCallId::EagerMacro(id) => {
435+
let loc: EagerCallLoc = db.lookup_intern_eager_expansion(id);
436+
loc.fragment
486437
}
487438
}
488439
}

crates/hir_expand/src/eager.rs

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -175,8 +175,13 @@ fn lazy_expand(
175175
) -> ExpandResult<Option<InFile<SyntaxNode>>> {
176176
let ast_id = db.ast_id_map(macro_call.file_id).ast_id(&macro_call.value);
177177

178+
let fragment = crate::to_fragment_kind(&macro_call.value);
178179
let id: MacroCallId = def
179-
.as_lazy_macro(db, krate, MacroCallKind::FnLike { ast_id: macro_call.with_value(ast_id) })
180+
.as_lazy_macro(
181+
db,
182+
krate,
183+
MacroCallKind::FnLike { ast_id: macro_call.with_value(ast_id), fragment },
184+
)
180185
.into();
181186

182187
let err = db.macro_expand_error(id);

crates/hir_expand/src/lib.rs

Lines changed: 66 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,9 @@ pub mod quote;
1616
pub mod eager;
1717

1818
use either::Either;
19+
1920
pub use mbe::{ExpandError, ExpandResult};
21+
pub use parser::FragmentKind;
2022

2123
use std::hash::Hash;
2224
use std::sync::Arc;
@@ -290,7 +292,7 @@ pub struct MacroCallLoc {
290292

291293
#[derive(Debug, Clone, PartialEq, Eq, Hash)]
292294
pub enum MacroCallKind {
293-
FnLike { ast_id: AstId<ast::MacroCall> },
295+
FnLike { ast_id: AstId<ast::MacroCall>, fragment: FragmentKind },
294296
Derive { ast_id: AstId<ast::Item>, derive_name: String, derive_attr: AttrId },
295297
}
296298

@@ -324,6 +326,13 @@ impl MacroCallKind {
324326
MacroCallKind::Derive { ast_id, .. } => Some(ast_id.to_node(db).syntax().clone()),
325327
}
326328
}
329+
330+
fn fragment_kind(&self) -> FragmentKind {
331+
match self {
332+
MacroCallKind::FnLike { fragment, .. } => *fragment,
333+
MacroCallKind::Derive { .. } => FragmentKind::Items,
334+
}
335+
}
327336
}
328337

329338
impl MacroCallId {
@@ -357,7 +366,6 @@ pub struct ExpansionInfo {
357366
}
358367

359368
pub use mbe::Origin;
360-
use parser::FragmentKind;
361369

362370
impl ExpansionInfo {
363371
pub fn call_node(&self) -> Option<InFile<SyntaxNode>> {
@@ -562,3 +570,59 @@ impl<N: AstNode> InFile<N> {
562570
self.with_value(self.value.syntax())
563571
}
564572
}
573+
574+
/// Given a `MacroCallId`, return what `FragmentKind` it belongs to.
575+
/// FIXME: Not completed
576+
pub fn to_fragment_kind(call: &ast::MacroCall) -> FragmentKind {
577+
use syntax::SyntaxKind::*;
578+
579+
let syn = call.syntax();
580+
581+
let parent = match syn.parent() {
582+
Some(it) => it,
583+
None => return FragmentKind::Statements,
584+
};
585+
586+
match parent.kind() {
587+
MACRO_ITEMS | SOURCE_FILE => FragmentKind::Items,
588+
MACRO_STMTS => FragmentKind::Statements,
589+
MACRO_PAT => FragmentKind::Pattern,
590+
MACRO_TYPE => FragmentKind::Type,
591+
ITEM_LIST => FragmentKind::Items,
592+
LET_STMT => {
593+
// FIXME: Handle LHS Pattern
594+
FragmentKind::Expr
595+
}
596+
EXPR_STMT => FragmentKind::Statements,
597+
BLOCK_EXPR => FragmentKind::Statements,
598+
ARG_LIST => FragmentKind::Expr,
599+
TRY_EXPR => FragmentKind::Expr,
600+
TUPLE_EXPR => FragmentKind::Expr,
601+
PAREN_EXPR => FragmentKind::Expr,
602+
ARRAY_EXPR => FragmentKind::Expr,
603+
FOR_EXPR => FragmentKind::Expr,
604+
PATH_EXPR => FragmentKind::Expr,
605+
CLOSURE_EXPR => FragmentKind::Expr,
606+
CONDITION => FragmentKind::Expr,
607+
BREAK_EXPR => FragmentKind::Expr,
608+
RETURN_EXPR => FragmentKind::Expr,
609+
MATCH_EXPR => FragmentKind::Expr,
610+
MATCH_ARM => FragmentKind::Expr,
611+
MATCH_GUARD => FragmentKind::Expr,
612+
RECORD_EXPR_FIELD => FragmentKind::Expr,
613+
CALL_EXPR => FragmentKind::Expr,
614+
INDEX_EXPR => FragmentKind::Expr,
615+
METHOD_CALL_EXPR => FragmentKind::Expr,
616+
FIELD_EXPR => FragmentKind::Expr,
617+
AWAIT_EXPR => FragmentKind::Expr,
618+
CAST_EXPR => FragmentKind::Expr,
619+
REF_EXPR => FragmentKind::Expr,
620+
PREFIX_EXPR => FragmentKind::Expr,
621+
RANGE_EXPR => FragmentKind::Expr,
622+
BIN_EXPR => FragmentKind::Expr,
623+
_ => {
624+
// Unknown , Just guess it is `Items`
625+
FragmentKind::Items
626+
}
627+
}
628+
}

0 commit comments

Comments
 (0)