mirror of
https://github.com/rust-lang/rust.git
synced 2024-12-12 16:45:37 +00:00
Track in-scope derive helpers during nameres
This commit is contained in:
parent
7cb5920372
commit
d4eb6708d9
@ -43,7 +43,7 @@ use crate::{
|
|||||||
UnresolvedMacro,
|
UnresolvedMacro,
|
||||||
};
|
};
|
||||||
|
|
||||||
use super::proc_macro::ProcMacroDef;
|
use super::proc_macro::{ProcMacroDef, ProcMacroKind};
|
||||||
|
|
||||||
const GLOB_RECURSION_LIMIT: usize = 100;
|
const GLOB_RECURSION_LIMIT: usize = 100;
|
||||||
const EXPANSION_DEPTH_LIMIT: usize = 128;
|
const EXPANSION_DEPTH_LIMIT: usize = 128;
|
||||||
@ -101,6 +101,7 @@ pub(super) fn collect_defs(
|
|||||||
exports_proc_macros: false,
|
exports_proc_macros: false,
|
||||||
from_glob_import: Default::default(),
|
from_glob_import: Default::default(),
|
||||||
ignore_attrs_on: FxHashSet::default(),
|
ignore_attrs_on: FxHashSet::default(),
|
||||||
|
derive_helpers_in_scope: FxHashMap::default(),
|
||||||
};
|
};
|
||||||
match block {
|
match block {
|
||||||
Some(block) => {
|
Some(block) => {
|
||||||
@ -247,6 +248,9 @@ struct DefCollector<'a> {
|
|||||||
exports_proc_macros: bool,
|
exports_proc_macros: bool,
|
||||||
from_glob_import: PerNsGlobImports,
|
from_glob_import: PerNsGlobImports,
|
||||||
ignore_attrs_on: FxHashSet<InFile<ModItem>>,
|
ignore_attrs_on: FxHashSet<InFile<ModItem>>,
|
||||||
|
/// Tracks which custom derives are in scope for an item, to allow resolution of derive helper
|
||||||
|
/// attributes.
|
||||||
|
derive_helpers_in_scope: FxHashMap<AstId<ast::Item>, Vec<Name>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl DefCollector<'_> {
|
impl DefCollector<'_> {
|
||||||
@ -950,21 +954,35 @@ impl DefCollector<'_> {
|
|||||||
// First, fetch the raw expansion result for purposes of error reporting. This goes through
|
// First, fetch the raw expansion result for purposes of error reporting. This goes through
|
||||||
// `macro_expand_error` to avoid depending on the full expansion result (to improve
|
// `macro_expand_error` to avoid depending on the full expansion result (to improve
|
||||||
// incrementality).
|
// incrementality).
|
||||||
|
let loc: MacroCallLoc = self.db.lookup_intern_macro(macro_call_id);
|
||||||
let err = self.db.macro_expand_error(macro_call_id);
|
let err = self.db.macro_expand_error(macro_call_id);
|
||||||
if let Some(err) = err {
|
if let Some(err) = err {
|
||||||
let loc: MacroCallLoc = self.db.lookup_intern_macro(macro_call_id);
|
|
||||||
|
|
||||||
let diag = match err {
|
let diag = match err {
|
||||||
hir_expand::ExpandError::UnresolvedProcMacro => {
|
hir_expand::ExpandError::UnresolvedProcMacro => {
|
||||||
// Missing proc macros are non-fatal, so they are handled specially.
|
// Missing proc macros are non-fatal, so they are handled specially.
|
||||||
DefDiagnostic::unresolved_proc_macro(module_id, loc.kind)
|
DefDiagnostic::unresolved_proc_macro(module_id, loc.kind.clone())
|
||||||
}
|
}
|
||||||
_ => DefDiagnostic::macro_error(module_id, loc.kind, err.to_string()),
|
_ => DefDiagnostic::macro_error(module_id, loc.kind.clone(), err.to_string()),
|
||||||
};
|
};
|
||||||
|
|
||||||
self.def_map.diagnostics.push(diag);
|
self.def_map.diagnostics.push(diag);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// If we've just resolved a derive, record its helper attributes.
|
||||||
|
if let MacroCallKind::Derive { ast_id, .. } = &loc.kind {
|
||||||
|
if loc.def.krate != self.def_map.krate {
|
||||||
|
let def_map = self.db.crate_def_map(loc.def.krate);
|
||||||
|
if let Some(def) = def_map.exported_proc_macros.get(&loc.def) {
|
||||||
|
if let ProcMacroKind::CustomDerive { helpers } = &def.kind {
|
||||||
|
self.derive_helpers_in_scope
|
||||||
|
.entry(*ast_id)
|
||||||
|
.or_default()
|
||||||
|
.extend(helpers.iter().cloned());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Then, fetch and process the item tree. This will reuse the expansion result from above.
|
// Then, fetch and process the item tree. This will reuse the expansion result from above.
|
||||||
let item_tree = self.db.file_item_tree(file_id);
|
let item_tree = self.db.file_item_tree(file_id);
|
||||||
let mod_dir = self.mod_dirs[&module_id].clone();
|
let mod_dir = self.mod_dirs[&module_id].clone();
|
||||||
@ -1120,9 +1138,8 @@ impl ModCollector<'_, '_> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if let Err(()) = self.resolve_attributes(&attrs, item) {
|
if let Err(()) = self.resolve_attributes(&attrs, item) {
|
||||||
// Do not process the item. It has at least one non-builtin attribute, which *must*
|
// Do not process the item. It has at least one non-builtin attribute, so the
|
||||||
// resolve to a proc macro (or fail to resolve), so we'll never see this item during
|
// fixed-point algorithm is required to resolve the rest of them.
|
||||||
// normal name resolution.
|
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1721,6 +1738,7 @@ mod tests {
|
|||||||
exports_proc_macros: false,
|
exports_proc_macros: false,
|
||||||
from_glob_import: Default::default(),
|
from_glob_import: Default::default(),
|
||||||
ignore_attrs_on: FxHashSet::default(),
|
ignore_attrs_on: FxHashSet::default(),
|
||||||
|
derive_helpers_in_scope: FxHashMap::default(),
|
||||||
};
|
};
|
||||||
collector.seed_with_top_level();
|
collector.seed_with_top_level();
|
||||||
collector.collect();
|
collector.collect();
|
||||||
|
@ -237,7 +237,7 @@ struct EagerCallInfo {
|
|||||||
|
|
||||||
#[derive(Debug, Clone, PartialEq, Eq, Hash)]
|
#[derive(Debug, Clone, PartialEq, Eq, Hash)]
|
||||||
pub struct MacroCallLoc {
|
pub struct MacroCallLoc {
|
||||||
pub(crate) def: MacroDefId,
|
pub def: MacroDefId,
|
||||||
pub(crate) krate: CrateId,
|
pub(crate) krate: CrateId,
|
||||||
eager: Option<EagerCallInfo>,
|
eager: Option<EagerCallInfo>,
|
||||||
pub kind: MacroCallKind,
|
pub kind: MacroCallKind,
|
||||||
|
Loading…
Reference in New Issue
Block a user