From 4f07d8dd587c24bca8622ee8c39e5a1e156825b4 Mon Sep 17 00:00:00 2001 From: Jonas Schievink Date: Fri, 18 Dec 2020 00:23:46 +0100 Subject: Refactor attributes API to allow handling cfg_attr --- crates/hir_def/src/adt.rs | 47 ++++++---- crates/hir_def/src/attr.rs | 146 ++++++++++++++++++++------------ crates/hir_def/src/body.rs | 17 ++-- crates/hir_def/src/body/lower.rs | 2 +- crates/hir_def/src/data.rs | 5 +- crates/hir_def/src/item_tree.rs | 19 +++-- crates/hir_def/src/item_tree/lower.rs | 17 ++-- crates/hir_def/src/nameres/collector.rs | 48 ++++++----- 8 files changed, 187 insertions(+), 114 deletions(-) (limited to 'crates') diff --git a/crates/hir_def/src/adt.rs b/crates/hir_def/src/adt.rs index eafa3abb6..236d6f1b7 100644 --- a/crates/hir_def/src/adt.rs +++ b/crates/hir_def/src/adt.rs @@ -3,6 +3,7 @@ use std::sync::Arc; use arena::{map::ArenaMap, Arena}; +use base_db::CrateId; use either::Either; use hir_expand::{ name::{AsName, Name}, @@ -66,8 +67,13 @@ pub enum ReprKind { Other, } -fn repr_from_value(item_tree: &ItemTree, of: AttrOwner) -> Option { - item_tree.attrs(of).by_key("repr").tt_values().find_map(parse_repr_tt) +fn repr_from_value( + db: &dyn DefDatabase, + krate: CrateId, + item_tree: &ItemTree, + of: AttrOwner, +) -> Option { + item_tree.attrs(db, krate, of).by_key("repr").tt_values().find_map(parse_repr_tt) } fn parse_repr_tt(tt: &Subtree) -> Option { @@ -86,12 +92,13 @@ fn parse_repr_tt(tt: &Subtree) -> Option { impl StructData { pub(crate) fn struct_data_query(db: &dyn DefDatabase, id: StructId) -> Arc { let loc = id.lookup(db); + let krate = loc.container.module(db).krate; let item_tree = db.item_tree(loc.id.file_id); - let repr = repr_from_value(&item_tree, ModItem::from(loc.id.value).into()); + let repr = repr_from_value(db, krate, &item_tree, ModItem::from(loc.id.value).into()); let cfg_options = db.crate_graph()[loc.container.module(db).krate].cfg_options.clone(); let strukt = &item_tree[loc.id.value]; - let variant_data = lower_fields(&item_tree, &cfg_options, &strukt.fields, None); + let variant_data = lower_fields(db, krate, &item_tree, &cfg_options, &strukt.fields, None); Arc::new(StructData { name: strukt.name.clone(), variant_data: Arc::new(variant_data), @@ -100,12 +107,13 @@ impl StructData { } pub(crate) fn union_data_query(db: &dyn DefDatabase, id: UnionId) -> Arc { let loc = id.lookup(db); + let krate = loc.container.module(db).krate; let item_tree = db.item_tree(loc.id.file_id); - let repr = repr_from_value(&item_tree, ModItem::from(loc.id.value).into()); + let repr = repr_from_value(db, krate, &item_tree, ModItem::from(loc.id.value).into()); let cfg_options = db.crate_graph()[loc.container.module(db).krate].cfg_options.clone(); let union = &item_tree[loc.id.value]; - let variant_data = lower_fields(&item_tree, &cfg_options, &union.fields, None); + let variant_data = lower_fields(db, krate, &item_tree, &cfg_options, &union.fields, None); Arc::new(StructData { name: union.name.clone(), @@ -118,16 +126,23 @@ impl StructData { impl EnumData { pub(crate) fn enum_data_query(db: &dyn DefDatabase, e: EnumId) -> Arc { let loc = e.lookup(db); + let krate = loc.container.module(db).krate; let item_tree = db.item_tree(loc.id.file_id); - let cfg_options = db.crate_graph()[loc.container.module(db).krate].cfg_options.clone(); + let cfg_options = db.crate_graph()[krate].cfg_options.clone(); let enum_ = &item_tree[loc.id.value]; let mut variants = Arena::new(); for var_id in enum_.variants.clone() { - if item_tree.attrs(var_id.into()).is_cfg_enabled(&cfg_options) { + if item_tree.attrs(db, krate, var_id.into()).is_cfg_enabled(&cfg_options) { let var = &item_tree[var_id]; - let var_data = - lower_fields(&item_tree, &cfg_options, &var.fields, Some(enum_.visibility)); + let var_data = lower_fields( + db, + krate, + &item_tree, + &cfg_options, + &var.fields, + Some(enum_.visibility), + ); variants.alloc(EnumVariantData { name: var.name.clone(), @@ -170,7 +185,7 @@ fn lower_enum( .variant_list() .into_iter() .flat_map(|it| it.variants()) - .filter(|var| expander.is_cfg_enabled(var)); + .filter(|var| expander.is_cfg_enabled(db, var)); for var in variants { trace.alloc( || var.clone(), @@ -262,7 +277,7 @@ fn lower_struct( match &ast.value { ast::StructKind::Tuple(fl) => { for (i, fd) in fl.fields().enumerate() { - if !expander.is_cfg_enabled(&fd) { + if !expander.is_cfg_enabled(db, &fd) { continue; } @@ -279,7 +294,7 @@ fn lower_struct( } ast::StructKind::Record(fl) => { for fd in fl.fields() { - if !expander.is_cfg_enabled(&fd) { + if !expander.is_cfg_enabled(db, &fd) { continue; } @@ -299,6 +314,8 @@ fn lower_struct( } fn lower_fields( + db: &dyn DefDatabase, + krate: CrateId, item_tree: &ItemTree, cfg_options: &CfgOptions, fields: &Fields, @@ -308,7 +325,7 @@ fn lower_fields( Fields::Record(flds) => { let mut arena = Arena::new(); for field_id in flds.clone() { - if item_tree.attrs(field_id.into()).is_cfg_enabled(cfg_options) { + if item_tree.attrs(db, krate, field_id.into()).is_cfg_enabled(cfg_options) { arena.alloc(lower_field(item_tree, &item_tree[field_id], override_visibility)); } } @@ -317,7 +334,7 @@ fn lower_fields( Fields::Tuple(flds) => { let mut arena = Arena::new(); for field_id in flds.clone() { - if item_tree.attrs(field_id.into()).is_cfg_enabled(cfg_options) { + if item_tree.attrs(db, krate, field_id.into()).is_cfg_enabled(cfg_options) { arena.alloc(lower_field(item_tree, &item_tree[field_id], override_visibility)); } } diff --git a/crates/hir_def/src/attr.rs b/crates/hir_def/src/attr.rs index 45313f335..9cd0b72aa 100644 --- a/crates/hir_def/src/attr.rs +++ b/crates/hir_def/src/attr.rs @@ -2,6 +2,7 @@ use std::{ops, sync::Arc}; +use base_db::CrateId; use cfg::{CfgExpr, CfgOptions}; use either::Either; use hir_expand::{hygiene::Hygiene, AstId, InFile}; @@ -38,12 +39,16 @@ impl From for String { } } +/// Syntactical attributes, without filtering of `cfg_attr`s. #[derive(Default, Debug, Clone, PartialEq, Eq)] -pub struct Attrs { +pub struct RawAttrs { entries: Option>, } -impl ops::Deref for Attrs { +#[derive(Default, Debug, Clone, PartialEq, Eq)] +pub struct Attrs(RawAttrs); + +impl ops::Deref for RawAttrs { type Target = [Attr]; fn deref(&self) -> &[Attr] { @@ -54,19 +59,88 @@ impl ops::Deref for Attrs { } } +impl ops::Deref for Attrs { + type Target = [Attr]; + + fn deref(&self) -> &[Attr] { + match &self.0.entries { + Some(it) => &*it, + None => &[], + } + } +} + +impl RawAttrs { + pub const EMPTY: Self = Self { entries: None }; + + pub(crate) fn new(owner: &dyn AttrsOwner, hygiene: &Hygiene) -> Self { + let (inner_attrs, inner_docs) = inner_attributes(owner.syntax()) + .map_or((None, None), |(attrs, docs)| ((Some(attrs), Some(docs)))); + + let outer_attrs = owner.attrs().filter(|attr| attr.excl_token().is_none()); + let attrs = outer_attrs + .chain(inner_attrs.into_iter().flatten()) + .map(|attr| (attr.syntax().text_range().start(), Attr::from_src(attr, hygiene))); + + let outer_docs = + ast::CommentIter::from_syntax_node(owner.syntax()).filter(ast::Comment::is_outer); + let docs = outer_docs.chain(inner_docs.into_iter().flatten()).map(|docs_text| { + ( + docs_text.syntax().text_range().start(), + docs_text.doc_comment().map(|doc| Attr { + input: Some(AttrInput::Literal(SmolStr::new(doc))), + path: ModPath::from(hir_expand::name!(doc)), + }), + ) + }); + // sort here by syntax node offset because the source can have doc attributes and doc strings be interleaved + let attrs: Vec<_> = docs.chain(attrs).sorted_by_key(|&(offset, _)| offset).collect(); + let entries = if attrs.is_empty() { + // Avoid heap allocation + None + } else { + Some(attrs.into_iter().flat_map(|(_, attr)| attr).collect()) + }; + Self { entries } + } + + fn from_attrs_owner(db: &dyn DefDatabase, owner: InFile<&dyn AttrsOwner>) -> Self { + let hygiene = Hygiene::new(db.upcast(), owner.file_id); + Self::new(owner.value, &hygiene) + } + + pub(crate) fn merge(&self, other: Self) -> Self { + match (&self.entries, &other.entries) { + (None, None) => Self::EMPTY, + (Some(entries), None) | (None, Some(entries)) => { + Self { entries: Some(entries.clone()) } + } + (Some(a), Some(b)) => { + Self { entries: Some(a.iter().chain(b.iter()).cloned().collect()) } + } + } + } + + /// Processes `cfg_attr`s, returning the resulting semantic `Attrs`. + pub(crate) fn filter(self, _db: &dyn DefDatabase, _krate: CrateId) -> Attrs { + // FIXME actually implement this + Attrs(self) + } +} + impl Attrs { - pub const EMPTY: Attrs = Attrs { entries: None }; + pub const EMPTY: Self = Self(RawAttrs::EMPTY); pub(crate) fn attrs_query(db: &dyn DefDatabase, def: AttrDefId) -> Attrs { - match def { + let raw_attrs = match def { AttrDefId::ModuleId(module) => { let def_map = db.crate_def_map(module.krate); let mod_data = &def_map[module.local_id]; match mod_data.declaration_source(db) { Some(it) => { - Attrs::from_attrs_owner(db, it.as_ref().map(|it| it as &dyn AttrsOwner)) + RawAttrs::from_attrs_owner(db, it.as_ref().map(|it| it as &dyn AttrsOwner)) } - None => Attrs::from_attrs_owner( + None => RawAttrs::from_attrs_owner( db, mod_data.definition_source(db).as_ref().map(|src| match src { ModuleSource::SourceFile(file) => file as &dyn AttrsOwner, @@ -78,14 +152,14 @@ impl Attrs { AttrDefId::FieldId(it) => { let src = it.parent.child_source(db); match &src.value[it.local_id] { - Either::Left(_tuple) => Attrs::default(), - Either::Right(record) => Attrs::from_attrs_owner(db, src.with_value(record)), + Either::Left(_tuple) => RawAttrs::default(), + Either::Right(record) => RawAttrs::from_attrs_owner(db, src.with_value(record)), } } AttrDefId::EnumVariantId(var_id) => { let src = var_id.parent.child_source(db); let src = src.as_ref().map(|it| &it[var_id.local_id]); - Attrs::from_attrs_owner(db, src.map(|it| it as &dyn AttrsOwner)) + RawAttrs::from_attrs_owner(db, src.map(|it| it as &dyn AttrsOwner)) } AttrDefId::AdtId(it) => match it { AdtId::StructId(it) => attrs_from_item_tree(it.lookup(db).id, db), @@ -101,53 +175,19 @@ impl Attrs { AttrDefId::StaticId(it) => attrs_from_item_tree(it.lookup(db).id, db), AttrDefId::FunctionId(it) => attrs_from_item_tree(it.lookup(db).id, db), AttrDefId::TypeAliasId(it) => attrs_from_item_tree(it.lookup(db).id, db), - } - } - - fn from_attrs_owner(db: &dyn DefDatabase, owner: InFile<&dyn AttrsOwner>) -> Attrs { - let hygiene = Hygiene::new(db.upcast(), owner.file_id); - Attrs::new(owner.value, &hygiene) - } - - pub(crate) fn new(owner: &dyn AttrsOwner, hygiene: &Hygiene) -> Attrs { - let (inner_attrs, inner_docs) = inner_attributes(owner.syntax()) - .map_or((None, None), |(attrs, docs)| ((Some(attrs), Some(docs)))); - - let outer_attrs = owner.attrs().filter(|attr| attr.excl_token().is_none()); - let attrs = outer_attrs - .chain(inner_attrs.into_iter().flatten()) - .map(|attr| (attr.syntax().text_range().start(), Attr::from_src(attr, hygiene))); - - let outer_docs = - ast::CommentIter::from_syntax_node(owner.syntax()).filter(ast::Comment::is_outer); - let docs = outer_docs.chain(inner_docs.into_iter().flatten()).map(|docs_text| { - ( - docs_text.syntax().text_range().start(), - docs_text.doc_comment().map(|doc| Attr { - input: Some(AttrInput::Literal(SmolStr::new(doc))), - path: ModPath::from(hir_expand::name!(doc)), - }), - ) - }); - // sort here by syntax node offset because the source can have doc attributes and doc strings be interleaved - let attrs: Vec<_> = docs.chain(attrs).sorted_by_key(|&(offset, _)| offset).collect(); - let entries = if attrs.is_empty() { - // Avoid heap allocation - None - } else { - Some(attrs.into_iter().flat_map(|(_, attr)| attr).collect()) }; - Attrs { entries } + + raw_attrs.filter(db, def.krate(db)) } pub fn merge(&self, other: Attrs) -> Attrs { - match (&self.entries, &other.entries) { - (None, None) => Attrs { entries: None }, + match (&self.0.entries, &other.0.entries) { + (None, None) => Attrs::EMPTY, (Some(entries), None) | (None, Some(entries)) => { - Attrs { entries: Some(entries.clone()) } + Attrs(RawAttrs { entries: Some(entries.clone()) }) } (Some(a), Some(b)) => { - Attrs { entries: Some(a.iter().chain(b.iter()).cloned().collect()) } + Attrs(RawAttrs { entries: Some(a.iter().chain(b.iter()).cloned().collect()) }) } } } @@ -291,16 +331,16 @@ impl<'a> AttrQuery<'a> { } } -fn attrs_from_ast(src: AstId, db: &dyn DefDatabase) -> Attrs +fn attrs_from_ast(src: AstId, db: &dyn DefDatabase) -> RawAttrs where N: ast::AttrsOwner, { let src = InFile::new(src.file_id, src.to_node(db.upcast())); - Attrs::from_attrs_owner(db, src.as_ref().map(|it| it as &dyn AttrsOwner)) + RawAttrs::from_attrs_owner(db, src.as_ref().map(|it| it as &dyn AttrsOwner)) } -fn attrs_from_item_tree(id: ItemTreeId, db: &dyn DefDatabase) -> Attrs { +fn attrs_from_item_tree(id: ItemTreeId, db: &dyn DefDatabase) -> RawAttrs { let tree = db.item_tree(id.file_id); let mod_item = N::id_to_mod_item(id.value); - tree.attrs(mod_item.into()).clone() + tree.raw_attrs(mod_item.into()).clone() } diff --git a/crates/hir_def/src/body.rs b/crates/hir_def/src/body.rs index c5d6f5fb0..998b82601 100644 --- a/crates/hir_def/src/body.rs +++ b/crates/hir_def/src/body.rs @@ -24,7 +24,7 @@ use test_utils::mark; pub(crate) use lower::LowerCtx; use crate::{ - attr::Attrs, + attr::{Attrs, RawAttrs}, db::DefDatabase, expr::{Expr, ExprId, Pat, PatId}, item_scope::BuiltinShadowMode, @@ -40,6 +40,7 @@ use crate::{ pub(crate) struct CfgExpander { cfg_options: CfgOptions, hygiene: Hygiene, + krate: CrateId, } pub(crate) struct Expander { @@ -65,15 +66,15 @@ impl CfgExpander { ) -> CfgExpander { let hygiene = Hygiene::new(db.upcast(), current_file_id); let cfg_options = db.crate_graph()[krate].cfg_options.clone(); - CfgExpander { cfg_options, hygiene } + CfgExpander { cfg_options, hygiene, krate } } - pub(crate) fn parse_attrs(&self, owner: &dyn ast::AttrsOwner) -> Attrs { - Attrs::new(owner, &self.hygiene) + pub(crate) fn parse_attrs(&self, db: &dyn DefDatabase, owner: &dyn ast::AttrsOwner) -> Attrs { + RawAttrs::new(owner, &self.hygiene).filter(db, self.krate) } - pub(crate) fn is_cfg_enabled(&self, owner: &dyn ast::AttrsOwner) -> bool { - let attrs = self.parse_attrs(owner); + pub(crate) fn is_cfg_enabled(&self, db: &dyn DefDatabase, owner: &dyn ast::AttrsOwner) -> bool { + let attrs = self.parse_attrs(db, owner); attrs.is_cfg_enabled(&self.cfg_options) } } @@ -189,8 +190,8 @@ impl Expander { InFile { file_id: self.current_file_id, value } } - pub(crate) fn parse_attrs(&self, owner: &dyn ast::AttrsOwner) -> Attrs { - self.cfg_expander.parse_attrs(owner) + pub(crate) fn parse_attrs(&self, db: &dyn DefDatabase, owner: &dyn ast::AttrsOwner) -> Attrs { + self.cfg_expander.parse_attrs(db, owner) } pub(crate) fn cfg_options(&self) -> &CfgOptions { diff --git a/crates/hir_def/src/body/lower.rs b/crates/hir_def/src/body/lower.rs index 3b3d74987..0f404be1b 100644 --- a/crates/hir_def/src/body/lower.rs +++ b/crates/hir_def/src/body/lower.rs @@ -963,7 +963,7 @@ impl ExprCollector<'_> { /// Returns `None` (and emits diagnostics) when `owner` if `#[cfg]`d out, and `Some(())` when /// not. fn check_cfg(&mut self, owner: &dyn ast::AttrsOwner) -> Option<()> { - match self.expander.parse_attrs(owner).cfg() { + match self.expander.parse_attrs(self.db, owner).cfg() { Some(cfg) => { if self.expander.cfg_options().check(&cfg) != Some(false) { return Some(()); diff --git a/crates/hir_def/src/data.rs b/crates/hir_def/src/data.rs index dd3a906af..e7b7724f7 100644 --- a/crates/hir_def/src/data.rs +++ b/crates/hir_def/src/data.rs @@ -35,6 +35,7 @@ pub struct FunctionData { impl FunctionData { pub(crate) fn fn_data_query(db: &dyn DefDatabase, func: FunctionId) -> Arc { let loc = func.lookup(db); + let krate = loc.container.module(db).krate; let item_tree = db.item_tree(loc.id.file_id); let func = &item_tree[loc.id.value]; @@ -42,7 +43,7 @@ impl FunctionData { name: func.name.clone(), params: func.params.to_vec(), ret_type: func.ret_type.clone(), - attrs: item_tree.attrs(ModItem::from(loc.id.value).into()).clone(), + attrs: item_tree.attrs(db, krate, ModItem::from(loc.id.value).into()).clone(), has_self_param: func.has_self_param, has_body: func.has_body, is_unsafe: func.is_unsafe, @@ -233,7 +234,7 @@ fn collect_items( match item { AssocItem::Function(id) => { let item = &item_tree[id]; - let attrs = item_tree.attrs(ModItem::from(id).into()); + let attrs = item_tree.attrs(db, module.krate, ModItem::from(id).into()); if !attrs.is_cfg_enabled(&cfg_options) { continue; } diff --git a/crates/hir_def/src/item_tree.rs b/crates/hir_def/src/item_tree.rs index b8e09e3af..5eb7cae7f 100644 --- a/crates/hir_def/src/item_tree.rs +++ b/crates/hir_def/src/item_tree.rs @@ -13,6 +13,7 @@ use std::{ use arena::{Arena, Idx, RawId}; use ast::{AstNode, AttrsOwner, NameOwner, StructKind}; +use base_db::CrateId; use either::Either; use hir_expand::{ ast_id_map::FileAstId, @@ -26,7 +27,7 @@ use syntax::{ast, match_ast}; use test_utils::mark; use crate::{ - attr::Attrs, + attr::{Attrs, RawAttrs}, db::DefDatabase, generics::GenericParams, path::{path, AssociatedTypeBinding, GenericArgs, ImportAlias, ModPath, Path, PathKind}, @@ -67,7 +68,7 @@ impl GenericParamsId { #[derive(Debug, Eq, PartialEq)] pub struct ItemTree { top_level: SmallVec<[ModItem; 1]>, - attrs: FxHashMap, + attrs: FxHashMap, inner_items: FxHashMap, SmallVec<[ModItem; 1]>>, data: Option>, @@ -88,7 +89,7 @@ impl ItemTree { let mut item_tree = match_ast! { match syntax { ast::SourceFile(file) => { - top_attrs = Some(Attrs::new(&file, &hygiene)); + top_attrs = Some(RawAttrs::new(&file, &hygiene)); ctx.lower_module_items(&file) }, ast::MacroItems(items) => { @@ -180,12 +181,16 @@ impl ItemTree { } /// Returns the inner attributes of the source file. - pub fn top_level_attrs(&self) -> &Attrs { - self.attrs.get(&AttrOwner::TopLevel).unwrap_or(&Attrs::EMPTY) + pub fn top_level_attrs(&self, db: &dyn DefDatabase, krate: CrateId) -> Attrs { + self.attrs.get(&AttrOwner::TopLevel).unwrap_or(&RawAttrs::EMPTY).clone().filter(db, krate) } - pub fn attrs(&self, of: AttrOwner) -> &Attrs { - self.attrs.get(&of).unwrap_or(&Attrs::EMPTY) + pub(crate) fn raw_attrs(&self, of: AttrOwner) -> &RawAttrs { + self.attrs.get(&of).unwrap_or(&RawAttrs::EMPTY) + } + + pub fn attrs(&self, db: &dyn DefDatabase, krate: CrateId, of: AttrOwner) -> Attrs { + self.raw_attrs(of).clone().filter(db, krate) } /// Returns the lowered inner items that `ast` corresponds to. diff --git a/crates/hir_def/src/item_tree/lower.rs b/crates/hir_def/src/item_tree/lower.rs index 7de385ee8..c8f090c22 100644 --- a/crates/hir_def/src/item_tree/lower.rs +++ b/crates/hir_def/src/item_tree/lower.rs @@ -10,7 +10,6 @@ use syntax::{ }; use crate::{ - attr::Attrs, generics::{GenericParams, TypeParamData, TypeParamProvenance}, type_ref::LifetimeRef, }; @@ -105,7 +104,7 @@ impl Ctx { | ast::Item::MacroDef(_) => {} }; - let attrs = Attrs::new(item, &self.hygiene); + let attrs = RawAttrs::new(item, &self.hygiene); let items = match item { ast::Item::Struct(ast) => self.lower_struct(ast).map(Into::into), ast::Item::Union(ast) => self.lower_union(ast).map(Into::into), @@ -138,7 +137,7 @@ impl Ctx { items } - fn add_attrs(&mut self, item: AttrOwner, attrs: Attrs) { + fn add_attrs(&mut self, item: AttrOwner, attrs: RawAttrs) { match self.tree.attrs.entry(item) { Entry::Occupied(mut entry) => { *entry.get_mut() = entry.get().merge(attrs); @@ -205,7 +204,7 @@ impl Ctx { for field in fields.fields() { if let Some(data) = self.lower_record_field(&field) { let idx = self.data().fields.alloc(data); - self.add_attrs(idx.into(), Attrs::new(&field, &self.hygiene)); + self.add_attrs(idx.into(), RawAttrs::new(&field, &self.hygiene)); } } let end = self.next_field_idx(); @@ -225,7 +224,7 @@ impl Ctx { for (i, field) in fields.fields().enumerate() { let data = self.lower_tuple_field(i, &field); let idx = self.data().fields.alloc(data); - self.add_attrs(idx.into(), Attrs::new(&field, &self.hygiene)); + self.add_attrs(idx.into(), RawAttrs::new(&field, &self.hygiene)); } let end = self.next_field_idx(); IdRange::new(start..end) @@ -270,7 +269,7 @@ impl Ctx { for variant in variants.variants() { if let Some(data) = self.lower_variant(&variant) { let idx = self.data().variants.alloc(data); - self.add_attrs(idx.into(), Attrs::new(&variant, &self.hygiene)); + self.add_attrs(idx.into(), RawAttrs::new(&variant, &self.hygiene)); } } let end = self.next_variant_idx(); @@ -438,7 +437,7 @@ impl Ctx { self.with_inherited_visibility(visibility, |this| { list.assoc_items() .filter_map(|item| { - let attrs = Attrs::new(&item, &this.hygiene); + let attrs = RawAttrs::new(&item, &this.hygiene); this.collect_inner_items(item.syntax()); this.lower_assoc_item(&item).map(|item| { this.add_attrs(ModItem::from(item).into(), attrs); @@ -475,7 +474,7 @@ impl Ctx { .filter_map(|item| { self.collect_inner_items(item.syntax()); let assoc = self.lower_assoc_item(&item)?; - let attrs = Attrs::new(&item, &self.hygiene); + let attrs = RawAttrs::new(&item, &self.hygiene); self.add_attrs(ModItem::from(assoc).into(), attrs); Some(assoc) }) @@ -560,7 +559,7 @@ impl Ctx { list.extern_items() .filter_map(|item| { self.collect_inner_items(item.syntax()); - let attrs = Attrs::new(&item, &self.hygiene); + let attrs = RawAttrs::new(&item, &self.hygiene); let id: ModItem = match item { ast::ExternItem::Fn(ast) => { let func_id = self.lower_function(&ast)?; diff --git a/crates/hir_def/src/nameres/collector.rs b/crates/hir_def/src/nameres/collector.rs index 1936348fb..b114a6fe4 100644 --- a/crates/hir_def/src/nameres/collector.rs +++ b/crates/hir_def/src/nameres/collector.rs @@ -221,17 +221,20 @@ impl DefCollector<'_> { let item_tree = self.db.item_tree(file_id.into()); let module_id = self.def_map.root; self.def_map.modules[module_id].origin = ModuleOrigin::CrateRoot { definition: file_id }; - let mut root_collector = ModCollector { - def_collector: &mut *self, - macro_depth: 0, - module_id, - file_id: file_id.into(), - item_tree: &item_tree, - mod_dir: ModDir::root(), - }; - if item_tree.top_level_attrs().cfg().map_or(true, |cfg| root_collector.is_cfg_enabled(&cfg)) + if item_tree + .top_level_attrs(self.db, self.def_map.krate) + .cfg() + .map_or(true, |cfg| self.cfg_options.check(&cfg) != Some(false)) { - root_collector.collect(item_tree.top_level_items()); + ModCollector { + def_collector: &mut *self, + macro_depth: 0, + module_id, + file_id: file_id.into(), + item_tree: &item_tree, + mod_dir: ModDir::root(), + } + .collect(item_tree.top_level_items()); } // main name resolution fixed-point loop. @@ -905,6 +908,8 @@ struct ModCollector<'a, 'b> { impl ModCollector<'_, '_> { fn collect(&mut self, items: &[ModItem]) { + let krate = self.def_collector.def_map.krate; + // Note: don't assert that inserted value is fresh: it's simply not true // for macros. self.def_collector.mod_dirs.insert(self.module_id, self.mod_dir.clone()); @@ -921,7 +926,7 @@ impl ModCollector<'_, '_> { // `#[macro_use] extern crate` is hoisted to imports macros before collecting // any other items. for item in items { - let attrs = self.item_tree.attrs((*item).into()); + let attrs = self.item_tree.attrs(self.def_collector.db, krate, (*item).into()); if attrs.cfg().map_or(true, |cfg| self.is_cfg_enabled(&cfg)) { if let ModItem::ExternCrate(id) = item { let import = self.item_tree[*id].clone(); @@ -933,7 +938,7 @@ impl ModCollector<'_, '_> { } for &item in items { - let attrs = self.item_tree.attrs(item.into()); + let attrs = self.item_tree.attrs(self.def_collector.db, krate, item.into()); if let Some(cfg) = attrs.cfg() { if !self.is_cfg_enabled(&cfg) { self.emit_unconfigured_diagnostic(item, &cfg); @@ -946,7 +951,7 @@ impl ModCollector<'_, '_> { let mut def = None; match item { - ModItem::Mod(m) => self.collect_module(&self.item_tree[m], attrs), + ModItem::Mod(m) => self.collect_module(&self.item_tree[m], &attrs), ModItem::Import(import_id) => { self.def_collector.unresolved_imports.push(ImportDirective { module_id: self.module_id, @@ -975,7 +980,11 @@ impl ModCollector<'_, '_> { // "Macro 2.0" is not currently supported by rust-analyzer, but libcore uses it // to define builtin macros, so we support at least that part. - let attrs = self.item_tree.attrs(ModItem::from(id).into()); + let attrs = self.item_tree.attrs( + self.def_collector.db, + krate, + ModItem::from(id).into(), + ); if attrs.by_key("rustc_builtin_macro").exists() { let krate = self.def_collector.def_map.krate; let macro_id = find_builtin_macro(&mac.name, krate, ast_id) @@ -1012,7 +1021,7 @@ impl ModCollector<'_, '_> { ModItem::Function(id) => { let func = &self.item_tree[id]; - self.collect_proc_macro_def(&func.name, attrs); + self.collect_proc_macro_def(&func.name, &attrs); def = Some(DefData { id: FunctionLoc { @@ -1032,7 +1041,7 @@ impl ModCollector<'_, '_> { // FIXME: check attrs to see if this is an attribute macro invocation; // in which case we don't add the invocation, just a single attribute // macro invocation - self.collect_derives(attrs, it.ast_id.upcast()); + self.collect_derives(&attrs, it.ast_id.upcast()); def = Some(DefData { id: StructLoc { container, id: ItemTreeId::new(self.file_id, id) } @@ -1049,7 +1058,7 @@ impl ModCollector<'_, '_> { // FIXME: check attrs to see if this is an attribute macro invocation; // in which case we don't add the invocation, just a single attribute // macro invocation - self.collect_derives(attrs, it.ast_id.upcast()); + self.collect_derives(&attrs, it.ast_id.upcast()); def = Some(DefData { id: UnionLoc { container, id: ItemTreeId::new(self.file_id, id) } @@ -1066,7 +1075,7 @@ impl ModCollector<'_, '_> { // FIXME: check attrs to see if this is an attribute macro invocation; // in which case we don't add the invocation, just a single attribute // macro invocation - self.collect_derives(attrs, it.ast_id.upcast()); + self.collect_derives(&attrs, it.ast_id.upcast()); def = Some(DefData { id: EnumLoc { container, id: ItemTreeId::new(self.file_id, id) } @@ -1303,8 +1312,9 @@ impl ModCollector<'_, '_> { } fn collect_macro_rules(&mut self, id: FileItemTreeId) { + let krate = self.def_collector.def_map.krate; let mac = &self.item_tree[id]; - let attrs = self.item_tree.attrs(ModItem::from(id).into()); + let attrs = self.item_tree.attrs(self.def_collector.db, krate, ModItem::from(id).into()); let ast_id = InFile::new(self.file_id, mac.ast_id.upcast()); let export_attr = attrs.by_key("macro_export"); -- cgit v1.2.3