Unnamed repository; edit this file 'description' to name the repository.
Diffstat (limited to 'crates/hir-def/src/data.rs')
-rw-r--r--crates/hir-def/src/data.rs246
1 files changed, 168 insertions, 78 deletions
diff --git a/crates/hir-def/src/data.rs b/crates/hir-def/src/data.rs
index 1633a33bed..40e6a43087 100644
--- a/crates/hir-def/src/data.rs
+++ b/crates/hir-def/src/data.rs
@@ -1,22 +1,28 @@
//! Contains basic data about various HIR declarations.
-use std::sync::Arc;
+pub mod adt;
-use hir_expand::{name::Name, AstId, ExpandResult, HirFileId, InFile, MacroCallId, MacroDefKind};
+use hir_expand::{
+ name::Name, AstId, ExpandResult, HirFileId, InFile, MacroCallId, MacroCallKind, MacroDefKind,
+};
use intern::Interned;
use smallvec::SmallVec;
-use syntax::ast;
+use syntax::{ast, Parse};
+use triomphe::Arc;
use crate::{
attr::Attrs,
- body::{Expander, Mark},
db::DefDatabase,
- item_tree::{self, AssocItem, FnFlags, ItemTree, ItemTreeId, ModItem, Param, TreeId},
+ expander::{Expander, Mark},
+ item_tree::{
+ self, AssocItem, FnFlags, ItemTree, ItemTreeId, MacroCall, ModItem, Param, TreeId,
+ },
+ macro_call_as_call_id, macro_id_to_def_id,
nameres::{
attr_resolution::ResolvedAttr,
diagnostics::DefDiagnostic,
proc_macro::{parse_macro_name_and_helper_attrs, ProcMacroKind},
- DefMap,
+ DefMap, MacroSubNs,
},
type_ref::{TraitRef, TypeBound, TypeRef},
visibility::RawVisibility,
@@ -28,9 +34,8 @@ use crate::{
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct FunctionData {
pub name: Name,
- pub params: Vec<(Option<Name>, Interned<TypeRef>)>,
+ pub params: Vec<Interned<TypeRef>>,
pub ret_type: Interned<TypeRef>,
- pub async_ret_type: Option<Interned<TypeRef>>,
pub attrs: Attrs,
pub visibility: RawVisibility,
pub abi: Option<Interned<str>>,
@@ -43,16 +48,16 @@ impl FunctionData {
pub(crate) fn fn_data_query(db: &dyn DefDatabase, func: FunctionId) -> Arc<FunctionData> {
let loc = func.lookup(db);
let krate = loc.container.module(db).krate;
- let crate_graph = db.crate_graph();
- let cfg_options = &crate_graph[krate].cfg_options;
let item_tree = loc.id.item_tree(db);
let func = &item_tree[loc.id.value];
let visibility = if let ItemContainerId::TraitId(trait_id) = loc.container {
- db.trait_data(trait_id).visibility.clone()
+ trait_vis(db, trait_id)
} else {
item_tree[func.visibility].clone()
};
+ let crate_graph = db.crate_graph();
+ let cfg_options = &crate_graph[krate].cfg_options;
let enabled_params = func
.params
.clone()
@@ -99,12 +104,11 @@ impl FunctionData {
params: enabled_params
.clone()
.filter_map(|id| match &item_tree[id] {
- Param::Normal(name, ty) => Some((name.clone(), ty.clone())),
+ Param::Normal(ty) => Some(ty.clone()),
Param::Varargs => None,
})
.collect(),
ret_type: func.ret_type.clone(),
- async_ret_type: func.async_ret_type.clone(),
attrs: item_tree.attrs(db, krate, ModItem::from(loc.id.value).into()),
visibility,
abi: func.abi.clone(),
@@ -188,7 +192,7 @@ impl TypeAliasData {
let item_tree = loc.id.item_tree(db);
let typ = &item_tree[loc.id.value];
let visibility = if let ItemContainerId::TraitId(trait_id) = loc.container {
- db.trait_data(trait_id).visibility.clone()
+ trait_vis(db, trait_id)
} else {
item_tree[typ.visibility].clone()
};
@@ -471,7 +475,7 @@ impl ConstData {
let item_tree = loc.id.item_tree(db);
let konst = &item_tree[loc.id.value];
let visibility = if let ItemContainerId::TraitId(trait_id) = loc.container {
- db.trait_data(trait_id).visibility.clone()
+ trait_vis(db, trait_id)
} else {
item_tree[konst.visibility].clone()
};
@@ -519,7 +523,7 @@ struct AssocItemCollector<'a> {
db: &'a dyn DefDatabase,
module_id: ModuleId,
def_map: Arc<DefMap>,
- inactive_diagnostics: Vec<DefDiagnostic>,
+ diagnostics: Vec<DefDiagnostic>,
container: ItemContainerId,
expander: Expander,
@@ -542,7 +546,7 @@ impl<'a> AssocItemCollector<'a> {
expander: Expander::new(db, file_id, module_id),
items: Vec::new(),
attr_calls: Vec::new(),
- inactive_diagnostics: Vec::new(),
+ diagnostics: Vec::new(),
}
}
@@ -556,11 +560,10 @@ impl<'a> AssocItemCollector<'a> {
(
self.items,
if self.attr_calls.is_empty() { None } else { Some(Box::new(self.attr_calls)) },
- self.inactive_diagnostics,
+ self.diagnostics,
)
}
- // FIXME: proc-macro diagnostics
fn collect(&mut self, item_tree: &ItemTree, tree_id: TreeId, assoc_items: &[AssocItem]) {
let container = self.container;
self.items.reserve(assoc_items.len());
@@ -568,7 +571,7 @@ impl<'a> AssocItemCollector<'a> {
'items: for &item in assoc_items {
let attrs = item_tree.attrs(self.db, self.module_id.krate, ModItem::from(item).into());
if !attrs.is_cfg_enabled(self.expander.cfg_options()) {
- self.inactive_diagnostics.push(DefDiagnostic::unconfigured_code(
+ self.diagnostics.push(DefDiagnostic::unconfigured_code(
self.module_id.local_id,
InFile::new(self.expander.current_file_id(), item.ast_id(item_tree).upcast()),
attrs.cfg().unwrap(),
@@ -582,84 +585,164 @@ impl<'a> AssocItemCollector<'a> {
AstId::new(self.expander.current_file_id(), item.ast_id(item_tree).upcast());
let ast_id_with_path = AstIdWithPath { path: (*attr.path).clone(), ast_id };
- if let Ok(ResolvedAttr::Macro(call_id)) = self.def_map.resolve_attr_macro(
+ match self.def_map.resolve_attr_macro(
self.db,
self.module_id.local_id,
ast_id_with_path,
attr,
) {
- self.attr_calls.push((ast_id, call_id));
- // If proc attribute macro expansion is disabled, skip expanding it here
- if !self.db.enable_proc_attr_macros() {
- continue 'attrs;
- }
- let loc = self.db.lookup_intern_macro_call(call_id);
- if let MacroDefKind::ProcMacro(exp, ..) = loc.def.kind {
- // If there's no expander for the proc macro (e.g. the
- // proc macro is ignored, or building the proc macro
- // crate failed), skip expansion like we would if it was
- // disabled. This is analogous to the handling in
- // `DefCollector::collect_macros`.
- if exp.is_dummy() {
+ Ok(ResolvedAttr::Macro(call_id)) => {
+ self.attr_calls.push((ast_id, call_id));
+ // If proc attribute macro expansion is disabled, skip expanding it here
+ if !self.db.expand_proc_attr_macros() {
continue 'attrs;
}
- }
- match self.expander.enter_expand_id::<ast::MacroItems>(self.db, call_id) {
- ExpandResult { value: Some((mark, _)), .. } => {
- self.collect_macro_items(mark);
- continue 'items;
+ let loc = self.db.lookup_intern_macro_call(call_id);
+ if let MacroDefKind::ProcMacro(exp, ..) = loc.def.kind {
+ // If there's no expander for the proc macro (e.g. the
+ // proc macro is ignored, or building the proc macro
+ // crate failed), skip expansion like we would if it was
+ // disabled. This is analogous to the handling in
+ // `DefCollector::collect_macros`.
+ if exp.is_dummy() {
+ continue 'attrs;
+ }
}
- ExpandResult { .. } => {}
+
+ let res =
+ self.expander.enter_expand_id::<ast::MacroItems>(self.db, call_id);
+ self.collect_macro_items(res, &|| loc.kind.clone());
+ continue 'items;
+ }
+ Ok(_) => (),
+ Err(_) => {
+ self.diagnostics.push(DefDiagnostic::unresolved_macro_call(
+ self.module_id.local_id,
+ MacroCallKind::Attr {
+ ast_id,
+ attr_args: Arc::new((tt::Subtree::empty(), Default::default())),
+ invoc_attr_index: attr.id,
+ },
+ attr.path().clone(),
+ ));
}
}
}
- match item {
- AssocItem::Function(id) => {
- let item = &item_tree[id];
+ self.collect_item(item_tree, tree_id, container, item);
+ }
+ }
- let def =
- FunctionLoc { container, id: ItemTreeId::new(tree_id, id) }.intern(self.db);
- self.items.push((item.name.clone(), def.into()));
- }
- AssocItem::Const(id) => {
- let item = &item_tree[id];
-
- let name = match item.name.clone() {
- Some(name) => name,
- None => continue,
- };
- let def =
- ConstLoc { container, id: ItemTreeId::new(tree_id, id) }.intern(self.db);
- self.items.push((name, def.into()));
- }
- AssocItem::TypeAlias(id) => {
- let item = &item_tree[id];
+ fn collect_item(
+ &mut self,
+ item_tree: &ItemTree,
+ tree_id: TreeId,
+ container: ItemContainerId,
+ item: AssocItem,
+ ) {
+ match item {
+ AssocItem::Function(id) => {
+ let item = &item_tree[id];
- let def = TypeAliasLoc { container, id: ItemTreeId::new(tree_id, id) }
- .intern(self.db);
- self.items.push((item.name.clone(), def.into()));
- }
- AssocItem::MacroCall(call) => {
- if let Some(root) = self.db.parse_or_expand(self.expander.current_file_id()) {
- let call = &item_tree[call];
-
- let ast_id_map = self.db.ast_id_map(self.expander.current_file_id());
- let call = ast_id_map.get(call.ast_id).to_node(&root);
- let _cx =
- stdx::panic_context::enter(format!("collect_items MacroCall: {call}"));
- let res = self.expander.enter_expand::<ast::MacroItems>(self.db, call);
-
- if let Ok(ExpandResult { value: Some((mark, _)), .. }) = res {
- self.collect_macro_items(mark);
- }
+ let def =
+ FunctionLoc { container, id: ItemTreeId::new(tree_id, id) }.intern(self.db);
+ self.items.push((item.name.clone(), def.into()));
+ }
+ AssocItem::Const(id) => {
+ let item = &item_tree[id];
+ let Some(name) = item.name.clone() else { return };
+ let def = ConstLoc { container, id: ItemTreeId::new(tree_id, id) }.intern(self.db);
+ self.items.push((name, def.into()));
+ }
+ AssocItem::TypeAlias(id) => {
+ let item = &item_tree[id];
+
+ let def =
+ TypeAliasLoc { container, id: ItemTreeId::new(tree_id, id) }.intern(self.db);
+ self.items.push((item.name.clone(), def.into()));
+ }
+ AssocItem::MacroCall(call) => {
+ let file_id = self.expander.current_file_id();
+ let MacroCall { ast_id, expand_to, ref path } = item_tree[call];
+ let module = self.expander.module.local_id;
+
+ let resolver = |path| {
+ self.def_map
+ .resolve_path(
+ self.db,
+ module,
+ &path,
+ crate::item_scope::BuiltinShadowMode::Other,
+ Some(MacroSubNs::Bang),
+ )
+ .0
+ .take_macros()
+ .map(|it| macro_id_to_def_id(self.db, it))
+ };
+ match macro_call_as_call_id(
+ self.db.upcast(),
+ &AstIdWithPath::new(file_id, ast_id, Clone::clone(path)),
+ expand_to,
+ self.expander.module.krate(),
+ resolver,
+ ) {
+ Ok(Some(call_id)) => {
+ let res =
+ self.expander.enter_expand_id::<ast::MacroItems>(self.db, call_id);
+ self.collect_macro_items(res, &|| hir_expand::MacroCallKind::FnLike {
+ ast_id: InFile::new(file_id, ast_id),
+ expand_to: hir_expand::ExpandTo::Items,
+ });
+ }
+ Ok(None) => (),
+ Err(_) => {
+ self.diagnostics.push(DefDiagnostic::unresolved_macro_call(
+ self.module_id.local_id,
+ MacroCallKind::FnLike {
+ ast_id: InFile::new(file_id, ast_id),
+ expand_to,
+ },
+ Clone::clone(path),
+ ));
}
}
}
}
}
- fn collect_macro_items(&mut self, mark: Mark) {
+ fn collect_macro_items(
+ &mut self,
+ ExpandResult { value, err }: ExpandResult<Option<(Mark, Parse<ast::MacroItems>)>>,
+ error_call_kind: &dyn Fn() -> hir_expand::MacroCallKind,
+ ) {
+ let Some((mark, parse)) = value else { return };
+
+ if let Some(err) = err {
+ let diag = match err {
+ // why is this reported here?
+ hir_expand::ExpandError::UnresolvedProcMacro(krate) => {
+ DefDiagnostic::unresolved_proc_macro(
+ self.module_id.local_id,
+ error_call_kind(),
+ krate,
+ )
+ }
+ _ => DefDiagnostic::macro_error(
+ self.module_id.local_id,
+ error_call_kind(),
+ err.to_string(),
+ ),
+ };
+ self.diagnostics.push(diag);
+ }
+ if let errors @ [_, ..] = parse.errors() {
+ self.diagnostics.push(DefDiagnostic::macro_expansion_parse_error(
+ self.module_id.local_id,
+ error_call_kind(),
+ errors.into(),
+ ));
+ }
+
let tree_id = item_tree::TreeId::new(self.expander.current_file_id(), None);
let item_tree = tree_id.item_tree(self.db);
let iter: SmallVec<[_; 2]> =
@@ -670,3 +753,10 @@ impl<'a> AssocItemCollector<'a> {
self.expander.exit(self.db, mark);
}
}
+
+fn trait_vis(db: &dyn DefDatabase, trait_id: TraitId) -> RawVisibility {
+ let ItemLoc { id: tree_id, .. } = trait_id.lookup(db);
+ let item_tree = tree_id.item_tree(db);
+ let tr_def = &item_tree[tree_id.value];
+ item_tree[tr_def.visibility].clone()
+}