Unnamed repository; edit this file 'description' to name the repository.
Auto merge of #13917 - Veykril:raw-attrs, r=Veykril
Split out hir-def attribute handling parts into hir-expand This should help with `cfg_attr` handling for macro inputs
bors 2023-01-11
parent 674b52a · parent 621e96b · commit c3b78f4
-rw-r--r--Cargo.lock13
-rw-r--r--crates/hir-def/Cargo.toml1
-rw-r--r--crates/hir-def/src/adt.rs2
-rw-r--r--crates/hir-def/src/attr.rs334
-rw-r--r--crates/hir-def/src/body.rs8
-rw-r--r--crates/hir-def/src/body/lower.rs2
-rw-r--r--crates/hir-def/src/child_by_source.rs2
-rw-r--r--crates/hir-def/src/data.rs2
-rw-r--r--crates/hir-def/src/db.rs2
-rw-r--r--crates/hir-def/src/expr.rs2
-rw-r--r--crates/hir-def/src/generics.rs2
-rw-r--r--crates/hir-def/src/item_scope.rs6
-rw-r--r--crates/hir-def/src/item_tree.rs15
-rw-r--r--crates/hir-def/src/item_tree/lower.rs24
-rw-r--r--crates/hir-def/src/item_tree/pretty.rs1
-rw-r--r--crates/hir-def/src/keys.rs3
-rw-r--r--crates/hir-def/src/lib.rs19
-rw-r--r--crates/hir-def/src/nameres/attr_resolution.rs3
-rw-r--r--crates/hir-def/src/nameres/collector.rs7
-rw-r--r--crates/hir-def/src/nameres/diagnostics.rs11
-rw-r--r--crates/hir-def/src/path.rs2
-rw-r--r--crates/hir-def/src/path/lower.rs3
-rw-r--r--crates/hir-def/src/pretty.rs2
-rw-r--r--crates/hir-def/src/resolver.rs2
-rw-r--r--crates/hir-def/src/type_ref.rs2
-rw-r--r--crates/hir-expand/Cargo.toml1
-rw-r--r--crates/hir-expand/src/attrs.rs346
-rw-r--r--crates/hir-expand/src/db.rs9
-rw-r--r--crates/hir-expand/src/hygiene.rs2
-rw-r--r--crates/hir-expand/src/lib.rs27
-rw-r--r--crates/hir-ty/Cargo.toml1
-rw-r--r--crates/hir-ty/src/display.rs2
-rw-r--r--crates/hir-ty/src/interner.rs7
-rw-r--r--crates/hir-ty/src/lower.rs2
-rw-r--r--crates/hir-ty/src/utils.rs2
-rw-r--r--crates/hir/src/lib.rs11
-rw-r--r--crates/hir/src/semantics/source_to_def.rs3
-rw-r--r--crates/intern/Cargo.toml18
-rw-r--r--crates/intern/src/lib.rs (renamed from crates/hir-def/src/intern.rs)19
39 files changed, 510 insertions, 410 deletions
diff --git a/Cargo.lock b/Cargo.lock
index d27ae416f0..5f426d8856 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -519,6 +519,7 @@ dependencies = [
"hkalbasi-rustc-ap-rustc_abi",
"hkalbasi-rustc-ap-rustc_index",
"indexmap",
+ "intern",
"itertools",
"la-arena",
"limit",
@@ -544,6 +545,7 @@ dependencies = [
"either",
"expect-test",
"hashbrown",
+ "intern",
"itertools",
"la-arena",
"limit",
@@ -574,6 +576,7 @@ dependencies = [
"hir-def",
"hir-expand",
"hkalbasi-rustc-ap-rustc_index",
+ "intern",
"itertools",
"la-arena",
"limit",
@@ -804,6 +807,16 @@ dependencies = [
]
[[package]]
+name = "intern"
+version = "0.0.0"
+dependencies = [
+ "dashmap",
+ "hashbrown",
+ "once_cell",
+ "rustc-hash",
+]
+
+[[package]]
name = "itertools"
version = "0.10.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
diff --git a/crates/hir-def/Cargo.toml b/crates/hir-def/Cargo.toml
index 698be76656..a107842770 100644
--- a/crates/hir-def/Cargo.toml
+++ b/crates/hir-def/Cargo.toml
@@ -29,6 +29,7 @@ smallvec = "1.10.0"
tracing = "0.1.35"
stdx = { path = "../stdx", version = "0.0.0" }
+intern = { path = "../intern", version = "0.0.0" }
base-db = { path = "../base-db", version = "0.0.0" }
syntax = { path = "../syntax", version = "0.0.0" }
profile = { path = "../profile", version = "0.0.0" }
diff --git a/crates/hir-def/src/adt.rs b/crates/hir-def/src/adt.rs
index db3b419488..cd35ba00f6 100644
--- a/crates/hir-def/src/adt.rs
+++ b/crates/hir-def/src/adt.rs
@@ -8,6 +8,7 @@ use hir_expand::{
name::{AsName, Name},
HirFileId, InFile,
};
+use intern::Interned;
use la_arena::{Arena, ArenaMap};
use rustc_abi::{Integer, IntegerType};
use syntax::ast::{self, HasName, HasVisibility};
@@ -17,7 +18,6 @@ use crate::{
body::{CfgExpander, LowerCtx},
builtin_type::{BuiltinInt, BuiltinUint},
db::DefDatabase,
- intern::Interned,
item_tree::{AttrOwner, Field, FieldAstId, Fields, ItemTree, ModItem, RawVisibilityId},
layout::{Align, ReprFlags, ReprOptions},
nameres::diagnostics::DefDiagnostic,
diff --git a/crates/hir-def/src/attr.rs b/crates/hir-def/src/attr.rs
index ab5d180e1b..a0113fd048 100644
--- a/crates/hir-def/src/attr.rs
+++ b/crates/hir-def/src/attr.rs
@@ -1,27 +1,27 @@
//! A higher level attributes based on TokenTree, with also some shortcuts.
-use std::{fmt, hash::Hash, ops, sync::Arc};
+use std::{hash::Hash, ops, sync::Arc};
use base_db::CrateId;
use cfg::{CfgExpr, CfgOptions};
use either::Either;
-use hir_expand::{hygiene::Hygiene, name::AsName, HirFileId, InFile};
+use hir_expand::{
+ attrs::{collect_attrs, Attr, AttrId, RawAttrs},
+ HirFileId, InFile,
+};
use itertools::Itertools;
use la_arena::{ArenaMap, Idx, RawIdx};
-use mbe::{syntax_node_to_token_tree, DelimiterKind, Punct};
-use smallvec::{smallvec, SmallVec};
+use mbe::DelimiterKind;
use syntax::{
- ast::{self, AstNode, HasAttrs, IsString},
- match_ast, AstPtr, AstToken, SmolStr, SyntaxNode, TextRange, TextSize,
+ ast::{self, HasAttrs, IsString},
+ AstPtr, AstToken, SmolStr, TextRange, TextSize,
};
use tt::Subtree;
use crate::{
db::DefDatabase,
- intern::Interned,
item_tree::{AttrOwner, Fields, ItemTreeId, ItemTreeNode},
nameres::{ModuleOrigin, ModuleSource},
- path::{ModPath, PathKind},
src::{HasChildSource, HasSource},
AdtId, AttrDefId, EnumId, GenericParamId, LocalEnumVariantId, LocalFieldId, Lookup, MacroId,
VariantId,
@@ -47,12 +47,6 @@ impl From<Documentation> for String {
}
}
-/// Syntactical attributes, without filtering of `cfg_attr`s.
-#[derive(Default, Debug, Clone, PartialEq, Eq)]
-pub(crate) struct RawAttrs {
- entries: Option<Arc<[Attr]>>,
-}
-
#[derive(Default, Debug, Clone, PartialEq, Eq)]
pub struct Attrs(RawAttrs);
@@ -62,30 +56,21 @@ pub struct AttrsWithOwner {
owner: AttrDefId,
}
-impl ops::Deref for RawAttrs {
- type Target = [Attr];
-
- fn deref(&self) -> &[Attr] {
- match &self.entries {
- Some(it) => &*it,
- None => &[],
- }
- }
-}
impl Attrs {
pub fn get(&self, id: AttrId) -> Option<&Attr> {
(**self).iter().find(|attr| attr.id == id)
}
+
+ pub(crate) fn filter(db: &dyn DefDatabase, krate: CrateId, raw_attrs: RawAttrs) -> Attrs {
+ Attrs(raw_attrs.filter(db.upcast(), krate))
+ }
}
impl ops::Deref for Attrs {
type Target = [Attr];
fn deref(&self) -> &[Attr] {
- match &self.0.entries {
- Some(it) => &*it,
- None => &[],
- }
+ &self.0
}
}
@@ -97,114 +82,6 @@ impl ops::Deref for AttrsWithOwner {
}
}
-impl RawAttrs {
- pub(crate) const EMPTY: Self = Self { entries: None };
-
- pub(crate) fn new(db: &dyn DefDatabase, owner: &dyn ast::HasAttrs, hygiene: &Hygiene) -> Self {
- let entries = collect_attrs(owner)
- .filter_map(|(id, attr)| match attr {
- Either::Left(attr) => {
- attr.meta().and_then(|meta| Attr::from_src(db, meta, hygiene, id))
- }
- Either::Right(comment) => comment.doc_comment().map(|doc| Attr {
- id,
- input: Some(Interned::new(AttrInput::Literal(SmolStr::new(doc)))),
- path: Interned::new(ModPath::from(hir_expand::name!(doc))),
- }),
- })
- .collect::<Arc<_>>();
-
- Self { entries: if entries.is_empty() { None } else { Some(entries) } }
- }
-
- fn from_attrs_owner(db: &dyn DefDatabase, owner: InFile<&dyn ast::HasAttrs>) -> Self {
- let hygiene = Hygiene::new(db.upcast(), owner.file_id);
- Self::new(db, owner.value, &hygiene)
- }
-
- pub(crate) fn merge(&self, other: Self) -> Self {
- // FIXME: This needs to fixup `AttrId`s
- match (&self.entries, other.entries) {
- (None, None) => Self::EMPTY,
- (None, entries @ Some(_)) => Self { entries },
- (Some(entries), None) => Self { entries: Some(entries.clone()) },
- (Some(a), Some(b)) => {
- let last_ast_index = a.last().map_or(0, |it| it.id.ast_index + 1);
- Self {
- entries: Some(
- a.iter()
- .cloned()
- .chain(b.iter().map(|it| {
- let mut it = it.clone();
- it.id.ast_index += last_ast_index;
- it
- }))
- .collect(),
- ),
- }
- }
- }
- }
-
- /// Processes `cfg_attr`s, returning the resulting semantic `Attrs`.
- pub(crate) fn filter(self, db: &dyn DefDatabase, krate: CrateId) -> Attrs {
- let has_cfg_attrs = self.iter().any(|attr| {
- attr.path.as_ident().map_or(false, |name| *name == hir_expand::name![cfg_attr])
- });
- if !has_cfg_attrs {
- return Attrs(self);
- }
-
- let crate_graph = db.crate_graph();
- let new_attrs = self
- .iter()
- .flat_map(|attr| -> SmallVec<[_; 1]> {
- let is_cfg_attr =
- attr.path.as_ident().map_or(false, |name| *name == hir_expand::name![cfg_attr]);
- if !is_cfg_attr {
- return smallvec![attr.clone()];
- }
-
- let subtree = match attr.token_tree_value() {
- Some(it) => it,
- _ => return smallvec![attr.clone()],
- };
-
- // Input subtree is: `(cfg, $(attr),+)`
- // Split it up into a `cfg` subtree and the `attr` subtrees.
- // FIXME: There should be a common API for this.
- let mut parts = subtree.token_trees.split(|tt| {
- matches!(tt, tt::TokenTree::Leaf(tt::Leaf::Punct(Punct { char: ',', .. })))
- });
- let cfg = match parts.next() {
- Some(it) => it,
- None => return smallvec![],
- };
- let cfg = Subtree { delimiter: subtree.delimiter, token_trees: cfg.to_vec() };
- let cfg = CfgExpr::parse(&cfg);
- let index = attr.id;
- let attrs = parts.filter(|a| !a.is_empty()).filter_map(|attr| {
- let tree = Subtree { delimiter: None, token_trees: attr.to_vec() };
- // FIXME hygiene
- let hygiene = Hygiene::new_unhygienic();
- Attr::from_tt(db, &tree, &hygiene, index)
- });
-
- let cfg_options = &crate_graph[krate].cfg_options;
- if cfg_options.check(&cfg) == Some(false) {
- smallvec![]
- } else {
- cov_mark::hit!(cfg_attr_active);
-
- attrs.collect()
- }
- })
- .collect();
-
- Attrs(RawAttrs { entries: Some(new_attrs) })
- }
-}
-
impl Attrs {
pub const EMPTY: Self = Self(RawAttrs::EMPTY);
@@ -403,7 +280,7 @@ impl AttrsWithOwner {
.raw_attrs(AttrOwner::ModItem(definition_tree_id.value.into()))
.clone(),
ModuleOrigin::BlockExpr { block } => RawAttrs::from_attrs_owner(
- db,
+ db.upcast(),
InFile::new(block.file_id, block.to_node(db.upcast()))
.as_ref()
.map(|it| it as &dyn ast::HasAttrs),
@@ -439,7 +316,7 @@ impl AttrsWithOwner {
GenericParamId::ConstParamId(it) => {
let src = it.parent().child_source(db);
RawAttrs::from_attrs_owner(
- db,
+ db.upcast(),
src.with_value(src.value[it.local_id()].as_ref().either(
|it| match it {
ast::TypeOrConstParam::Type(it) => it as _,
@@ -452,7 +329,7 @@ impl AttrsWithOwner {
GenericParamId::TypeParamId(it) => {
let src = it.parent().child_source(db);
RawAttrs::from_attrs_owner(
- db,
+ db.upcast(),
src.with_value(src.value[it.local_id()].as_ref().either(
|it| match it {
ast::TypeOrConstParam::Type(it) => it as _,
@@ -464,14 +341,14 @@ impl AttrsWithOwner {
}
GenericParamId::LifetimeParamId(it) => {
let src = it.parent.child_source(db);
- RawAttrs::from_attrs_owner(db, src.with_value(&src.value[it.local_id]))
+ RawAttrs::from_attrs_owner(db.upcast(), src.with_value(&src.value[it.local_id]))
}
},
AttrDefId::ExternBlockId(it) => attrs_from_item_tree(it.lookup(db).id, db),
};
- let attrs = raw_attrs.filter(db, def.krate(db));
- Self { attrs, owner: def }
+ let attrs = raw_attrs.filter(db.upcast(), def.krate(db));
+ Self { attrs: Attrs(attrs), owner: def }
}
pub fn source_map(&self, db: &dyn DefDatabase) -> AttrSourceMap {
@@ -627,40 +504,6 @@ fn doc_indent(attrs: &Attrs) -> usize {
.unwrap_or(0)
}
-fn inner_attributes(
- syntax: &SyntaxNode,
-) -> Option<impl Iterator<Item = Either<ast::Attr, ast::Comment>>> {
- let node = match_ast! {
- match syntax {
- ast::SourceFile(_) => syntax.clone(),
- ast::ExternBlock(it) => it.extern_item_list()?.syntax().clone(),
- ast::Fn(it) => it.body()?.stmt_list()?.syntax().clone(),
- ast::Impl(it) => it.assoc_item_list()?.syntax().clone(),
- ast::Module(it) => it.item_list()?.syntax().clone(),
- ast::BlockExpr(it) => {
- use syntax::SyntaxKind::{BLOCK_EXPR , EXPR_STMT};
- // Block expressions accept outer and inner attributes, but only when they are the outer
- // expression of an expression statement or the final expression of another block expression.
- let may_carry_attributes = matches!(
- it.syntax().parent().map(|it| it.kind()),
- Some(BLOCK_EXPR | EXPR_STMT)
- );
- if !may_carry_attributes {
- return None
- }
- syntax.clone()
- },
- _ => return None,
- }
- };
-
- let attrs = ast::AttrDocCommentIter::from_syntax_node(&node).filter(|el| match el {
- Either::Left(attr) => attr.kind().is_inner(),
- Either::Right(comment) => comment.is_inner(),
- });
- Some(attrs)
-}
-
#[derive(Debug)]
pub struct AttrSourceMap {
source: Vec<Either<ast::Attr, ast::Comment>>,
@@ -703,7 +546,7 @@ impl AttrSourceMap {
}
fn source_of_id(&self, id: AttrId) -> InFile<&Either<ast::Attr, ast::Comment>> {
- let ast_idx = id.ast_index as usize;
+ let ast_idx = id.ast_index();
let file_id = match self.mod_def_site_file_id {
Some((file_id, def_site_cut)) if def_site_cut <= ast_idx => file_id,
_ => self.file_id,
@@ -779,128 +622,6 @@ fn get_doc_string_in_attr(it: &ast::Attr) -> Option<ast::String> {
}
}
-#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
-pub struct AttrId {
- pub(crate) ast_index: u32,
-}
-
-#[derive(Debug, Clone, PartialEq, Eq)]
-pub struct Attr {
- pub(crate) id: AttrId,
- pub(crate) path: Interned<ModPath>,
- pub(crate) input: Option<Interned<AttrInput>>,
-}
-
-#[derive(Debug, Clone, PartialEq, Eq, Hash)]
-pub enum AttrInput {
- /// `#[attr = "string"]`
- Literal(SmolStr),
- /// `#[attr(subtree)]`
- TokenTree(tt::Subtree, mbe::TokenMap),
-}
-
-impl fmt::Display for AttrInput {
- fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
- match self {
- AttrInput::Literal(lit) => write!(f, " = \"{}\"", lit.escape_debug()),
- AttrInput::TokenTree(subtree, _) => subtree.fmt(f),
- }
- }
-}
-
-impl Attr {
- fn from_src(
- db: &dyn DefDatabase,
- ast: ast::Meta,
- hygiene: &Hygiene,
- id: AttrId,
- ) -> Option<Attr> {
- let path = Interned::new(ModPath::from_src(db.upcast(), ast.path()?, hygiene)?);
- let input = if let Some(ast::Expr::Literal(lit)) = ast.expr() {
- let value = match lit.kind() {
- ast::LiteralKind::String(string) => string.value()?.into(),
- _ => lit.syntax().first_token()?.text().trim_matches('"').into(),
- };
- Some(Interned::new(AttrInput::Literal(value)))
- } else if let Some(tt) = ast.token_tree() {
- let (tree, map) = syntax_node_to_token_tree(tt.syntax());
- Some(Interned::new(AttrInput::TokenTree(tree, map)))
- } else {
- None
- };
- Some(Attr { id, path, input })
- }
-
- fn from_tt(
- db: &dyn DefDatabase,
- tt: &tt::Subtree,
- hygiene: &Hygiene,
- id: AttrId,
- ) -> Option<Attr> {
- let (parse, _) = mbe::token_tree_to_syntax_node(tt, mbe::TopEntryPoint::MetaItem);
- let ast = ast::Meta::cast(parse.syntax_node())?;
-
- Self::from_src(db, ast, hygiene, id)
- }
-
- pub fn path(&self) -> &ModPath {
- &self.path
- }
-}
-
-impl Attr {
- /// #[path = "string"]
- pub fn string_value(&self) -> Option<&SmolStr> {
- match self.input.as_deref()? {
- AttrInput::Literal(it) => Some(it),
- _ => None,
- }
- }
-
- /// #[path(ident)]
- pub fn single_ident_value(&self) -> Option<&tt::Ident> {
- match self.input.as_deref()? {
- AttrInput::TokenTree(subtree, _) => match &*subtree.token_trees {
- [tt::TokenTree::Leaf(tt::Leaf::Ident(ident))] => Some(ident),
- _ => None,
- },
- _ => None,
- }
- }
-
- /// #[path TokenTree]
- pub fn token_tree_value(&self) -> Option<&Subtree> {
- match self.input.as_deref()? {
- AttrInput::TokenTree(subtree, _) => Some(subtree),
- _ => None,
- }
- }
-
- /// Parses this attribute as a token tree consisting of comma separated paths.
- pub fn parse_path_comma_token_tree(&self) -> Option<impl Iterator<Item = ModPath> + '_> {
- let args = self.token_tree_value()?;
-
- if args.delimiter_kind() != Some(DelimiterKind::Parenthesis) {
- return None;
- }
- let paths = args
- .token_trees
- .split(|tt| matches!(tt, tt::TokenTree::Leaf(tt::Leaf::Punct(Punct { char: ',', .. }))))
- .filter_map(|tts| {
- if tts.is_empty() {
- return None;
- }
- let segments = tts.iter().filter_map(|tt| match tt {
- tt::TokenTree::Leaf(tt::Leaf::Ident(id)) => Some(id.as_name()),
- _ => None,
- });
- Some(ModPath::from_segments(PathKind::Plain, segments))
- });
-
- Some(paths)
- }
-}
-
#[derive(Debug, Clone, Copy)]
pub struct AttrQuery<'attr> {
attrs: &'attr Attrs,
@@ -953,21 +674,6 @@ fn attrs_from_item_tree<N: ItemTreeNode>(id: ItemTreeId<N>, db: &dyn DefDatabase
tree.raw_attrs(mod_item.into()).clone()
}
-fn collect_attrs(
- owner: &dyn ast::HasAttrs,
-) -> impl Iterator<Item = (AttrId, Either<ast::Attr, ast::Comment>)> {
- let inner_attrs = inner_attributes(owner.syntax()).into_iter().flatten();
- let outer_attrs =
- ast::AttrDocCommentIter::from_syntax_node(owner.syntax()).filter(|el| match el {
- Either::Left(attr) => attr.kind().is_outer(),
- Either::Right(comment) => comment.is_outer(),
- });
- outer_attrs
- .chain(inner_attrs)
- .enumerate()
- .map(|(id, attr)| (AttrId { ast_index: id as u32 }, attr))
-}
-
pub(crate) fn variants_attrs_source_map(
db: &dyn DefDatabase,
def: EnumId,
diff --git a/crates/hir-def/src/body.rs b/crates/hir-def/src/body.rs
index 78fbaa9d7d..9713256813 100644
--- a/crates/hir-def/src/body.rs
+++ b/crates/hir-def/src/body.rs
@@ -12,7 +12,9 @@ use base_db::CrateId;
use cfg::{CfgExpr, CfgOptions};
use drop_bomb::DropBomb;
use either::Either;
-use hir_expand::{hygiene::Hygiene, ExpandError, ExpandResult, HirFileId, InFile, MacroCallId};
+use hir_expand::{
+ attrs::RawAttrs, hygiene::Hygiene, ExpandError, ExpandResult, HirFileId, InFile, MacroCallId,
+};
use la_arena::{Arena, ArenaMap};
use limit::Limit;
use profile::Count;
@@ -20,7 +22,7 @@ use rustc_hash::FxHashMap;
use syntax::{ast, AstPtr, SyntaxNodePtr};
use crate::{
- attr::{Attrs, RawAttrs},
+ attr::Attrs,
db::DefDatabase,
expr::{dummy_expr_id, Expr, ExprId, Label, LabelId, Pat, PatId},
item_scope::BuiltinShadowMode,
@@ -64,7 +66,7 @@ impl CfgExpander {
}
pub(crate) fn parse_attrs(&self, db: &dyn DefDatabase, owner: &dyn ast::HasAttrs) -> Attrs {
- RawAttrs::new(db, owner, &self.hygiene).filter(db, self.krate)
+ Attrs::filter(db, self.krate, RawAttrs::new(db.upcast(), owner, &self.hygiene))
}
pub(crate) fn is_cfg_enabled(&self, db: &dyn DefDatabase, owner: &dyn ast::HasAttrs) -> bool {
diff --git a/crates/hir-def/src/body/lower.rs b/crates/hir-def/src/body/lower.rs
index e8da24e3ad..4c29e16b2b 100644
--- a/crates/hir-def/src/body/lower.rs
+++ b/crates/hir-def/src/body/lower.rs
@@ -10,6 +10,7 @@ use hir_expand::{
name::{name, AsName, Name},
AstId, ExpandError, HirFileId, InFile,
};
+use intern::Interned;
use la_arena::Arena;
use once_cell::unsync::OnceCell;
use profile::Count;
@@ -33,7 +34,6 @@ use crate::{
Label, LabelId, Literal, MatchArm, Movability, Pat, PatId, RecordFieldPat, RecordLitField,
Statement,
},
- intern::Interned,
item_scope::BuiltinShadowMode,
path::{GenericArgs, Path},
type_ref::{Mutability, Rawness, TypeRef},
diff --git a/crates/hir-def/src/child_by_source.rs b/crates/hir-def/src/child_by_source.rs
index bb13165257..19d2fe956f 100644
--- a/crates/hir-def/src/child_by_source.rs
+++ b/crates/hir-def/src/child_by_source.rs
@@ -117,7 +117,7 @@ impl ChildBySource for ItemScope {
let adt = ast_id.to_node(db.upcast());
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)
+ adt.doc_comments_and_attrs().nth(attr_id.ast_index())
{
res[keys::DERIVE_MACRO_CALL].insert(attr, (attr_id, call_id, calls.into()));
}
diff --git a/crates/hir-def/src/data.rs b/crates/hir-def/src/data.rs
index e6b05f27a5..f461e85b01 100644
--- a/crates/hir-def/src/data.rs
+++ b/crates/hir-def/src/data.rs
@@ -3,6 +3,7 @@
use std::sync::Arc;
use hir_expand::{name::Name, AstId, ExpandResult, HirFileId, InFile, MacroCallId, MacroDefKind};
+use intern::Interned;
use smallvec::SmallVec;
use syntax::ast;
@@ -10,7 +11,6 @@ use crate::{
attr::Attrs,
body::{Expander, Mark},
db::DefDatabase,
- intern::Interned,
item_tree::{self, AssocItem, FnFlags, ItemTree, ItemTreeId, ModItem, Param, TreeId},
nameres::{
attr_resolution::ResolvedAttr,
diff --git a/crates/hir-def/src/db.rs b/crates/hir-def/src/db.rs
index 431c825549..65cdd1b69b 100644
--- a/crates/hir-def/src/db.rs
+++ b/crates/hir-def/src/db.rs
@@ -4,6 +4,7 @@ use std::sync::Arc;
use base_db::{salsa, CrateId, SourceDatabase, Upcast};
use either::Either;
use hir_expand::{db::AstDatabase, HirFileId};
+use intern::Interned;
use la_arena::ArenaMap;
use syntax::{ast, AstPtr, SmolStr};
@@ -17,7 +18,6 @@ use crate::{
},
generics::GenericParams,
import_map::ImportMap,
- intern::Interned,
item_tree::{AttrOwner, ItemTree},
lang_item::{LangItemTarget, LangItems},
nameres::{diagnostics::DefDiagnostic, DefMap},
diff --git a/crates/hir-def/src/expr.rs b/crates/hir-def/src/expr.rs
index 7b65694211..48028b7c6a 100644
--- a/crates/hir-def/src/expr.rs
+++ b/crates/hir-def/src/expr.rs
@@ -15,11 +15,11 @@
use std::fmt;
use hir_expand::name::Name;
+use intern::Interned;
use la_arena::{Idx, RawIdx};
use crate::{
builtin_type::{BuiltinFloat, BuiltinInt, BuiltinUint},
- intern::Interned,
path::{GenericArgs, Path},
type_ref::{Mutability, Rawness, TypeRef},
BlockId,
diff --git a/crates/hir-def/src/generics.rs b/crates/hir-def/src/generics.rs
index f74559f5d6..b2ab0c30e0 100644
--- a/crates/hir-def/src/generics.rs
+++ b/crates/hir-def/src/generics.rs
@@ -9,6 +9,7 @@ use hir_expand::{
name::{AsName, Name},
ExpandResult, HirFileId, InFile,
};
+use intern::Interned;
use la_arena::{Arena, ArenaMap, Idx};
use once_cell::unsync::Lazy;
use std::ops::DerefMut;
@@ -20,7 +21,6 @@ use crate::{
child_by_source::ChildBySource,
db::DefDatabase,
dyn_map::DynMap,
- intern::Interned,
keys,
src::{HasChildSource, HasSource},
type_ref::{LifetimeRef, TypeBound, TypeRef},
diff --git a/crates/hir-def/src/item_scope.rs b/crates/hir-def/src/item_scope.rs
index c7b213b7e9..53a4173ff4 100644
--- a/crates/hir-def/src/item_scope.rs
+++ b/crates/hir-def/src/item_scope.rs
@@ -4,7 +4,7 @@
use std::collections::hash_map::Entry;
use base_db::CrateId;
-use hir_expand::{name::Name, AstId, MacroCallId};
+use hir_expand::{attrs::AttrId, name::Name, AstId, MacroCallId};
use itertools::Itertools;
use once_cell::sync::Lazy;
use profile::Count;
@@ -14,8 +14,8 @@ use stdx::format_to;
use syntax::ast;
use crate::{
- attr::AttrId, db::DefDatabase, per_ns::PerNs, visibility::Visibility, AdtId, BuiltinType,
- ConstId, HasModule, ImplId, LocalModuleId, MacroId, ModuleDefId, ModuleId, TraitId,
+ db::DefDatabase, per_ns::PerNs, visibility::Visibility, AdtId, BuiltinType, ConstId, HasModule,
+ ImplId, LocalModuleId, MacroId, ModuleDefId, ModuleId, TraitId,
};
#[derive(Copy, Clone, Debug)]
diff --git a/crates/hir-def/src/item_tree.rs b/crates/hir-def/src/item_tree.rs
index 80297f8adf..3e1f7d4446 100644
--- a/crates/hir-def/src/item_tree.rs
+++ b/crates/hir-def/src/item_tree.rs
@@ -48,10 +48,12 @@ use base_db::CrateId;
use either::Either;
use hir_expand::{
ast_id_map::FileAstId,
+ attrs::RawAttrs,
hygiene::Hygiene,
name::{name, AsName, Name},
ExpandTo, HirFileId, InFile,
};
+use intern::Interned;
use la_arena::{Arena, Idx, IdxRange, RawIdx};
use profile::Count;
use rustc_hash::FxHashMap;
@@ -60,10 +62,9 @@ use stdx::never;
use syntax::{ast, match_ast, SyntaxKind};
use crate::{
- attr::{Attrs, RawAttrs},
+ attr::Attrs,
db::DefDatabase,
generics::GenericParams,
- intern::Interned,
path::{path, AssociatedTypeBinding, GenericArgs, ImportAlias, ModPath, Path, PathKind},
type_ref::{Mutability, TraitRef, TypeBound, TypeRef},
visibility::RawVisibility,
@@ -120,7 +121,7 @@ impl ItemTree {
let mut item_tree = match_ast! {
match syntax {
ast::SourceFile(file) => {
- top_attrs = Some(RawAttrs::new(db, &file, ctx.hygiene()));
+ top_attrs = Some(RawAttrs::new(db.upcast(), &file, ctx.hygiene()));
ctx.lower_module_items(&file)
},
ast::MacroItems(items) => {
@@ -152,7 +153,11 @@ impl ItemTree {
/// Returns the inner attributes of the source file.
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)
+ Attrs::filter(
+ db,
+ krate,
+ self.attrs.get(&AttrOwner::TopLevel).unwrap_or(&RawAttrs::EMPTY).clone(),
+ )
}
pub(crate) fn raw_attrs(&self, of: AttrOwner) -> &RawAttrs {
@@ -160,7 +165,7 @@ impl ItemTree {
}
pub(crate) fn attrs(&self, db: &dyn DefDatabase, krate: CrateId, of: AttrOwner) -> Attrs {
- self.raw_attrs(of).clone().filter(db, krate)
+ Attrs::filter(db, krate, self.raw_attrs(of).clone())
}
pub fn pretty_print(&self) -> String {
diff --git a/crates/hir-def/src/item_tree/lower.rs b/crates/hir-def/src/item_tree/lower.rs
index b25274bccc..27705cbbbd 100644
--- a/crates/hir-def/src/item_tree/lower.rs
+++ b/crates/hir-def/src/item_tree/lower.rs
@@ -99,7 +99,7 @@ impl<'a> Ctx<'a> {
}
fn lower_mod_item(&mut self, item: &ast::Item) -> Option<ModItem> {
- let attrs = RawAttrs::new(self.db, item, self.hygiene());
+ let attrs = RawAttrs::new(self.db.upcast(), item, self.hygiene());
let item: ModItem = match item {
ast::Item::Struct(ast) => self.lower_struct(ast)?.into(),
ast::Item::Union(ast) => self.lower_union(ast)?.into(),
@@ -173,7 +173,7 @@ impl<'a> Ctx<'a> {
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(), RawAttrs::new(self.db, &field, self.hygiene()));
+ self.add_attrs(idx.into(), RawAttrs::new(self.db.upcast(), &field, self.hygiene()));
}
}
let end = self.next_field_idx();
@@ -194,7 +194,7 @@ impl<'a> Ctx<'a> {
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(), RawAttrs::new(self.db, &field, self.hygiene()));
+ self.add_attrs(idx.into(), RawAttrs::new(self.db.upcast(), &field, self.hygiene()));
}
let end = self.next_field_idx();
IdxRange::new(start..end)
@@ -239,7 +239,10 @@ impl<'a> Ctx<'a> {
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(), RawAttrs::new(self.db, &variant, self.hygiene()));
+ self.add_attrs(
+ idx.into(),
+ RawAttrs::new(self.db.upcast(), &variant, self.hygiene()),
+ );
}
}
let end = self.next_variant_idx();
@@ -283,7 +286,10 @@ impl<'a> Ctx<'a> {
};
let ty = Interned::new(self_type);
let idx = self.data().params.alloc(Param::Normal(None, ty));
- self.add_attrs(idx.into(), RawAttrs::new(self.db, &self_param, self.hygiene()));
+ self.add_attrs(
+ idx.into(),
+ RawAttrs::new(self.db.upcast(), &self_param, self.hygiene()),
+ );
has_self_param = true;
}
for param in param_list.params() {
@@ -307,7 +313,7 @@ impl<'a> Ctx<'a> {
self.data().params.alloc(Param::Normal(name, ty))
}
};
- self.add_attrs(idx.into(), RawAttrs::new(self.db, &param, self.hygiene()));
+ self.add_attrs(idx.into(), RawAttrs::new(self.db.upcast(), &param, self.hygiene()));
}
}
let end_param = self.next_param_idx();
@@ -442,7 +448,7 @@ impl<'a> Ctx<'a> {
let items = trait_def.assoc_item_list().map(|list| {
list.assoc_items()
.filter_map(|item| {
- let attrs = RawAttrs::new(self.db, &item, self.hygiene());
+ let attrs = RawAttrs::new(self.db.upcast(), &item, self.hygiene());
self.lower_assoc_item(&item).map(|item| {
self.add_attrs(ModItem::from(item).into(), attrs);
item
@@ -471,7 +477,7 @@ impl<'a> Ctx<'a> {
.flat_map(|it| it.assoc_items())
.filter_map(|item| {
let assoc = self.lower_assoc_item(&item)?;
- let attrs = RawAttrs::new(self.db, &item, self.hygiene());
+ let attrs = RawAttrs::new(self.db.upcast(), &item, self.hygiene());
self.add_attrs(ModItem::from(assoc).into(), attrs);
Some(assoc)
})
@@ -541,7 +547,7 @@ impl<'a> Ctx<'a> {
// (in other words, the knowledge that they're in an extern block must not be used).
// This is because an extern block can contain macros whose ItemTree's top-level items
// should be considered to be in an extern block too.
- let attrs = RawAttrs::new(self.db, &item, self.hygiene());
+ let attrs = RawAttrs::new(self.db.upcast(), &item, self.hygiene());
let id: ModItem = match item {
ast::ExternItem::Fn(ast) => self.lower_function(&ast)?.into(),
ast::ExternItem::Static(ast) => self.lower_static(&ast)?.into(),
diff --git a/crates/hir-def/src/item_tree/pretty.rs b/crates/hir-def/src/item_tree/pretty.rs
index 48c40df22f..8f230b87d0 100644
--- a/crates/hir-def/src/item_tree/pretty.rs
+++ b/crates/hir-def/src/item_tree/pretty.rs
@@ -3,7 +3,6 @@
use std::fmt::{self, Write};
use crate::{
- attr::RawAttrs,
generics::{TypeOrConstParamData, WherePredicate, WherePredicateTypeTarget},
pretty::{print_path, print_type_bounds, print_type_ref},
visibility::RawVisibility,
diff --git a/crates/hir-def/src/keys.rs b/crates/hir-def/src/keys.rs
index c5cb9a2af5..72beec8186 100644
--- a/crates/hir-def/src/keys.rs
+++ b/crates/hir-def/src/keys.rs
@@ -2,12 +2,11 @@
use std::marker::PhantomData;
-use hir_expand::MacroCallId;
+use hir_expand::{attrs::AttrId, MacroCallId};
use rustc_hash::FxHashMap;
use syntax::{ast, AstNode, AstPtr};
use crate::{
- attr::AttrId,
dyn_map::{DynMap, Policy},
ConstId, EnumId, EnumVariantId, FieldId, FunctionId, ImplId, LifetimeParamId, Macro2Id,
MacroRulesId, ProcMacroId, StaticId, StructId, TraitId, TypeAliasId, TypeOrConstParamId,
diff --git a/crates/hir-def/src/lib.rs b/crates/hir-def/src/lib.rs
index 8267ef09cb..8eae2e92f4 100644
--- a/crates/hir-def/src/lib.rs
+++ b/crates/hir-def/src/lib.rs
@@ -28,7 +28,6 @@ pub mod dyn_map;
pub mod keys;
pub mod item_tree;
-pub mod intern;
pub mod adt;
pub mod data;
@@ -61,10 +60,10 @@ use std::{
sync::Arc,
};
-use attr::Attr;
use base_db::{impl_intern_key, salsa, CrateId, ProcMacroKind};
use hir_expand::{
ast_id_map::FileAstId,
+ attrs::{Attr, AttrId, AttrInput},
builtin_attr_macro::BuiltinAttrExpander,
builtin_derive_macro::BuiltinDeriveExpander,
builtin_fn_macro::{BuiltinFnLikeExpander, EagerExpander},
@@ -82,7 +81,6 @@ use syntax::ast;
use crate::{
adt::VariantData,
- attr::AttrId,
builtin_type::BuiltinType,
item_tree::{
Const, Enum, Function, Impl, ItemTreeId, ItemTreeNode, MacroDef, MacroRules, ModItem,
@@ -943,7 +941,7 @@ pub fn macro_id_to_def_id(db: &dyn db::DefDatabase, id: MacroId) -> MacroDefId {
fn derive_macro_as_call_id(
db: &dyn db::DefDatabase,
item_attr: &AstIdWithPath<ast::Adt>,
- derive_attr: AttrId,
+ derive_attr_index: AttrId,
derive_pos: u32,
krate: CrateId,
resolver: impl Fn(path::ModPath) -> Option<(MacroId, MacroDefId)>,
@@ -956,7 +954,7 @@ fn derive_macro_as_call_id(
MacroCallKind::Derive {
ast_id: item_attr.ast_id,
derive_index: derive_pos,
- derive_attr_index: derive_attr.ast_index,
+ derive_attr_index,
},
);
Ok((macro_id, def_id, call_id))
@@ -971,7 +969,7 @@ fn attr_macro_as_call_id(
is_derive: bool,
) -> MacroCallId {
let mut arg = match macro_attr.input.as_deref() {
- Some(attr::AttrInput::TokenTree(tt, map)) => (tt.clone(), map.clone()),
+ Some(AttrInput::TokenTree(tt, map)) => (tt.clone(), map.clone()),
_ => Default::default(),
};
@@ -984,9 +982,16 @@ fn attr_macro_as_call_id(
MacroCallKind::Attr {
ast_id: item_attr.ast_id,
attr_args: Arc::new(arg),
- invoc_attr_index: macro_attr.id.ast_index,
+ invoc_attr_index: macro_attr.id,
is_derive,
},
);
res
}
+intern::impl_internable!(
+ crate::type_ref::TypeRef,
+ crate::type_ref::TraitRef,
+ crate::type_ref::TypeBound,
+ crate::path::GenericArgs,
+ generics::GenericParams,
+);
diff --git a/crates/hir-def/src/nameres/attr_resolution.rs b/crates/hir-def/src/nameres/attr_resolution.rs
index 3650204ee9..79cabeb0fb 100644
--- a/crates/hir-def/src/nameres/attr_resolution.rs
+++ b/crates/hir-def/src/nameres/attr_resolution.rs
@@ -1,10 +1,9 @@
//! Post-nameres attribute resolution.
-use hir_expand::MacroCallId;
+use hir_expand::{attrs::Attr, MacroCallId};
use syntax::{ast, SmolStr};
use crate::{
- attr::Attr,
attr_macro_as_call_id, builtin_attr,
db::DefDatabase,
item_scope::BuiltinShadowMode,
diff --git a/crates/hir-def/src/nameres/collector.rs b/crates/hir-def/src/nameres/collector.rs
index 160203b778..33a787fd9f 100644
--- a/crates/hir-def/src/nameres/collector.rs
+++ b/crates/hir-def/src/nameres/collector.rs
@@ -10,6 +10,7 @@ use cfg::{CfgExpr, CfgOptions};
use either::Either;
use hir_expand::{
ast_id_map::FileAstId,
+ attrs::{Attr, AttrId},
builtin_attr_macro::find_builtin_attr,
builtin_derive_macro::find_builtin_derive,
builtin_fn_macro::find_builtin_macro,
@@ -26,7 +27,7 @@ use stdx::always;
use syntax::{ast, SmolStr};
use crate::{
- attr::{Attr, AttrId, Attrs},
+ attr::Attrs,
attr_macro_as_call_id,
db::DefDatabase,
derive_macro_as_call_id,
@@ -451,7 +452,7 @@ impl DefCollector<'_> {
MacroCallKind::Attr {
ast_id: ast_id.ast_id,
attr_args: Default::default(),
- invoc_attr_index: attr.id.ast_index,
+ invoc_attr_index: attr.id,
is_derive: false,
},
attr.path().clone(),
@@ -1406,7 +1407,7 @@ impl DefCollector<'_> {
directive.module_id,
MacroCallKind::Derive {
ast_id: ast_id.ast_id,
- derive_attr_index: derive_attr.ast_index,
+ derive_attr_index: *derive_attr,
derive_index: *derive_pos as u32,
},
ast_id.path.clone(),
diff --git a/crates/hir-def/src/nameres/diagnostics.rs b/crates/hir-def/src/nameres/diagnostics.rs
index 0661422919..b024d7c677 100644
--- a/crates/hir-def/src/nameres/diagnostics.rs
+++ b/crates/hir-def/src/nameres/diagnostics.rs
@@ -2,12 +2,11 @@
use base_db::CrateId;
use cfg::{CfgExpr, CfgOptions};
-use hir_expand::MacroCallKind;
+use hir_expand::{attrs::AttrId, MacroCallKind};
use la_arena::Idx;
use syntax::ast::{self, AnyHasAttrs};
use crate::{
- attr::AttrId,
item_tree::{self, ItemTreeId},
nameres::LocalModuleId,
path::ModPath,
@@ -32,9 +31,9 @@ pub enum DefDiagnosticKind {
UnimplementedBuiltinMacro { ast: AstId<ast::Macro> },
- InvalidDeriveTarget { ast: AstId<ast::Item>, id: u32 },
+ InvalidDeriveTarget { ast: AstId<ast::Item>, id: usize },
- MalformedDerive { ast: AstId<ast::Adt>, id: u32 },
+ MalformedDerive { ast: AstId<ast::Adt>, id: usize },
}
#[derive(Debug, PartialEq, Eq)]
@@ -120,7 +119,7 @@ impl DefDiagnostic {
) -> Self {
Self {
in_module: container,
- kind: DefDiagnosticKind::InvalidDeriveTarget { ast, id: id.ast_index },
+ kind: DefDiagnosticKind::InvalidDeriveTarget { ast, id: id.ast_index() },
}
}
@@ -131,7 +130,7 @@ impl DefDiagnostic {
) -> Self {
Self {
in_module: container,
- kind: DefDiagnosticKind::MalformedDerive { ast, id: id.ast_index },
+ kind: DefDiagnosticKind::MalformedDerive { ast, id: id.ast_index() },
}
}
}
diff --git a/crates/hir-def/src/path.rs b/crates/hir-def/src/path.rs
index 592223f7d8..25a23fcd61 100644
--- a/crates/hir-def/src/path.rs
+++ b/crates/hir-def/src/path.rs
@@ -8,10 +8,10 @@ use std::{
use crate::{
body::LowerCtx,
- intern::Interned,
type_ref::{ConstScalarOrPath, LifetimeRef},
};
use hir_expand::name::Name;
+use intern::Interned;
use syntax::ast;
use crate::type_ref::{TypeBound, TypeRef};
diff --git a/crates/hir-def/src/path/lower.rs b/crates/hir-def/src/path/lower.rs
index cfa3a6baaf..d570191595 100644
--- a/crates/hir-def/src/path/lower.rs
+++ b/crates/hir-def/src/path/lower.rs
@@ -1,9 +1,10 @@
//! Transforms syntax into `Path` objects, ideally with accounting for hygiene
-use crate::{intern::Interned, type_ref::ConstScalarOrPath};
+use crate::type_ref::ConstScalarOrPath;
use either::Either;
use hir_expand::name::{name, AsName};
+use intern::Interned;
use syntax::ast::{self, AstNode, HasTypeBounds};
use super::AssociatedTypeBinding;
diff --git a/crates/hir-def/src/pretty.rs b/crates/hir-def/src/pretty.rs
index befd0c5ffa..1c0bd204d3 100644
--- a/crates/hir-def/src/pretty.rs
+++ b/crates/hir-def/src/pretty.rs
@@ -3,10 +3,10 @@
use std::fmt::{self, Write};
use hir_expand::mod_path::PathKind;
+use intern::Interned;
use itertools::Itertools;
use crate::{
- intern::Interned,
path::{GenericArg, GenericArgs, Path},
type_ref::{Mutability, TraitBoundModifier, TypeBound, TypeRef},
};
diff --git a/crates/hir-def/src/resolver.rs b/crates/hir-def/src/resolver.rs
index 1ef7f9577f..86958e3dae 100644
--- a/crates/hir-def/src/resolver.rs
+++ b/crates/hir-def/src/resolver.rs
@@ -4,6 +4,7 @@ use std::{hash::BuildHasherDefault, sync::Arc};
use base_db::CrateId;
use hir_expand::name::{name, Name};
use indexmap::IndexMap;
+use intern::Interned;
use rustc_hash::FxHashSet;
use smallvec::{smallvec, SmallVec};
@@ -13,7 +14,6 @@ use crate::{
db::DefDatabase,
expr::{ExprId, LabelId, PatId},
generics::{GenericParams, TypeOrConstParamData},
- intern::Interned,
item_scope::{BuiltinShadowMode, BUILTIN_SCOPE},
nameres::DefMap,
path::{ModPath, PathKind},
diff --git a/crates/hir-def/src/type_ref.rs b/crates/hir-def/src/type_ref.rs
index f8bb78ddcf..0149fdaa43 100644
--- a/crates/hir-def/src/type_ref.rs
+++ b/crates/hir-def/src/type_ref.rs
@@ -7,13 +7,13 @@ use hir_expand::{
name::{AsName, Name},
AstId,
};
+use intern::Interned;
use syntax::ast::{self, HasName};
use crate::{
body::LowerCtx,
builtin_type::{BuiltinInt, BuiltinType, BuiltinUint},
expr::Literal,
- intern::Interned,
path::Path,
};
diff --git a/crates/hir-expand/Cargo.toml b/crates/hir-expand/Cargo.toml
index 77eb1fd450..a73e690a7e 100644
--- a/crates/hir-expand/Cargo.toml
+++ b/crates/hir-expand/Cargo.toml
@@ -22,6 +22,7 @@ hashbrown = { version = "0.12.1", features = [
smallvec = { version = "1.10.0", features = ["const_new"] }
stdx = { path = "../stdx", version = "0.0.0" }
+intern = { path = "../intern", version = "0.0.0" }
base-db = { path = "../base-db", version = "0.0.0" }
cfg = { path = "../cfg", version = "0.0.0" }
syntax = { path = "../syntax", version = "0.0.0" }
diff --git a/crates/hir-expand/src/attrs.rs b/crates/hir-expand/src/attrs.rs
new file mode 100644
index 0000000000..c7135732b8
--- /dev/null
+++ b/crates/hir-expand/src/attrs.rs
@@ -0,0 +1,346 @@
+//! A higher level attributes based on TokenTree, with also some shortcuts.
+use std::{fmt, ops, sync::Arc};
+
+use base_db::CrateId;
+use cfg::CfgExpr;
+use either::Either;
+use intern::Interned;
+use mbe::{syntax_node_to_token_tree, DelimiterKind, Punct};
+use smallvec::{smallvec, SmallVec};
+use syntax::{ast, match_ast, AstNode, SmolStr, SyntaxNode};
+use tt::Subtree;
+
+use crate::{
+ db::AstDatabase,
+ hygiene::Hygiene,
+ mod_path::{ModPath, PathKind},
+ name::AsName,
+ InFile,
+};
+
+/// Syntactical attributes, without filtering of `cfg_attr`s.
+#[derive(Default, Debug, Clone, PartialEq, Eq)]
+pub struct RawAttrs {
+ entries: Option<Arc<[Attr]>>,
+}
+
+impl ops::Deref for RawAttrs {
+ type Target = [Attr];
+
+ fn deref(&self) -> &[Attr] {
+ match &self.entries {
+ Some(it) => &*it,
+ None => &[],
+ }
+ }
+}
+
+impl RawAttrs {
+ pub const EMPTY: Self = Self { entries: None };
+
+ pub fn new(db: &dyn AstDatabase, owner: &dyn ast::HasAttrs, hygiene: &Hygiene) -> Self {
+ let entries = collect_attrs(owner)
+ .filter_map(|(id, attr)| match attr {
+ Either::Left(attr) => {
+ attr.meta().and_then(|meta| Attr::from_src(db, meta, hygiene, id))
+ }
+ Either::Right(comment) => comment.doc_comment().map(|doc| Attr {
+ id,
+ input: Some(Interned::new(AttrInput::Literal(SmolStr::new(doc)))),
+ path: Interned::new(ModPath::from(crate::name!(doc))),
+ }),
+ })
+ .collect::<Arc<_>>();
+
+ Self { entries: if entries.is_empty() { None } else { Some(entries) } }
+ }
+
+ pub fn from_attrs_owner(db: &dyn AstDatabase, owner: InFile<&dyn ast::HasAttrs>) -> Self {
+ let hygiene = Hygiene::new(db, owner.file_id);
+ Self::new(db, owner.value, &hygiene)
+ }
+
+ pub fn merge(&self, other: Self) -> Self {
+ match (&self.entries, other.entries) {
+ (None, None) => Self::EMPTY,
+ (None, entries @ Some(_)) => Self { entries },
+ (Some(entries), None) => Self { entries: Some(entries.clone()) },
+ (Some(a), Some(b)) => {
+ let last_ast_index = a.last().map_or(0, |it| it.id.ast_index() + 1) as u32;
+ Self {
+ entries: Some(
+ a.iter()
+ .cloned()
+ .chain(b.iter().map(|it| {
+ let mut it = it.clone();
+ it.id.id = it.id.ast_index() as u32 + last_ast_index
+ | (it.id.cfg_attr_index().unwrap_or(0) as u32)
+ << AttrId::AST_INDEX_BITS;
+ it
+ }))
+ .collect(),
+ ),
+ }
+ }
+ }
+ }
+
+ /// Processes `cfg_attr`s, returning the resulting semantic `Attrs`.
+ // FIXME: This should return a different type
+ pub fn filter(self, db: &dyn AstDatabase, krate: CrateId) -> RawAttrs {
+ let has_cfg_attrs = self
+ .iter()
+ .any(|attr| attr.path.as_ident().map_or(false, |name| *name == crate::name![cfg_attr]));
+ if !has_cfg_attrs {
+ return self;
+ }
+
+ let crate_graph = db.crate_graph();
+ let new_attrs = self
+ .iter()
+ .flat_map(|attr| -> SmallVec<[_; 1]> {
+ let is_cfg_attr =
+ attr.path.as_ident().map_or(false, |name| *name == crate::name![cfg_attr]);
+ if !is_cfg_attr {
+ return smallvec![attr.clone()];
+ }
+
+ let subtree = match attr.token_tree_value() {
+ Some(it) => it,
+ _ => return smallvec![attr.clone()],
+ };
+
+ let (cfg, parts) = match parse_cfg_attr_input(subtree) {
+ Some(it) => it,
+ None => return smallvec![attr.clone()],
+ };
+ let index = attr.id;
+ let attrs =
+ parts.enumerate().take(1 << AttrId::CFG_ATTR_BITS).filter_map(|(idx, attr)| {
+ let tree = Subtree { delimiter: None, token_trees: attr.to_vec() };
+ // FIXME hygiene
+ let hygiene = Hygiene::new_unhygienic();
+ Attr::from_tt(db, &tree, &hygiene, index.with_cfg_attr(idx))
+ });
+
+ let cfg_options = &crate_graph[krate].cfg_options;
+ let cfg = Subtree { delimiter: subtree.delimiter, token_trees: cfg.to_vec() };
+ let cfg = CfgExpr::parse(&cfg);
+ if cfg_options.check(&cfg) == Some(false) {
+ smallvec![]
+ } else {
+ cov_mark::hit!(cfg_attr_active);
+
+ attrs.collect()
+ }
+ })
+ .collect();
+
+ RawAttrs { entries: Some(new_attrs) }
+ }
+}
+
+#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
+pub struct AttrId {
+ id: u32,
+}
+
+// FIXME: This only handles a single level of cfg_attr nesting
+// that is `#[cfg_attr(all(), cfg_attr(all(), cfg(any())))]` breaks again
+impl AttrId {
+ const CFG_ATTR_BITS: usize = 7;
+ const AST_INDEX_MASK: usize = 0x00FF_FFFF;
+ const AST_INDEX_BITS: usize = Self::AST_INDEX_MASK.count_ones() as usize;
+ const CFG_ATTR_SET_BITS: u32 = 1 << 31;
+
+ pub fn ast_index(&self) -> usize {
+ self.id as usize & Self::AST_INDEX_MASK
+ }
+
+ pub fn cfg_attr_index(&self) -> Option<usize> {
+ if self.id & Self::CFG_ATTR_SET_BITS == 0 {
+ None
+ } else {
+ Some(self.id as usize >> Self::AST_INDEX_BITS)
+ }
+ }
+
+ pub fn with_cfg_attr(self, idx: usize) -> AttrId {
+ AttrId { id: self.id | (idx as u32) << Self::AST_INDEX_BITS | Self::CFG_ATTR_SET_BITS }
+ }
+}
+
+#[derive(Debug, Clone, PartialEq, Eq)]
+pub struct Attr {
+ pub id: AttrId,
+ pub path: Interned<ModPath>,
+ pub input: Option<Interned<AttrInput>>,
+}
+
+#[derive(Debug, Clone, PartialEq, Eq, Hash)]
+pub enum AttrInput {
+ /// `#[attr = "string"]`
+ Literal(SmolStr),
+ /// `#[attr(subtree)]`
+ TokenTree(tt::Subtree, mbe::TokenMap),
+}
+
+impl fmt::Display for AttrInput {
+ fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
+ match self {
+ AttrInput::Literal(lit) => write!(f, " = \"{}\"", lit.escape_debug()),
+ AttrInput::TokenTree(subtree, _) => subtree.fmt(f),
+ }
+ }
+}
+
+impl Attr {
+ fn from_src(
+ db: &dyn AstDatabase,
+ ast: ast::Meta,
+ hygiene: &Hygiene,
+ id: AttrId,
+ ) -> Option<Attr> {
+ let path = Interned::new(ModPath::from_src(db, ast.path()?, hygiene)?);
+ let input = if let Some(ast::Expr::Literal(lit)) = ast.expr() {
+ let value = match lit.kind() {
+ ast::LiteralKind::String(string) => string.value()?.into(),
+ _ => lit.syntax().first_token()?.text().trim_matches('"').into(),
+ };
+ Some(Interned::new(AttrInput::Literal(value)))
+ } else if let Some(tt) = ast.token_tree() {
+ let (tree, map) = syntax_node_to_token_tree(tt.syntax());
+ Some(Interned::new(AttrInput::TokenTree(tree, map)))
+ } else {
+ None
+ };
+ Some(Attr { id, path, input })
+ }
+
+ fn from_tt(
+ db: &dyn AstDatabase,
+ tt: &tt::Subtree,
+ hygiene: &Hygiene,
+ id: AttrId,
+ ) -> Option<Attr> {
+ let (parse, _) = mbe::token_tree_to_syntax_node(tt, mbe::TopEntryPoint::MetaItem);
+ let ast = ast::Meta::cast(parse.syntax_node())?;
+
+ Self::from_src(db, ast, hygiene, id)
+ }
+
+ pub fn path(&self) -> &ModPath {
+ &self.path
+ }
+}
+
+impl Attr {
+ /// #[path = "string"]
+ pub fn string_value(&self) -> Option<&SmolStr> {
+ match self.input.as_deref()? {
+ AttrInput::Literal(it) => Some(it),
+ _ => None,
+ }
+ }
+
+ /// #[path(ident)]
+ pub fn single_ident_value(&self) -> Option<&tt::Ident> {
+ match self.input.as_deref()? {
+ AttrInput::TokenTree(subtree, _) => match &*subtree.token_trees {
+ [tt::TokenTree::Leaf(tt::Leaf::Ident(ident))] => Some(ident),
+ _ => None,
+ },
+ _ => None,
+ }
+ }
+
+ /// #[path TokenTree]
+ pub fn token_tree_value(&self) -> Option<&Subtree> {
+ match self.input.as_deref()? {
+ AttrInput::TokenTree(subtree, _) => Some(subtree),
+ _ => None,
+ }
+ }
+
+ /// Parses this attribute as a token tree consisting of comma separated paths.
+ pub fn parse_path_comma_token_tree(&self) -> Option<impl Iterator<Item = ModPath> + '_> {
+ let args = self.token_tree_value()?;
+
+ if args.delimiter_kind() != Some(DelimiterKind::Parenthesis) {
+ return None;
+ }
+ let paths = args
+ .token_trees
+ .split(|tt| matches!(tt, tt::TokenTree::Leaf(tt::Leaf::Punct(Punct { char: ',', .. }))))
+ .filter_map(|tts| {
+ if tts.is_empty() {
+ return None;
+ }
+ let segments = tts.iter().filter_map(|tt| match tt {
+ tt::TokenTree::Leaf(tt::Leaf::Ident(id)) => Some(id.as_name()),
+ _ => None,
+ });
+ Some(ModPath::from_segments(PathKind::Plain, segments))
+ });
+
+ Some(paths)
+ }
+}
+
+pub fn collect_attrs(
+ owner: &dyn ast::HasAttrs,
+) -> impl Iterator<Item = (AttrId, Either<ast::Attr, ast::Comment>)> {
+ let inner_attrs = inner_attributes(owner.syntax()).into_iter().flatten();
+ let outer_attrs =
+ ast::AttrDocCommentIter::from_syntax_node(owner.syntax()).filter(|el| match el {
+ Either::Left(attr) => attr.kind().is_outer(),
+ Either::Right(comment) => comment.is_outer(),
+ });
+ outer_attrs.chain(inner_attrs).enumerate().map(|(id, attr)| (AttrId { id: id as u32 }, attr))
+}
+
+fn inner_attributes(
+ syntax: &SyntaxNode,
+) -> Option<impl Iterator<Item = Either<ast::Attr, ast::Comment>>> {
+ let node = match_ast! {
+ match syntax {
+ ast::SourceFile(_) => syntax.clone(),
+ ast::ExternBlock(it) => it.extern_item_list()?.syntax().clone(),
+ ast::Fn(it) => it.body()?.stmt_list()?.syntax().clone(),
+ ast::Impl(it) => it.assoc_item_list()?.syntax().clone(),
+ ast::Module(it) => it.item_list()?.syntax().clone(),
+ ast::BlockExpr(it) => {
+ use syntax::SyntaxKind::{BLOCK_EXPR , EXPR_STMT};
+ // Block expressions accept outer and inner attributes, but only when they are the outer
+ // expression of an expression statement or the final expression of another block expression.
+ let may_carry_attributes = matches!(
+ it.syntax().parent().map(|it| it.kind()),
+ Some(BLOCK_EXPR | EXPR_STMT)
+ );
+ if !may_carry_attributes {
+ return None
+ }
+ syntax.clone()
+ },
+ _ => return None,
+ }
+ };
+
+ let attrs = ast::AttrDocCommentIter::from_syntax_node(&node).filter(|el| match el {
+ Either::Left(attr) => attr.kind().is_inner(),
+ Either::Right(comment) => comment.is_inner(),
+ });
+ Some(attrs)
+}
+
+// Input subtree is: `(cfg, $(attr),+)`
+// Split it up into a `cfg` subtree and the `attr` subtrees.
+pub fn parse_cfg_attr_input(
+ subtree: &Subtree,
+) -> Option<(&[tt::TokenTree], impl Iterator<Item = &[tt::TokenTree]>)> {
+ let mut parts = subtree
+ .token_trees
+ .split(|tt| matches!(tt, tt::TokenTree::Leaf(tt::Leaf::Punct(Punct { char: ',', .. }))));
+ let cfg = parts.next()?;
+ Some((cfg, parts.filter(|it| !it.is_empty())))
+}
diff --git a/crates/hir-expand/src/db.rs b/crates/hir-expand/src/db.rs
index b28e60187d..ec5886824f 100644
--- a/crates/hir-expand/src/db.rs
+++ b/crates/hir-expand/src/db.rs
@@ -168,7 +168,9 @@ pub fn expand_speculative(
// Attributes may have an input token tree, build the subtree and map for this as well
// then try finding a token id for our token if it is inside this input subtree.
let item = ast::Item::cast(speculative_args.clone())?;
- item.doc_comments_and_attrs().nth(invoc_attr_index as usize).and_then(Either::left)
+ item.doc_comments_and_attrs()
+ .nth(invoc_attr_index.ast_index())
+ .and_then(Either::left)
}?;
match attr.token_tree() {
Some(token_tree) => {
@@ -321,6 +323,7 @@ fn macro_arg(
}
fn censor_for_macro_input(loc: &MacroCallLoc, node: &SyntaxNode) -> FxHashSet<SyntaxNode> {
+ // FIXME: handle `cfg_attr`
(|| {
let censor = match loc.kind {
MacroCallKind::FnLike { .. } => return None,
@@ -328,7 +331,7 @@ fn censor_for_macro_input(loc: &MacroCallLoc, node: &SyntaxNode) -> FxHashSet<Sy
cov_mark::hit!(derive_censoring);
ast::Item::cast(node.clone())?
.attrs()
- .take(derive_attr_index as usize + 1)
+ .take(derive_attr_index.ast_index() + 1)
// FIXME, this resolution should not be done syntactically
// derive is a proper macro now, no longer builtin
// But we do not have resolution at this stage, this means
@@ -343,7 +346,7 @@ fn censor_for_macro_input(loc: &MacroCallLoc, node: &SyntaxNode) -> FxHashSet<Sy
cov_mark::hit!(attribute_macro_attr_censoring);
ast::Item::cast(node.clone())?
.doc_comments_and_attrs()
- .nth(invoc_attr_index as usize)
+ .nth(invoc_attr_index.ast_index())
.and_then(Either::left)
.map(|attr| attr.syntax().clone())
.into_iter()
diff --git a/crates/hir-expand/src/hygiene.rs b/crates/hir-expand/src/hygiene.rs
index df1e20256c..5a55dc5c9e 100644
--- a/crates/hir-expand/src/hygiene.rs
+++ b/crates/hir-expand/src/hygiene.rs
@@ -191,7 +191,7 @@ fn make_hygiene_info(
let tt = ast_id
.to_node(db)
.doc_comments_and_attrs()
- .nth(invoc_attr_index as usize)
+ .nth(invoc_attr_index.ast_index())
.and_then(Either::left)?
.token_tree()?;
Some(InFile::new(ast_id.file_id, tt))
diff --git a/crates/hir-expand/src/lib.rs b/crates/hir-expand/src/lib.rs
index bc5f9f3b8a..5554c7517f 100644
--- a/crates/hir-expand/src/lib.rs
+++ b/crates/hir-expand/src/lib.rs
@@ -17,6 +17,7 @@ pub mod proc_macro;
pub mod quote;
pub mod eager;
pub mod mod_path;
+pub mod attrs;
mod fixup;
pub use mbe::{Origin, ValueResult};
@@ -37,6 +38,7 @@ use syntax::{
use crate::{
ast_id_map::FileAstId,
+ attrs::AttrId,
builtin_attr_macro::BuiltinAttrExpander,
builtin_derive_macro::BuiltinDeriveExpander,
builtin_fn_macro::{BuiltinFnLikeExpander, EagerExpander},
@@ -145,7 +147,7 @@ pub enum MacroCallKind {
///
/// Outer attributes are counted first, then inner attributes. This does not support
/// out-of-line modules, which may have attributes spread across 2 files!
- derive_attr_index: u32,
+ derive_attr_index: AttrId,
/// Index of the derive macro in the derive attribute
derive_index: u32,
},
@@ -156,7 +158,7 @@ pub enum MacroCallKind {
///
/// Outer attributes are counted first, then inner attributes. This does not support
/// out-of-line modules, which may have attributes spread across 2 files!
- invoc_attr_index: u32,
+ invoc_attr_index: AttrId,
/// Whether this attribute is the `#[derive]` attribute.
is_derive: bool,
},
@@ -261,10 +263,11 @@ impl HirFileId {
});
let attr_input_or_mac_def = def.or_else(|| match loc.kind {
MacroCallKind::Attr { ast_id, invoc_attr_index, .. } => {
+ // FIXME: handle `cfg_attr`
let tt = ast_id
.to_node(db)
.doc_comments_and_attrs()
- .nth(invoc_attr_index as usize)
+ .nth(invoc_attr_index.ast_index())
.and_then(Either::left)?
.token_tree()?;
Some(InFile::new(ast_id.file_id, tt))
@@ -397,8 +400,7 @@ impl MacroDefId {
}
}
-// FIXME: attribute indices do not account for `cfg_attr`, which means that we'll strip the whole
-// `cfg_attr` instead of just one of the attributes it expands to
+// FIXME: attribute indices do not account for nested `cfg_attr`
impl MacroCallKind {
/// Returns the file containing the macro invocation.
@@ -419,7 +421,7 @@ impl MacroCallKind {
// FIXME: handle `cfg_attr`
ast_id.with_value(ast_id.to_node(db)).map(|it| {
it.doc_comments_and_attrs()
- .nth(*derive_attr_index as usize)
+ .nth(derive_attr_index.ast_index())
.and_then(|it| match it {
Either::Left(attr) => Some(attr.syntax().clone()),
Either::Right(_) => None,
@@ -431,7 +433,7 @@ impl MacroCallKind {
// FIXME: handle `cfg_attr`
ast_id.with_value(ast_id.to_node(db)).map(|it| {
it.doc_comments_and_attrs()
- .nth(*invoc_attr_index as usize)
+ .nth(invoc_attr_index.ast_index())
.and_then(|it| match it {
Either::Left(attr) => Some(attr.syntax().clone()),
Either::Right(_) => None,
@@ -488,19 +490,21 @@ impl MacroCallKind {
MacroCallKind::FnLike { ast_id, .. } => ast_id.to_node(db).syntax().text_range(),
MacroCallKind::Derive { ast_id, derive_attr_index, .. } => {
// FIXME: should be the range of the macro name, not the whole derive
+ // FIXME: handle `cfg_attr`
ast_id
.to_node(db)
.doc_comments_and_attrs()
- .nth(derive_attr_index as usize)
+ .nth(derive_attr_index.ast_index())
.expect("missing derive")
.expect_left("derive is a doc comment?")
.syntax()
.text_range()
}
+ // FIXME: handle `cfg_attr`
MacroCallKind::Attr { ast_id, invoc_attr_index, .. } => ast_id
.to_node(db)
.doc_comments_and_attrs()
- .nth(invoc_attr_index as usize)
+ .nth(invoc_attr_index.ast_index())
.expect("missing attribute")
.expect_left("attribute macro is a doc comment?")
.syntax()
@@ -592,9 +596,10 @@ impl ExpansionInfo {
let token_range = token.value.text_range();
match &loc.kind {
MacroCallKind::Attr { attr_args, invoc_attr_index, is_derive, .. } => {
+ // FIXME: handle `cfg_attr`
let attr = item
.doc_comments_and_attrs()
- .nth(*invoc_attr_index as usize)
+ .nth(invoc_attr_index.ast_index())
.and_then(Either::left)?;
match attr.token_tree() {
Some(token_tree)
@@ -1031,3 +1036,5 @@ impl ExpandTo {
pub struct UnresolvedMacro {
pub path: ModPath,
}
+
+intern::impl_internable!(ModPath, attrs::AttrInput);
diff --git a/crates/hir-ty/Cargo.toml b/crates/hir-ty/Cargo.toml
index ae837ac6dc..75b33da1f2 100644
--- a/crates/hir-ty/Cargo.toml
+++ b/crates/hir-ty/Cargo.toml
@@ -29,6 +29,7 @@ typed-arena = "2.0.1"
rustc_index = { version = "0.0.20221221", package = "hkalbasi-rustc-ap-rustc_index", default-features = false }
stdx = { path = "../stdx", version = "0.0.0" }
+intern = { path = "../intern", version = "0.0.0" }
hir-def = { path = "../hir-def", version = "0.0.0" }
hir-expand = { path = "../hir-expand", version = "0.0.0" }
base-db = { path = "../base-db", version = "0.0.0" }
diff --git a/crates/hir-ty/src/display.rs b/crates/hir-ty/src/display.rs
index 66e813eed8..f9642aa747 100644
--- a/crates/hir-ty/src/display.rs
+++ b/crates/hir-ty/src/display.rs
@@ -11,7 +11,6 @@ use hir_def::{
db::DefDatabase,
find_path,
generics::{TypeOrConstParamData, TypeParamProvenance},
- intern::{Internable, Interned},
item_scope::ItemInNs,
path::{Path, PathKind},
type_ref::{ConstScalar, TraitBoundModifier, TypeBound, TypeRef},
@@ -19,6 +18,7 @@ use hir_def::{
HasModule, ItemContainerId, Lookup, ModuleDefId, ModuleId, TraitId,
};
use hir_expand::{hygiene::Hygiene, name::Name};
+use intern::{Internable, Interned};
use itertools::Itertools;
use smallvec::SmallVec;
use syntax::SmolStr;
diff --git a/crates/hir-ty/src/interner.rs b/crates/hir-ty/src/interner.rs
index 441503a300..7bf73560cb 100644
--- a/crates/hir-ty/src/interner.rs
+++ b/crates/hir-ty/src/interner.rs
@@ -4,11 +4,8 @@
use crate::{chalk_db, tls, GenericArg};
use base_db::salsa::InternId;
use chalk_ir::{Goal, GoalData};
-use hir_def::{
- intern::{impl_internable, InternStorage, Internable, Interned},
- type_ref::ConstScalar,
- TypeAliasId,
-};
+use hir_def::{type_ref::ConstScalar, TypeAliasId};
+use intern::{impl_internable, Interned};
use smallvec::SmallVec;
use std::{fmt, sync::Arc};
diff --git a/crates/hir-ty/src/lower.rs b/crates/hir-ty/src/lower.rs
index 592410008a..4b1f40f91d 100644
--- a/crates/hir-ty/src/lower.rs
+++ b/crates/hir-ty/src/lower.rs
@@ -23,7 +23,6 @@ use hir_def::{
generics::{
TypeOrConstParamData, TypeParamProvenance, WherePredicate, WherePredicateTypeTarget,
},
- intern::Interned,
lang_item::lang_attr,
path::{GenericArg, ModPath, Path, PathKind, PathSegment, PathSegments},
resolver::{HasResolver, Resolver, TypeNs},
@@ -35,6 +34,7 @@ use hir_def::{
TypeAliasId, TypeOrConstParamId, TypeParamId, UnionId, VariantId,
};
use hir_expand::{name::Name, ExpandResult};
+use intern::Interned;
use itertools::Either;
use la_arena::ArenaMap;
use rustc_hash::FxHashSet;
diff --git a/crates/hir-ty/src/utils.rs b/crates/hir-ty/src/utils.rs
index 9893566bd5..4f516e18be 100644
--- a/crates/hir-ty/src/utils.rs
+++ b/crates/hir-ty/src/utils.rs
@@ -11,13 +11,13 @@ use hir_def::{
GenericParams, TypeOrConstParamData, TypeParamProvenance, WherePredicate,
WherePredicateTypeTarget,
},
- intern::Interned,
resolver::{HasResolver, TypeNs},
type_ref::{TraitBoundModifier, TypeRef},
ConstParamId, FunctionId, GenericDefId, ItemContainerId, Lookup, TraitId, TypeAliasId,
TypeOrConstParamId, TypeParamId,
};
use hir_expand::name::Name;
+use intern::Interned;
use itertools::Either;
use rustc_hash::FxHashSet;
use smallvec::{smallvec, SmallVec};
diff --git a/crates/hir/src/lib.rs b/crates/hir/src/lib.rs
index 08fd4453df..ec66660f34 100644
--- a/crates/hir/src/lib.rs
+++ b/crates/hir/src/lib.rs
@@ -107,7 +107,7 @@ pub use {
cfg::{CfgAtom, CfgExpr, CfgOptions},
hir_def::{
adt::StructKind,
- attr::{Attr, Attrs, AttrsWithOwner, Documentation},
+ attr::{Attrs, AttrsWithOwner, Documentation},
builtin_attr::AttributeTemplate,
find_path::PrefixKind,
import_map,
@@ -122,6 +122,7 @@ pub use {
ModuleDefId,
},
hir_expand::{
+ attrs::Attr,
name::{known, Name},
ExpandResult, HirFileId, InFile, MacroFile, Origin,
},
@@ -784,7 +785,7 @@ fn precise_macro_call_location(
let token = (|| {
let derive_attr = node
.doc_comments_and_attrs()
- .nth(*derive_attr_index as usize)
+ .nth(derive_attr_index.ast_index())
.and_then(Either::left)?;
let token_tree = derive_attr.meta()?.token_tree()?;
let group_by = token_tree
@@ -812,9 +813,11 @@ fn precise_macro_call_location(
let node = ast_id.to_node(db.upcast());
let attr = node
.doc_comments_and_attrs()
- .nth((*invoc_attr_index) as usize)
+ .nth(invoc_attr_index.ast_index())
.and_then(Either::left)
- .unwrap_or_else(|| panic!("cannot find attribute #{invoc_attr_index}"));
+ .unwrap_or_else(|| {
+ panic!("cannot find attribute #{}", invoc_attr_index.ast_index())
+ });
(
ast_id.with_value(SyntaxNodePtr::from(AstPtr::new(&attr))),
diff --git a/crates/hir/src/semantics/source_to_def.rs b/crates/hir/src/semantics/source_to_def.rs
index fa45e3c12e..2b5bfda1d4 100644
--- a/crates/hir/src/semantics/source_to_def.rs
+++ b/crates/hir/src/semantics/source_to_def.rs
@@ -87,7 +87,6 @@
use base_db::FileId;
use hir_def::{
- attr::AttrId,
child_by_source::ChildBySource,
dyn_map::DynMap,
expr::{LabelId, PatId},
@@ -96,7 +95,7 @@ use hir_def::{
GenericDefId, GenericParamId, ImplId, LifetimeParamId, MacroId, ModuleId, StaticId, StructId,
TraitId, TypeAliasId, TypeParamId, UnionId, VariantId,
};
-use hir_expand::{name::AsName, HirFileId, MacroCallId};
+use hir_expand::{attrs::AttrId, name::AsName, HirFileId, MacroCallId};
use rustc_hash::FxHashMap;
use smallvec::SmallVec;
use stdx::impl_from;
diff --git a/crates/intern/Cargo.toml b/crates/intern/Cargo.toml
new file mode 100644
index 0000000000..78007fc860
--- /dev/null
+++ b/crates/intern/Cargo.toml
@@ -0,0 +1,18 @@
+[package]
+name = "intern"
+version = "0.0.0"
+description = "TBD"
+license = "MIT OR Apache-2.0"
+edition = "2021"
+rust-version = "1.65"
+
+[lib]
+doctest = false
+
+
+[dependencies]
+# We need to freeze the version of the crate, as the raw-api feature is considered unstable
+dashmap = { version = "=5.4.0", features = ["raw-api"] }
+hashbrown = { version = "0.12.1", default-features = false }
+once_cell = "1.15.0"
+rustc-hash = "1.1.0"
diff --git a/crates/hir-def/src/intern.rs b/crates/intern/src/lib.rs
index f08521a340..fb2903696b 100644
--- a/crates/hir-def/src/intern.rs
+++ b/crates/intern/src/lib.rs
@@ -14,8 +14,6 @@ use hashbrown::HashMap;
use once_cell::sync::OnceCell;
use rustc_hash::FxHasher;
-use crate::generics::GenericParams;
-
type InternMap<T> = DashMap<Arc<T>, (), BuildHasherDefault<FxHasher>>;
type Guard<T> = dashmap::RwLockWriteGuard<
'static,
@@ -204,9 +202,9 @@ pub trait Internable: Hash + Eq + 'static {
#[doc(hidden)]
macro_rules! _impl_internable {
( $($t:path),+ $(,)? ) => { $(
- impl Internable for $t {
- fn storage() -> &'static InternStorage<Self> {
- static STORAGE: InternStorage<$t> = InternStorage::new();
+ impl $crate::Internable for $t {
+ fn storage() -> &'static $crate::InternStorage<Self> {
+ static STORAGE: $crate::InternStorage<$t> = $crate::InternStorage::new();
&STORAGE
}
}
@@ -215,13 +213,4 @@ macro_rules! _impl_internable {
pub use crate::_impl_internable as impl_internable;
-impl_internable!(
- crate::type_ref::TypeRef,
- crate::type_ref::TraitRef,
- crate::type_ref::TypeBound,
- crate::path::ModPath,
- crate::path::GenericArgs,
- crate::attr::AttrInput,
- GenericParams,
- str,
-);
+impl_internable!(str,);