internal: Expand the derive attribute into a pseudo expansion

This commit is contained in:
Lukas Wirth 2022-02-21 02:42:58 +01:00
parent 1fe3b2edd6
commit 7b89d5ede2
17 changed files with 178 additions and 155 deletions

View file

@ -116,11 +116,11 @@ impl ChildBySource for ItemScope {
self.derive_macro_invocs().filter(|(id, _)| id.file_id == file_id).for_each(
|(ast_id, calls)| {
let adt = ast_id.to_node(db.upcast());
calls.for_each(|(attr_id, calls)| {
calls.for_each(|(attr_id, call_id, calls)| {
if let Some(Either::Left(attr)) =
adt.doc_comments_and_attrs().nth(attr_id.ast_index as usize)
{
res[keys::DERIVE_MACRO_CALL].insert(attr, (attr_id, calls.into()));
res[keys::DERIVE_MACRO_CALL].insert(attr, (attr_id, call_id, calls.into()));
}
});
},

View file

@ -66,8 +66,10 @@ pub struct ItemScope {
attr_macros: FxHashMap<AstId<ast::Item>, MacroCallId>,
/// The derive macro invocations in this scope, keyed by the owner item over the actual derive attributes
/// paired with the derive macro invocations for the specific attribute.
derive_macros:
FxHashMap<AstId<ast::Adt>, SmallVec<[(AttrId, SmallVec<[Option<MacroCallId>; 1]>); 1]>>,
derive_macros: FxHashMap<
AstId<ast::Adt>,
SmallVec<[(AttrId, MacroCallId, SmallVec<[Option<MacroCallId>; 1]>); 1]>,
>,
}
pub(crate) static BUILTIN_SCOPE: Lazy<FxHashMap<Name, PerNs>> = Lazy::new(|| {
@ -210,7 +212,7 @@ impl ItemScope {
idx: usize,
) {
if let Some(derives) = self.derive_macros.get_mut(&adt) {
if let Some((_, invocs)) = derives.iter_mut().find(|&&mut (id, _)| id == attr_id) {
if let Some((.., invocs)) = derives.iter_mut().find(|&&mut (id, ..)| id == attr_id) {
invocs[idx] = Some(call);
}
}
@ -223,19 +225,23 @@ impl ItemScope {
&mut self,
adt: AstId<ast::Adt>,
attr_id: AttrId,
call_id: MacroCallId,
len: usize,
) {
self.derive_macros.entry(adt).or_default().push((attr_id, smallvec![None; len]));
self.derive_macros.entry(adt).or_default().push((attr_id, call_id, smallvec![None; len]));
}
pub(crate) fn derive_macro_invocs(
&self,
) -> impl Iterator<
Item = (AstId<ast::Adt>, impl Iterator<Item = (AttrId, &[Option<MacroCallId>])>),
Item = (
AstId<ast::Adt>,
impl Iterator<Item = (AttrId, MacroCallId, &[Option<MacroCallId>])>,
),
> + '_ {
self.derive_macros
.iter()
.map(|(k, v)| (*k, v.iter().map(|(attr_id, invocs)| (*attr_id, &**invocs))))
self.derive_macros.iter().map(|(k, v)| {
(*k, v.iter().map(|&(attr_id, call_id, ref invocs)| (attr_id, call_id, &**invocs)))
})
}
pub(crate) fn unnamed_trait_vis(&self, tr: TraitId) -> Option<Visibility> {

View file

@ -34,7 +34,8 @@ pub const CONST_PARAM: Key<ast::ConstParam, ConstParamId> = Key::new();
pub const MACRO: Key<ast::Macro, MacroDefId> = Key::new();
pub const ATTR_MACRO_CALL: Key<ast::Item, MacroCallId> = Key::new();
pub const DERIVE_MACRO_CALL: Key<ast::Attr, (AttrId, Box<[Option<MacroCallId>]>)> = Key::new();
pub const DERIVE_MACRO_CALL: Key<ast::Attr, (AttrId, MacroCallId, Box<[Option<MacroCallId>]>)> =
Key::new();
/// XXX: AST Nodes and SyntaxNodes have identity equality semantics: nodes are
/// equal if they point to exactly the same object.

View file

@ -690,9 +690,9 @@ impl AsMacroCall for InFile<&ast::MacroCall> {
};
macro_call_as_call_id(
db,
&AstIdWithPath::new(ast_id.file_id, ast_id.value, path),
expands_to,
db,
krate,
resolver,
error_sink,
@ -714,9 +714,9 @@ impl<T: ast::AstNode> AstIdWithPath<T> {
}
fn macro_call_as_call_id(
db: &dyn db::DefDatabase,
call: &AstIdWithPath<ast::MacroCall>,
expand_to: ExpandTo,
db: &dyn db::DefDatabase,
krate: CrateId,
resolver: impl Fn(path::ModPath) -> Option<MacroDefId>,
error_sink: &mut dyn FnMut(ExpandError),
@ -739,10 +739,10 @@ fn macro_call_as_call_id(
}
fn derive_macro_as_call_id(
db: &dyn db::DefDatabase,
item_attr: &AstIdWithPath<ast::Adt>,
derive_attr: AttrId,
derive_pos: u32,
db: &dyn db::DefDatabase,
krate: CrateId,
resolver: impl Fn(path::ModPath) -> Option<MacroDefId>,
) -> Result<MacroCallId, UnresolvedMacro> {
@ -761,11 +761,12 @@ fn derive_macro_as_call_id(
}
fn attr_macro_as_call_id(
db: &dyn db::DefDatabase,
item_attr: &AstIdWithPath<ast::Item>,
macro_attr: &Attr,
db: &dyn db::DefDatabase,
krate: CrateId,
def: MacroDefId,
is_derive: bool,
) -> MacroCallId {
let mut arg = match macro_attr.input.as_deref() {
Some(attr::AttrInput::TokenTree(tt, map)) => (tt.clone(), map.clone()),
@ -782,6 +783,7 @@ fn attr_macro_as_call_id(
ast_id: item_attr.ast_id,
attr_args: Arc::new(arg),
invoc_attr_index: macro_attr.id.ast_index,
is_derive,
},
);
res

View file

@ -54,7 +54,7 @@ impl DefMap {
None => return Err(UnresolvedMacro { path: ast_id.path.clone() }),
};
Ok(ResolvedAttr::Macro(attr_macro_as_call_id(&ast_id, attr, db, self.krate, def)))
Ok(ResolvedAttr::Macro(attr_macro_as_call_id(db, &ast_id, attr, self.krate, def, false)))
}
pub(crate) fn is_builtin_or_registered_attr(&self, path: &ModPath) -> bool {

View file

@ -1055,9 +1055,9 @@ impl DefCollector<'_> {
match &directive.kind {
MacroDirectiveKind::FnLike { ast_id, expand_to } => {
let call_id = macro_call_as_call_id(
self.db,
ast_id,
*expand_to,
self.db,
self.def_map.krate,
&resolver,
&mut |_err| (),
@ -1070,10 +1070,10 @@ impl DefCollector<'_> {
}
MacroDirectiveKind::Derive { ast_id, derive_attr, derive_pos } => {
let call_id = derive_macro_as_call_id(
self.db,
ast_id,
*derive_attr,
*derive_pos as u32,
self.db,
self.def_map.krate,
&resolver,
);
@ -1170,9 +1170,17 @@ impl DefCollector<'_> {
len = idx;
}
let call_id = attr_macro_as_call_id(
self.db,
file_ast_id,
attr,
self.def_map.krate,
def,
true,
);
self.def_map.modules[directive.module_id]
.scope
.init_derive_attribute(ast_id, attr.id, len + 1);
.init_derive_attribute(ast_id, attr.id, call_id, len + 1);
}
None => {
let diag = DefDiagnostic::malformed_derive(
@ -1192,8 +1200,14 @@ impl DefCollector<'_> {
}
// Not resolved to a derive helper or the derive attribute, so try to treat as a normal attribute.
let call_id =
attr_macro_as_call_id(file_ast_id, attr, self.db, self.def_map.krate, def);
let call_id = attr_macro_as_call_id(
self.db,
file_ast_id,
attr,
self.def_map.krate,
def,
false,
);
let loc: MacroCallLoc = self.db.lookup_intern_macro_call(call_id);
// Skip #[test]/#[bench] expansion, which would merely result in more memory usage
@ -1310,9 +1324,9 @@ impl DefCollector<'_> {
match &directive.kind {
MacroDirectiveKind::FnLike { ast_id, expand_to } => {
let macro_call_as_call_id = macro_call_as_call_id(
self.db,
ast_id,
*expand_to,
self.db,
self.def_map.krate,
|path| {
let resolved_res = self.def_map.resolve_path_fp_with_macro(
@ -1959,9 +1973,9 @@ impl ModCollector<'_, '_> {
// Case 1: try to resolve in legacy scope and expand macro_rules
let mut error = None;
match macro_call_as_call_id(
self.def_collector.db,
&ast_id,
mac.expand_to,
self.def_collector.db,
self.def_collector.def_map.krate,
|path| {
path.as_ident().and_then(|name| {