Skip out on single-segment immediate macro resolution when there are errors

This commit is contained in:
Lukas Wirth 2023-08-01 12:38:53 +02:00
parent d999d34e39
commit e14d84d0a6
2 changed files with 39 additions and 21 deletions

View File

@ -1083,7 +1083,7 @@ fn as_call_id(
&self, &self,
db: &dyn ExpandDatabase, db: &dyn ExpandDatabase,
krate: CrateId, krate: CrateId,
resolver: impl Fn(path::ModPath) -> Option<MacroDefId>, resolver: impl Fn(path::ModPath) -> Option<MacroDefId> + Copy,
) -> Option<MacroCallId> { ) -> Option<MacroCallId> {
self.as_call_id_with_errors(db, krate, resolver).ok()?.value self.as_call_id_with_errors(db, krate, resolver).ok()?.value
} }
@ -1092,7 +1092,7 @@ fn as_call_id_with_errors(
&self, &self,
db: &dyn ExpandDatabase, db: &dyn ExpandDatabase,
krate: CrateId, krate: CrateId,
resolver: impl Fn(path::ModPath) -> Option<MacroDefId>, resolver: impl Fn(path::ModPath) -> Option<MacroDefId> + Copy,
) -> Result<ExpandResult<Option<MacroCallId>>, UnresolvedMacro>; ) -> Result<ExpandResult<Option<MacroCallId>>, UnresolvedMacro>;
} }
@ -1101,7 +1101,7 @@ fn as_call_id_with_errors(
&self, &self,
db: &dyn ExpandDatabase, db: &dyn ExpandDatabase,
krate: CrateId, krate: CrateId,
resolver: impl Fn(path::ModPath) -> Option<MacroDefId>, resolver: impl Fn(path::ModPath) -> Option<MacroDefId> + Copy,
) -> Result<ExpandResult<Option<MacroCallId>>, UnresolvedMacro> { ) -> Result<ExpandResult<Option<MacroCallId>>, UnresolvedMacro> {
let expands_to = hir_expand::ExpandTo::from_call_site(self.value); let expands_to = hir_expand::ExpandTo::from_call_site(self.value);
let ast_id = AstId::new(self.file_id, db.ast_id_map(self.file_id).ast_id(self.value)); let ast_id = AstId::new(self.file_id, db.ast_id_map(self.file_id).ast_id(self.value));
@ -1112,12 +1112,13 @@ fn as_call_id_with_errors(
return Ok(ExpandResult::only_err(ExpandError::other("malformed macro invocation"))); return Ok(ExpandResult::only_err(ExpandError::other("malformed macro invocation")));
}; };
macro_call_as_call_id_( macro_call_as_call_id_with_eager(
db, db,
&AstIdWithPath::new(ast_id.file_id, ast_id.value, path), &AstIdWithPath::new(ast_id.file_id, ast_id.value, path),
expands_to, expands_to,
krate, krate,
resolver, resolver,
resolver,
) )
} }
} }
@ -1140,17 +1141,19 @@ fn macro_call_as_call_id(
call: &AstIdWithPath<ast::MacroCall>, call: &AstIdWithPath<ast::MacroCall>,
expand_to: ExpandTo, expand_to: ExpandTo,
krate: CrateId, krate: CrateId,
resolver: impl Fn(path::ModPath) -> Option<MacroDefId>, resolver: impl Fn(path::ModPath) -> Option<MacroDefId> + Copy,
) -> Result<Option<MacroCallId>, UnresolvedMacro> { ) -> Result<Option<MacroCallId>, UnresolvedMacro> {
macro_call_as_call_id_(db, call, expand_to, krate, resolver).map(|res| res.value) macro_call_as_call_id_with_eager(db, call, expand_to, krate, resolver, resolver)
.map(|res| res.value)
} }
fn macro_call_as_call_id_( fn macro_call_as_call_id_with_eager(
db: &dyn ExpandDatabase, db: &dyn ExpandDatabase,
call: &AstIdWithPath<ast::MacroCall>, call: &AstIdWithPath<ast::MacroCall>,
expand_to: ExpandTo, expand_to: ExpandTo,
krate: CrateId, krate: CrateId,
resolver: impl Fn(path::ModPath) -> Option<MacroDefId>, resolver: impl FnOnce(path::ModPath) -> Option<MacroDefId>,
eager_resolver: impl Fn(path::ModPath) -> Option<MacroDefId>,
) -> Result<ExpandResult<Option<MacroCallId>>, UnresolvedMacro> { ) -> Result<ExpandResult<Option<MacroCallId>>, UnresolvedMacro> {
let def = let def =
resolver(call.path.clone()).ok_or_else(|| UnresolvedMacro { path: call.path.clone() })?; resolver(call.path.clone()).ok_or_else(|| UnresolvedMacro { path: call.path.clone() })?;
@ -1159,7 +1162,7 @@ fn macro_call_as_call_id_(
MacroDefKind::BuiltInEager(..) => { MacroDefKind::BuiltInEager(..) => {
let macro_call = InFile::new(call.ast_id.file_id, call.ast_id.to_node(db)); let macro_call = InFile::new(call.ast_id.file_id, call.ast_id.to_node(db));
expand_eager_macro_input(db, krate, macro_call, def, &|path| { expand_eager_macro_input(db, krate, macro_call, def, &|path| {
resolver(path).filter(MacroDefId::is_fn_like) eager_resolver(path).filter(MacroDefId::is_fn_like)
}) })
} }
_ if def.is_fn_like() => ExpandResult { _ if def.is_fn_like() => ExpandResult {

View File

@ -38,7 +38,7 @@
self, ExternCrate, Fields, FileItemTreeId, ImportKind, ItemTree, ItemTreeId, ItemTreeNode, self, ExternCrate, Fields, FileItemTreeId, ImportKind, ItemTree, ItemTreeId, ItemTreeNode,
MacroCall, MacroDef, MacroRules, Mod, ModItem, ModKind, TreeId, MacroCall, MacroDef, MacroRules, Mod, ModItem, ModKind, TreeId,
}, },
macro_call_as_call_id, macro_id_to_def_id, macro_call_as_call_id, macro_call_as_call_id_with_eager, macro_id_to_def_id,
nameres::{ nameres::{
diagnostics::DefDiagnostic, diagnostics::DefDiagnostic,
mod_resolution::ModDir, mod_resolution::ModDir,
@ -2187,7 +2187,7 @@ fn collect_macro_call(&mut self, mac: &MacroCall, container: ItemContainerId) {
// scopes without eager expansion. // scopes without eager expansion.
// Case 1: try to resolve macro calls with single-segment name and expand macro_rules // Case 1: try to resolve macro calls with single-segment name and expand macro_rules
if let Ok(res) = macro_call_as_call_id( if let Ok(res) = macro_call_as_call_id_with_eager(
db.upcast(), db.upcast(),
&ast_id, &ast_id,
mac.expand_to, mac.expand_to,
@ -2210,19 +2210,34 @@ fn collect_macro_call(&mut self, mac: &MacroCall, container: ItemContainerId) {
.map(|it| macro_id_to_def_id(self.def_collector.db, it)) .map(|it| macro_id_to_def_id(self.def_collector.db, it))
}) })
}, },
) { |path| {
// Legacy macros need to be expanded immediately, so that any macros they produce let resolved_res = self.def_collector.def_map.resolve_path_fp_with_macro(
// are in scope. db,
if let Some(val) = res { ResolveMode::Other,
self.def_collector.collect_macro_expansion(
self.module_id, self.module_id,
val, &path,
self.macro_depth + 1, BuiltinShadowMode::Module,
container, Some(MacroSubNs::Bang),
); );
} resolved_res.resolved_def.take_macros().map(|it| macro_id_to_def_id(db, it))
},
) {
// FIXME: if there were errors, this mightve been in the eager expansion from an
// unresolved macro, so we need to push this into late macro resolution. see fixme above
if res.err.is_none() {
// Legacy macros need to be expanded immediately, so that any macros they produce
// are in scope.
if let Some(val) = res.value {
self.def_collector.collect_macro_expansion(
self.module_id,
val,
self.macro_depth + 1,
container,
);
}
return; return;
}
} }
// Case 2: resolve in module scope, expand during name resolution. // Case 2: resolve in module scope, expand during name resolution.