Skip to content

Commit 77afc6e

Browse files
committed
fix: Report remaining macro errors in assoc item collection
1 parent 2aa44c8 commit 77afc6e

File tree

2 files changed

+132
-81
lines changed

2 files changed

+132
-81
lines changed

crates/hir-def/src/data.rs

Lines changed: 128 additions & 79 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,9 @@ pub mod adt;
44

55
use std::sync::Arc;
66

7-
use hir_expand::{name::Name, AstId, ExpandResult, HirFileId, InFile, MacroCallId, MacroDefKind};
7+
use hir_expand::{
8+
name::Name, AstId, ExpandResult, HirFileId, InFile, MacroCallId, MacroCallKind, MacroDefKind,
9+
};
810
use intern::Interned;
911
use smallvec::SmallVec;
1012
use syntax::{ast, Parse};
@@ -13,7 +15,9 @@ use crate::{
1315
attr::Attrs,
1416
db::DefDatabase,
1517
expander::{Expander, Mark},
16-
item_tree::{self, AssocItem, FnFlags, ItemTree, ItemTreeId, ModItem, Param, TreeId},
18+
item_tree::{
19+
self, AssocItem, FnFlags, ItemTree, ItemTreeId, MacroCall, ModItem, Param, TreeId,
20+
},
1721
macro_call_as_call_id, macro_id_to_def_id,
1822
nameres::{
1923
attr_resolution::ResolvedAttr,
@@ -520,7 +524,7 @@ struct AssocItemCollector<'a> {
520524
db: &'a dyn DefDatabase,
521525
module_id: ModuleId,
522526
def_map: Arc<DefMap>,
523-
inactive_diagnostics: Vec<DefDiagnostic>,
527+
diagnostics: Vec<DefDiagnostic>,
524528
container: ItemContainerId,
525529
expander: Expander,
526530

@@ -543,7 +547,7 @@ impl<'a> AssocItemCollector<'a> {
543547
expander: Expander::new(db, file_id, module_id),
544548
items: Vec::new(),
545549
attr_calls: Vec::new(),
546-
inactive_diagnostics: Vec::new(),
550+
diagnostics: Vec::new(),
547551
}
548552
}
549553

@@ -557,19 +561,18 @@ impl<'a> AssocItemCollector<'a> {
557561
(
558562
self.items,
559563
if self.attr_calls.is_empty() { None } else { Some(Box::new(self.attr_calls)) },
560-
self.inactive_diagnostics,
564+
self.diagnostics,
561565
)
562566
}
563567

564-
// FIXME: proc-macro diagnostics
565568
fn collect(&mut self, item_tree: &ItemTree, tree_id: TreeId, assoc_items: &[AssocItem]) {
566569
let container = self.container;
567570
self.items.reserve(assoc_items.len());
568571

569572
'items: for &item in assoc_items {
570573
let attrs = item_tree.attrs(self.db, self.module_id.krate, ModItem::from(item).into());
571574
if !attrs.is_cfg_enabled(self.expander.cfg_options()) {
572-
self.inactive_diagnostics.push(DefDiagnostic::unconfigured_code(
575+
self.diagnostics.push(DefDiagnostic::unconfigured_code(
573576
self.module_id.local_id,
574577
InFile::new(self.expander.current_file_id(), item.ast_id(item_tree).upcast()),
575578
attrs.cfg().unwrap(),
@@ -583,91 +586,126 @@ impl<'a> AssocItemCollector<'a> {
583586
AstId::new(self.expander.current_file_id(), item.ast_id(item_tree).upcast());
584587
let ast_id_with_path = AstIdWithPath { path: (*attr.path).clone(), ast_id };
585588

586-
if let Ok(ResolvedAttr::Macro(call_id)) = self.def_map.resolve_attr_macro(
589+
match self.def_map.resolve_attr_macro(
587590
self.db,
588591
self.module_id.local_id,
589592
ast_id_with_path,
590593
attr,
591594
) {
592-
self.attr_calls.push((ast_id, call_id));
593-
// If proc attribute macro expansion is disabled, skip expanding it here
594-
if !self.db.expand_proc_attr_macros() {
595-
continue 'attrs;
596-
}
597-
let loc = self.db.lookup_intern_macro_call(call_id);
598-
if let MacroDefKind::ProcMacro(exp, ..) = loc.def.kind {
599-
// If there's no expander for the proc macro (e.g. the
600-
// proc macro is ignored, or building the proc macro
601-
// crate failed), skip expansion like we would if it was
602-
// disabled. This is analogous to the handling in
603-
// `DefCollector::collect_macros`.
604-
if exp.is_dummy() {
595+
Ok(ResolvedAttr::Macro(call_id)) => {
596+
self.attr_calls.push((ast_id, call_id));
597+
// If proc attribute macro expansion is disabled, skip expanding it here
598+
if !self.db.expand_proc_attr_macros() {
605599
continue 'attrs;
606600
}
607-
}
601+
let loc = self.db.lookup_intern_macro_call(call_id);
602+
if let MacroDefKind::ProcMacro(exp, ..) = loc.def.kind {
603+
// If there's no expander for the proc macro (e.g. the
604+
// proc macro is ignored, or building the proc macro
605+
// crate failed), skip expansion like we would if it was
606+
// disabled. This is analogous to the handling in
607+
// `DefCollector::collect_macros`.
608+
if exp.is_dummy() {
609+
continue 'attrs;
610+
}
611+
}
608612

609-
let res = self.expander.enter_expand_id::<ast::MacroItems>(self.db, call_id);
610-
self.collect_macro_items(res, &|| loc.kind.clone());
611-
continue 'items;
613+
let res =
614+
self.expander.enter_expand_id::<ast::MacroItems>(self.db, call_id);
615+
self.collect_macro_items(res, &|| loc.kind.clone());
616+
continue 'items;
617+
}
618+
Ok(_) => (),
619+
Err(_) => {
620+
self.diagnostics.push(DefDiagnostic::unresolved_macro_call(
621+
self.module_id.local_id,
622+
MacroCallKind::Attr {
623+
ast_id,
624+
attr_args: Arc::new((tt::Subtree::empty(), Default::default())),
625+
invoc_attr_index: attr.id,
626+
is_derive: false,
627+
},
628+
attr.path().clone(),
629+
));
630+
}
612631
}
613632
}
614633

615-
match item {
616-
AssocItem::Function(id) => {
617-
let item = &item_tree[id];
634+
self.collect_item(item_tree, tree_id, container, item);
635+
}
636+
}
618637

619-
let def =
620-
FunctionLoc { container, id: ItemTreeId::new(tree_id, id) }.intern(self.db);
621-
self.items.push((item.name.clone(), def.into()));
622-
}
623-
AssocItem::Const(id) => {
624-
let item = &item_tree[id];
625-
626-
let name = match item.name.clone() {
627-
Some(name) => name,
628-
None => continue,
629-
};
630-
let def =
631-
ConstLoc { container, id: ItemTreeId::new(tree_id, id) }.intern(self.db);
632-
self.items.push((name, def.into()));
633-
}
634-
AssocItem::TypeAlias(id) => {
635-
let item = &item_tree[id];
638+
fn collect_item(
639+
&mut self,
640+
item_tree: &ItemTree,
641+
tree_id: TreeId,
642+
container: ItemContainerId,
643+
item: AssocItem,
644+
) {
645+
match item {
646+
AssocItem::Function(id) => {
647+
let item = &item_tree[id];
636648

637-
let def = TypeAliasLoc { container, id: ItemTreeId::new(tree_id, id) }
638-
.intern(self.db);
639-
self.items.push((item.name.clone(), def.into()));
640-
}
641-
AssocItem::MacroCall(call) => {
642-
let file_id = self.expander.current_file_id();
643-
let call = &item_tree[call];
644-
let module = self.expander.module.local_id;
645-
646-
if let Ok(Some(call_id)) = macro_call_as_call_id(
647-
self.db.upcast(),
648-
&AstIdWithPath::new(file_id, call.ast_id, Clone::clone(&call.path)),
649-
call.expand_to,
650-
self.expander.module.krate(),
651-
|path| {
652-
self.def_map
653-
.resolve_path(
654-
self.db,
655-
module,
656-
&path,
657-
crate::item_scope::BuiltinShadowMode::Other,
658-
)
659-
.0
660-
.take_macros()
661-
.map(|it| macro_id_to_def_id(self.db, it))
662-
},
663-
) {
649+
let def =
650+
FunctionLoc { container, id: ItemTreeId::new(tree_id, id) }.intern(self.db);
651+
self.items.push((item.name.clone(), def.into()));
652+
}
653+
AssocItem::Const(id) => {
654+
let item = &item_tree[id];
655+
let Some(name) = item.name.clone() else { return };
656+
let def = ConstLoc { container, id: ItemTreeId::new(tree_id, id) }.intern(self.db);
657+
self.items.push((name, def.into()));
658+
}
659+
AssocItem::TypeAlias(id) => {
660+
let item = &item_tree[id];
661+
662+
let def =
663+
TypeAliasLoc { container, id: ItemTreeId::new(tree_id, id) }.intern(self.db);
664+
self.items.push((item.name.clone(), def.into()));
665+
}
666+
AssocItem::MacroCall(call) => {
667+
let file_id = self.expander.current_file_id();
668+
let MacroCall { ast_id, expand_to, ref path } = item_tree[call];
669+
let module = self.expander.module.local_id;
670+
671+
let resolver = |path| {
672+
self.def_map
673+
.resolve_path(
674+
self.db,
675+
module,
676+
&path,
677+
crate::item_scope::BuiltinShadowMode::Other,
678+
)
679+
.0
680+
.take_macros()
681+
.map(|it| macro_id_to_def_id(self.db, it))
682+
};
683+
match macro_call_as_call_id(
684+
self.db.upcast(),
685+
&AstIdWithPath::new(file_id, ast_id, Clone::clone(path)),
686+
expand_to,
687+
self.expander.module.krate(),
688+
resolver,
689+
) {
690+
Ok(Some(call_id)) => {
664691
let res =
665692
self.expander.enter_expand_id::<ast::MacroItems>(self.db, call_id);
666693
self.collect_macro_items(res, &|| hir_expand::MacroCallKind::FnLike {
667-
ast_id: InFile::new(file_id, call.ast_id),
694+
ast_id: InFile::new(file_id, ast_id),
668695
expand_to: hir_expand::ExpandTo::Items,
669696
});
670697
}
698+
Ok(None) => (),
699+
Err(_) => {
700+
self.diagnostics.push(DefDiagnostic::unresolved_macro_call(
701+
self.module_id.local_id,
702+
MacroCallKind::FnLike {
703+
ast_id: InFile::new(file_id, ast_id),
704+
expand_to,
705+
},
706+
Clone::clone(path),
707+
));
708+
}
671709
}
672710
}
673711
}
@@ -681,14 +719,25 @@ impl<'a> AssocItemCollector<'a> {
681719
let Some((mark, parse)) = value else { return };
682720

683721
if let Some(err) = err {
684-
self.inactive_diagnostics.push(DefDiagnostic::macro_error(
685-
self.module_id.local_id,
686-
error_call_kind(),
687-
err.to_string(),
688-
));
722+
let diag = match err {
723+
// why is this reported here?
724+
hir_expand::ExpandError::UnresolvedProcMacro(krate) => {
725+
DefDiagnostic::unresolved_proc_macro(
726+
self.module_id.local_id,
727+
error_call_kind(),
728+
krate,
729+
)
730+
}
731+
_ => DefDiagnostic::macro_error(
732+
self.module_id.local_id,
733+
error_call_kind(),
734+
err.to_string(),
735+
),
736+
};
737+
self.diagnostics.push(diag);
689738
}
690739
if let errors @ [_, ..] = parse.errors() {
691-
self.inactive_diagnostics.push(DefDiagnostic::macro_expansion_parse_error(
740+
self.diagnostics.push(DefDiagnostic::macro_expansion_parse_error(
692741
self.module_id.local_id,
693742
error_call_kind(),
694743
errors.into(),

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

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -88,7 +88,8 @@ impl DefDiagnostic {
8888
Self { in_module: container, kind: DefDiagnosticKind::UnconfiguredCode { ast, cfg, opts } }
8989
}
9090

91-
pub(super) fn unresolved_proc_macro(
91+
// FIXME: Whats the difference between this and unresolved_macro_call
92+
pub(crate) fn unresolved_proc_macro(
9293
container: LocalModuleId,
9394
ast: MacroCallKind,
9495
krate: CrateId,
@@ -118,7 +119,8 @@ impl DefDiagnostic {
118119
}
119120
}
120121

121-
pub(super) fn unresolved_macro_call(
122+
// FIXME: Whats the difference between this and unresolved_proc_macro
123+
pub(crate) fn unresolved_macro_call(
122124
container: LocalModuleId,
123125
ast: MacroCallKind,
124126
path: ModPath,

0 commit comments

Comments
 (0)