Unnamed repository; edit this file 'description' to name the repository.
Diffstat (limited to 'crates/hir/src/lib.rs')
-rw-r--r--crates/hir/src/lib.rs302
1 files changed, 213 insertions, 89 deletions
diff --git a/crates/hir/src/lib.rs b/crates/hir/src/lib.rs
index 016f341851..266ef2a55c 100644
--- a/crates/hir/src/lib.rs
+++ b/crates/hir/src/lib.rs
@@ -37,14 +37,14 @@ mod display;
use std::{mem::discriminant, ops::ControlFlow};
use arrayvec::ArrayVec;
-use base_db::{CrateDisplayName, CrateId, CrateOrigin, FileId};
+use base_db::{CrateDisplayName, CrateId, CrateOrigin};
use either::Either;
use hir_def::{
body::{BodyDiagnostic, SyntheticSyntax},
data::adt::VariantData,
generics::{LifetimeParamData, TypeOrConstParamData, TypeParamProvenance},
hir::{BindingAnnotation, BindingId, ExprOrPatId, LabelId, Pat},
- item_tree::ItemTreeNode,
+ item_tree::{AttrOwner, FieldParent, ItemTreeFieldId, ItemTreeNode},
lang_item::LangItemTarget,
layout::{self, ReprOptions, TargetDataLayout},
nameres::{self, diagnostics::DefDiagnostic},
@@ -58,7 +58,7 @@ use hir_def::{
TypeOrConstParamId, TypeParamId, UnionId,
};
use hir_expand::{
- attrs::collect_attrs, name::name, proc_macro::ProcMacroKind, AstId, MacroCallKind, ValueResult,
+ attrs::collect_attrs, proc_macro::ProcMacroKind, AstId, MacroCallKind, ValueResult,
};
use hir_ty::{
all_super_traits, autoderef, check_orphan_rules,
@@ -78,11 +78,11 @@ use hir_ty::{
use itertools::Itertools;
use nameres::diagnostics::DefDiagnosticKind;
use rustc_hash::FxHashSet;
-use span::{Edition, MacroCallId};
+use span::{Edition, EditionedFileId, FileId, MacroCallId};
use stdx::{impl_from, never};
use syntax::{
- ast::{self, HasAttrs as _, HasName},
- format_smolstr, AstNode, AstPtr, SmolStr, SyntaxNode, SyntaxNodePtr, TextRange, T,
+ ast::{self, HasAttrs as _, HasGenericParams, HasName},
+ format_smolstr, AstNode, AstPtr, SmolStr, SyntaxNode, SyntaxNodePtr, TextRange, ToSmolStr, T,
};
use triomphe::Arc;
@@ -129,12 +129,16 @@ pub use {
hir_expand::{
attrs::{Attr, AttrId},
change::ChangeWithProcMacros,
+ files::{
+ FilePosition, FilePositionWrapper, FileRange, FileRangeWrapper, HirFilePosition,
+ HirFileRange, InFile, InFileWrapper, InMacroFile, InRealFile, MacroFilePosition,
+ MacroFileRange,
+ },
hygiene::{marks_rev, SyntaxContextExt},
inert_attr_macro::AttributeTemplate,
- name::{known, Name},
- proc_macro::ProcMacros,
- tt, ExpandResult, HirFileId, HirFileIdExt, InFile, InMacroFile, InRealFile, MacroFileId,
- MacroFileIdExt,
+ name::Name,
+ proc_macro::{ProcMacros, ProcMacrosBuilder},
+ tt, ExpandResult, HirFileId, HirFileIdExt, MacroFileId, MacroFileIdExt,
},
hir_ty::{
consteval::ConstEvalError,
@@ -145,6 +149,7 @@ pub use {
},
// FIXME: Properly encapsulate mir
hir_ty::{mir, Interner as ChalkTyInterner},
+ intern::{sym, Symbol},
};
// These are negative re-exports: pub using these names is forbidden, they
@@ -258,7 +263,7 @@ impl Crate {
pub fn get_html_root_url(self: &Crate, db: &dyn HirDatabase) -> Option<String> {
// Look for #![doc(html_root_url = "...")]
let attrs = db.attrs(AttrDefId::ModuleId(self.root_module().into()));
- let doc_url = attrs.by_key("doc").find_string_value_in_tt("html_root_url");
+ let doc_url = attrs.by_key(&sym::doc).find_string_value_in_tt(&sym::html_root_url);
doc_url.map(|s| s.trim_matches('"').trim_end_matches('/').to_owned() + "/")
}
@@ -676,9 +681,9 @@ impl Module {
TypeOrConstParamId { parent, local_id },
))
});
- let res = type_params
- .chain(lifetime_params)
- .any(|p| db.attrs(AttrDefId::GenericParamId(p)).by_key("may_dangle").exists());
+ let res = type_params.chain(lifetime_params).any(|p| {
+ db.attrs(AttrDefId::GenericParamId(p)).by_key(&sym::may_dangle).exists()
+ });
Some(res)
})()
.unwrap_or(false);
@@ -828,19 +833,27 @@ fn macro_call_diagnostics(
let ValueResult { value: parse_errors, err } = &*e;
if let Some(err) = err {
let loc = db.lookup_intern_macro_call(macro_call_id);
- let (node, precise_location, macro_name, kind) = precise_macro_call_location(&loc.kind, db);
- let diag = match err {
- &hir_expand::ExpandError::UnresolvedProcMacro(krate) => {
- UnresolvedProcMacro { node, precise_location, macro_name, kind, krate }.into()
- }
- err => MacroError { node, precise_location, message: err.to_string() }.into(),
+ let file_id = loc.kind.file_id();
+ let node =
+ InFile::new(file_id, db.ast_id_map(file_id).get_erased(loc.kind.erased_ast_id()));
+ let (message, error) = err.render_to_string(db.upcast());
+ let precise_location = if err.span().anchor.file_id == file_id {
+ Some(
+ err.span().range
+ + db.ast_id_map(err.span().anchor.file_id.into())
+ .get_erased(err.span().anchor.ast_id)
+ .text_range()
+ .start(),
+ )
+ } else {
+ None
};
- acc.push(diag);
+ acc.push(MacroError { node, precise_location, message, error }.into());
}
if !parse_errors.is_empty() {
let loc = db.lookup_intern_macro_call(macro_call_id);
- let (node, precise_location, _, _) = precise_macro_call_location(&loc.kind, db);
+ let (node, precise_location) = precise_macro_call_location(&loc.kind, db);
acc.push(
MacroExpansionParseError { node, precise_location, errors: parse_errors.clone() }
.into(),
@@ -890,6 +903,19 @@ fn emit_def_diagnostic_(
acc.push(UnresolvedExternCrate { decl: InFile::new(ast.file_id, item) }.into());
}
+ DefDiagnosticKind::MacroError { ast, path, err } => {
+ let item = ast.to_ptr(db.upcast());
+ let (message, error) = err.render_to_string(db.upcast());
+ acc.push(
+ MacroError {
+ node: InFile::new(ast.file_id, item.syntax_node_ptr()),
+ precise_location: None,
+ message: format!("{}: {message}", path.display(db.upcast())),
+ error,
+ }
+ .into(),
+ )
+ }
DefDiagnosticKind::UnresolvedImport { id, index } => {
let file_id = id.file_id();
let item_tree = id.item_tree(db.upcast());
@@ -901,22 +927,93 @@ fn emit_def_diagnostic_(
);
}
- DefDiagnosticKind::UnconfiguredCode { ast, cfg, opts } => {
- let item = ast.to_ptr(db.upcast());
- acc.push(
- InactiveCode { node: ast.with_value(item), cfg: cfg.clone(), opts: opts.clone() }
- .into(),
- );
- }
- DefDiagnosticKind::UnresolvedProcMacro { ast, krate } => {
- let (node, precise_location, macro_name, kind) = precise_macro_call_location(ast, db);
- acc.push(
- UnresolvedProcMacro { node, precise_location, macro_name, kind, krate: *krate }
+ DefDiagnosticKind::UnconfiguredCode { tree, item, cfg, opts } => {
+ let item_tree = tree.item_tree(db.upcast());
+ let ast_id_map = db.ast_id_map(tree.file_id());
+ // FIXME: This parses... We could probably store relative ranges for the children things
+ // here in the item tree?
+ (|| {
+ let process_field_list =
+ |field_list: Option<_>, idx: ItemTreeFieldId| match field_list? {
+ ast::FieldList::RecordFieldList(it) => Some(SyntaxNodePtr::new(
+ it.fields().nth(idx.into_raw().into_u32() as usize)?.syntax(),
+ )),
+ ast::FieldList::TupleFieldList(it) => Some(SyntaxNodePtr::new(
+ it.fields().nth(idx.into_raw().into_u32() as usize)?.syntax(),
+ )),
+ };
+ let ptr = match *item {
+ AttrOwner::ModItem(it) => {
+ ast_id_map.get(it.ast_id(&item_tree)).syntax_node_ptr()
+ }
+ AttrOwner::TopLevel => ast_id_map.root(),
+ AttrOwner::Variant(it) => {
+ ast_id_map.get(item_tree[it].ast_id).syntax_node_ptr()
+ }
+ AttrOwner::Field(FieldParent::Variant(parent), idx) => process_field_list(
+ ast_id_map
+ .get(item_tree[parent].ast_id)
+ .to_node(&db.parse_or_expand(tree.file_id()))
+ .field_list(),
+ idx,
+ )?,
+ AttrOwner::Field(FieldParent::Struct(parent), idx) => process_field_list(
+ ast_id_map
+ .get(item_tree[parent.index()].ast_id)
+ .to_node(&db.parse_or_expand(tree.file_id()))
+ .field_list(),
+ idx,
+ )?,
+ AttrOwner::Field(FieldParent::Union(parent), idx) => SyntaxNodePtr::new(
+ ast_id_map
+ .get(item_tree[parent.index()].ast_id)
+ .to_node(&db.parse_or_expand(tree.file_id()))
+ .record_field_list()?
+ .fields()
+ .nth(idx.into_raw().into_u32() as usize)?
+ .syntax(),
+ ),
+ AttrOwner::Param(parent, idx) => SyntaxNodePtr::new(
+ ast_id_map
+ .get(item_tree[parent.index()].ast_id)
+ .to_node(&db.parse_or_expand(tree.file_id()))
+ .param_list()?
+ .params()
+ .nth(idx.into_raw().into_u32() as usize)?
+ .syntax(),
+ ),
+ AttrOwner::TypeOrConstParamData(parent, idx) => SyntaxNodePtr::new(
+ ast_id_map
+ .get(parent.ast_id(&item_tree))
+ .to_node(&db.parse_or_expand(tree.file_id()))
+ .generic_param_list()?
+ .type_or_const_params()
+ .nth(idx.into_raw().into_u32() as usize)?
+ .syntax(),
+ ),
+ AttrOwner::LifetimeParamData(parent, idx) => SyntaxNodePtr::new(
+ ast_id_map
+ .get(parent.ast_id(&item_tree))
+ .to_node(&db.parse_or_expand(tree.file_id()))
+ .generic_param_list()?
+ .lifetime_params()
+ .nth(idx.into_raw().into_u32() as usize)?
+ .syntax(),
+ ),
+ };
+ acc.push(
+ InactiveCode {
+ node: InFile::new(tree.file_id(), ptr),
+ cfg: cfg.clone(),
+ opts: opts.clone(),
+ }
.into(),
- );
+ );
+ Some(())
+ })();
}
DefDiagnosticKind::UnresolvedMacroCall { ast, path } => {
- let (node, precise_location, _, _) = precise_macro_call_location(ast, db);
+ let (node, precise_location) = precise_macro_call_location(ast, db);
acc.push(
UnresolvedMacroCall {
macro_call: node,
@@ -985,7 +1082,7 @@ fn emit_def_diagnostic_(
fn precise_macro_call_location(
ast: &MacroCallKind,
db: &dyn HirDatabase,
-) -> (InFile<SyntaxNodePtr>, Option<TextRange>, Option<String>, MacroKind) {
+) -> (InFile<SyntaxNodePtr>, Option<TextRange>) {
// FIXME: maybe we actually want slightly different ranges for the different macro diagnostics
// - e.g. the full attribute for macro errors, but only the name for name resolution
match ast {
@@ -997,8 +1094,6 @@ fn precise_macro_call_location(
.and_then(|it| it.segment())
.and_then(|it| it.name_ref())
.map(|it| it.syntax().text_range()),
- node.path().and_then(|it| it.segment()).map(|it| it.to_string()),
- MacroKind::ProcMacro,
)
}
MacroCallKind::Derive { ast_id, derive_attr_index, derive_index, .. } => {
@@ -1027,8 +1122,6 @@ fn precise_macro_call_location(
(
ast_id.with_value(SyntaxNodePtr::from(AstPtr::new(&node))),
token.as_ref().map(|tok| tok.text_range()),
- token.as_ref().map(ToString::to_string),
- MacroKind::Derive,
)
}
MacroCallKind::Attr { ast_id, invoc_attr_index, .. } => {
@@ -1043,12 +1136,6 @@ fn precise_macro_call_location(
(
ast_id.with_value(SyntaxNodePtr::from(AstPtr::new(&attr))),
Some(attr.syntax().text_range()),
- attr.path()
- .and_then(|path| path.segment())
- .and_then(|seg| seg.name_ref())
- .as_ref()
- .map(ToString::to_string),
- MacroKind::Attr,
)
}
}
@@ -1712,20 +1799,28 @@ impl DefWithBody {
BodyDiagnostic::InactiveCode { node, cfg, opts } => {
InactiveCode { node: *node, cfg: cfg.clone(), opts: opts.clone() }.into()
}
- BodyDiagnostic::MacroError { node, message } => MacroError {
- node: (*node).map(|it| it.into()),
- precise_location: None,
- message: message.to_string(),
- }
- .into(),
- BodyDiagnostic::UnresolvedProcMacro { node, krate } => UnresolvedProcMacro {
- node: (*node).map(|it| it.into()),
- precise_location: None,
- macro_name: None,
- kind: MacroKind::ProcMacro,
- krate: *krate,
+ BodyDiagnostic::MacroError { node, err } => {
+ let (message, error) = err.render_to_string(db.upcast());
+
+ let precise_location = if err.span().anchor.file_id == node.file_id {
+ Some(
+ err.span().range
+ + db.ast_id_map(err.span().anchor.file_id.into())
+ .get_erased(err.span().anchor.ast_id)
+ .text_range()
+ .start(),
+ )
+ } else {
+ None
+ };
+ MacroError {
+ node: (*node).map(|it| it.into()),
+ precise_location,
+ message,
+ error,
+ }
+ .into()
}
- .into(),
BodyDiagnostic::UnresolvedMacroCall { node, path } => UnresolvedMacroCall {
macro_call: (*node).map(|ast_ptr| ast_ptr.into()),
precise_location: None,
@@ -1801,6 +1896,16 @@ impl DefWithBody {
Some(s) => s.map(|it| it.into()),
None => continue,
},
+ mir::MirSpan::BindingId(b) => {
+ match source_map
+ .patterns_for_binding(b)
+ .iter()
+ .find_map(|p| source_map.pat_syntax(*p).ok())
+ {
+ Some(s) => s.map(|it| it.into()),
+ None => continue,
+ }
+ }
mir::MirSpan::Unknown => continue,
};
acc.push(
@@ -1817,8 +1922,8 @@ impl DefWithBody {
let Some(&local) = mir_body.binding_locals.get(binding_id) else {
continue;
};
- if body[binding_id]
- .definitions
+ if source_map
+ .patterns_for_binding(binding_id)
.iter()
.any(|&pat| source_map.pat_syntax(pat).is_err())
{
@@ -1826,7 +1931,7 @@ impl DefWithBody {
continue;
}
let mut need_mut = &mol[local];
- if body[binding_id].name.as_str() == Some("self")
+ if body[binding_id].name == sym::self_.clone()
&& need_mut == &mir::MutabilityReason::Unused
{
need_mut = &mir::MutabilityReason::Not;
@@ -1836,7 +1941,7 @@ impl DefWithBody {
match (need_mut, is_mut) {
(mir::MutabilityReason::Unused, _) => {
- let should_ignore = matches!(body[binding_id].name.as_str(), Some(it) if it.starts_with('_'));
+ let should_ignore = body[binding_id].name.as_str().starts_with('_');
if !should_ignore {
acc.push(UnusedVariable { local }.into())
}
@@ -1854,6 +1959,16 @@ impl DefWithBody {
Ok(s) => s.map(|it| it.into()),
Err(_) => continue,
},
+ mir::MirSpan::BindingId(b) => {
+ match source_map
+ .patterns_for_binding(*b)
+ .iter()
+ .find_map(|p| source_map.pat_syntax(*p).ok())
+ {
+ Some(s) => s.map(|it| it.into()),
+ None => continue,
+ }
+ }
mir::MirSpan::SelfParam => match source_map.self_param_syntax()
{
Some(s) => s.map(|it| it.into()),
@@ -1866,7 +1981,7 @@ impl DefWithBody {
}
(mir::MutabilityReason::Not, true) => {
if !infer.mutated_bindings_in_closure.contains(&binding_id) {
- let should_ignore = matches!(body[binding_id].name.as_str(), Some(it) if it.starts_with('_'));
+ let should_ignore = body[binding_id].name.as_str().starts_with('_');
if !should_ignore {
acc.push(UnusedMut { local }.into())
}
@@ -1972,7 +2087,6 @@ impl Function {
return Type::new_with_resolver_inner(db, &resolver, output_eq.ty).into();
}
}
- never!("Async fn ret_type should be impl Future");
None
}
@@ -2087,14 +2201,14 @@ impl Function {
/// is this a `fn main` or a function with an `export_name` of `main`?
pub fn is_main(self, db: &dyn HirDatabase) -> bool {
let data = db.function_data(self.id);
- data.attrs.export_name() == Some("main")
- || self.module(db).is_crate_root() && data.name.to_smol_str() == "main"
+ data.attrs.export_name() == Some(&sym::main)
+ || self.module(db).is_crate_root() && data.name == sym::main
}
/// Is this a function with an `export_name` of `main`?
pub fn exported_main(self, db: &dyn HirDatabase) -> bool {
let data = db.function_data(self.id);
- data.attrs.export_name() == Some("main")
+ data.attrs.export_name() == Some(&sym::main)
}
/// Does this function have the ignore attribute?
@@ -2588,7 +2702,7 @@ pub struct StaticLifetime;
impl StaticLifetime {
pub fn name(self) -> Name {
- known::STATIC_LIFETIME
+ Name::new_symbol_root(sym::tick_static.clone())
}
}
@@ -3199,7 +3313,7 @@ impl LocalSource {
}
}
- pub fn original_file(&self, db: &dyn HirDatabase) -> FileId {
+ pub fn original_file(&self, db: &dyn HirDatabase) -> EditionedFileId {
self.source.file_id.original_file(db.upcast())
}
@@ -3248,7 +3362,7 @@ impl Local {
}
pub fn is_self(self, db: &dyn HirDatabase) -> bool {
- self.name(db) == name![self]
+ self.name(db) == sym::self_.clone()
}
pub fn is_mut(self, db: &dyn HirDatabase) -> bool {
@@ -3287,8 +3401,8 @@ impl Local {
source: source.map(|ast| Either::Right(ast.to_node(&root))),
}]
}
- _ => body[self.binding_id]
- .definitions
+ _ => source_map
+ .patterns_for_binding(self.binding_id)
.iter()
.map(|&definition| {
let src = source_map.pat_syntax(definition).unwrap(); // Hmm...
@@ -3316,8 +3430,8 @@ impl Local {
source: source.map(|ast| Either::Right(ast.to_node(&root))),
}
}
- _ => body[self.binding_id]
- .definitions
+ _ => source_map
+ .patterns_for_binding(self.binding_id)
.first()
.map(|&definition| {
let src = source_map.pat_syntax(definition).unwrap(); // Hmm...
@@ -3379,23 +3493,27 @@ impl BuiltinAttr {
if let builtin @ Some(_) = Self::builtin(name) {
return builtin;
}
- let idx =
- db.crate_def_map(krate.id).registered_attrs().iter().position(|it| it == name)? as u32;
+ let idx = db
+ .crate_def_map(krate.id)
+ .registered_attrs()
+ .iter()
+ .position(|it| it.as_str() == name)? as u32;
Some(BuiltinAttr { krate: Some(krate.id), idx })
}
fn builtin(name: &str) -> Option<Self> {
- hir_expand::inert_attr_macro::find_builtin_attr_idx(name)
+ hir_expand::inert_attr_macro::find_builtin_attr_idx(&Symbol::intern(name))
.map(|idx| BuiltinAttr { krate: None, idx: idx as u32 })
}
- pub fn name(&self, db: &dyn HirDatabase) -> SmolStr {
- // FIXME: Return a `Name` here
+ pub fn name(&self, db: &dyn HirDatabase) -> Name {
match self.krate {
- Some(krate) => db.crate_def_map(krate).registered_attrs()[self.idx as usize].clone(),
- None => {
- SmolStr::new(hir_expand::inert_attr_macro::INERT_ATTRIBUTES[self.idx as usize].name)
- }
+ Some(krate) => Name::new_symbol_root(
+ db.crate_def_map(krate).registered_attrs()[self.idx as usize].clone(),
+ ),
+ None => Name::new_symbol_root(Symbol::intern(
+ hir_expand::inert_attr_macro::INERT_ATTRIBUTES[self.idx as usize].name,
+ )),
}
}
@@ -3419,13 +3537,15 @@ impl ToolModule {
pub(crate) fn by_name(db: &dyn HirDatabase, krate: Crate, name: &str) -> Option<Self> {
let krate = krate.id;
let idx =
- db.crate_def_map(krate).registered_tools().iter().position(|it| it == name)? as u32;
+ db.crate_def_map(krate).registered_tools().iter().position(|it| it.as_str() == name)?
+ as u32;
Some(ToolModule { krate, idx })
}
- pub fn name(&self, db: &dyn HirDatabase) -> SmolStr {
- // FIXME: Return a `Name` here
- db.crate_def_map(self.krate).registered_tools()[self.idx as usize].clone()
+ pub fn name(&self, db: &dyn HirDatabase) -> Name {
+ Name::new_symbol_root(
+ db.crate_def_map(self.krate).registered_tools()[self.idx as usize].clone(),
+ )
}
}
@@ -3694,6 +3814,10 @@ impl Impl {
inherent.all_impls().chain(trait_.all_impls()).map(Self::from).collect()
}
+ pub fn all_in_module(db: &dyn HirDatabase, module: Module) -> Vec<Impl> {
+ module.id.def_map(db.upcast())[module.id.local_id].scope.impls().map(Into::into).collect()
+ }
+
pub fn all_for_type(db: &dyn HirDatabase, Type { ty, env }: Type) -> Vec<Impl> {
let def_crates = match method_resolution::def_crates(db, &ty, env.krate) {
Some(def_crates) => def_crates,
@@ -4600,7 +4724,7 @@ impl Type {
) -> impl Iterator<Item = SmolStr> + 'a {
// iterate the lifetime
self.as_adt()
- .and_then(|a| a.lifetime(db).map(|lt| lt.name.to_smol_str()))
+ .and_then(|a| a.lifetime(db).map(|lt| lt.name.display_no_db().to_smolstr()))
.into_iter()
// add the type and const parameters
.chain(self.type_and_const_arguments(db))