Unnamed repository; edit this file 'description' to name the repository.
Diffstat (limited to 'crates/hir/src/source_analyzer.rs')
-rw-r--r--crates/hir/src/source_analyzer.rs206
1 files changed, 111 insertions, 95 deletions
diff --git a/crates/hir/src/source_analyzer.rs b/crates/hir/src/source_analyzer.rs
index c1a75ce7e5..ec2ccf8cba 100644
--- a/crates/hir/src/source_analyzer.rs
+++ b/crates/hir/src/source_analyzer.rs
@@ -10,7 +10,9 @@ use std::iter::{self, once};
use crate::{
Adt, AssocItem, BindingMode, BuiltinAttr, BuiltinType, Callable, Const, DeriveHelper, Field,
Function, GenericSubstitution, Local, Macro, ModuleDef, Static, Struct, ToolModule, Trait,
- TraitAlias, TupleField, Type, TypeAlias, Variant, db::HirDatabase, semantics::PathResolution,
+ TraitAlias, TupleField, Type, TypeAlias, Variant,
+ db::HirDatabase,
+ semantics::{PathResolution, PathResolutionPerNs},
};
use either::Either;
use hir_def::{
@@ -29,7 +31,7 @@ use hir_def::{
type_ref::{Mutability, TypeRefId},
};
use hir_expand::{
- HirFileId, InFile, MacroCallId,
+ HirFileId, InFile,
mod_path::{ModPath, PathKind, path},
name::{AsName, Name},
};
@@ -57,9 +59,9 @@ use triomphe::Arc;
/// `SourceAnalyzer` is a convenience wrapper which exposes HIR API in terms of
/// original source files. It should not be used inside the HIR itself.
#[derive(Debug)]
-pub(crate) struct SourceAnalyzer {
+pub(crate) struct SourceAnalyzer<'db> {
pub(crate) file_id: HirFileId,
- pub(crate) resolver: Resolver,
+ pub(crate) resolver: Resolver<'db>,
pub(crate) body_or_sig: Option<BodyOrSig>,
}
@@ -85,32 +87,32 @@ pub(crate) enum BodyOrSig {
},
}
-impl SourceAnalyzer {
+impl<'db> SourceAnalyzer<'db> {
pub(crate) fn new_for_body(
- db: &dyn HirDatabase,
+ db: &'db dyn HirDatabase,
def: DefWithBodyId,
node: InFile<&SyntaxNode>,
offset: Option<TextSize>,
- ) -> SourceAnalyzer {
+ ) -> SourceAnalyzer<'db> {
Self::new_for_body_(db, def, node, offset, Some(db.infer(def)))
}
pub(crate) fn new_for_body_no_infer(
- db: &dyn HirDatabase,
+ db: &'db dyn HirDatabase,
def: DefWithBodyId,
node: InFile<&SyntaxNode>,
offset: Option<TextSize>,
- ) -> SourceAnalyzer {
+ ) -> SourceAnalyzer<'db> {
Self::new_for_body_(db, def, node, offset, None)
}
pub(crate) fn new_for_body_(
- db: &dyn HirDatabase,
+ db: &'db dyn HirDatabase,
def: DefWithBodyId,
node @ InFile { file_id, .. }: InFile<&SyntaxNode>,
offset: Option<TextSize>,
infer: Option<Arc<InferenceResult>>,
- ) -> SourceAnalyzer {
+ ) -> SourceAnalyzer<'db> {
let (body, source_map) = db.body_with_source_map(def);
let scopes = db.expr_scopes(def);
let scope = match offset {
@@ -134,11 +136,11 @@ impl SourceAnalyzer {
}
pub(crate) fn new_generic_def(
- db: &dyn HirDatabase,
+ db: &'db dyn HirDatabase,
def: GenericDefId,
InFile { file_id, .. }: InFile<&SyntaxNode>,
_offset: Option<TextSize>,
- ) -> SourceAnalyzer {
+ ) -> SourceAnalyzer<'db> {
let (_params, store, source_map) = db.generic_params_and_store_and_source_map(def);
let resolver = def.resolver(db);
SourceAnalyzer {
@@ -149,11 +151,11 @@ impl SourceAnalyzer {
}
pub(crate) fn new_variant_body(
- db: &dyn HirDatabase,
+ db: &'db dyn HirDatabase,
def: VariantId,
InFile { file_id, .. }: InFile<&SyntaxNode>,
_offset: Option<TextSize>,
- ) -> SourceAnalyzer {
+ ) -> SourceAnalyzer<'db> {
let (fields, source_map) = db.variant_fields_with_source_map(def);
let resolver = def.resolver(db);
SourceAnalyzer {
@@ -168,9 +170,9 @@ impl SourceAnalyzer {
}
pub(crate) fn new_for_resolver(
- resolver: Resolver,
+ resolver: Resolver<'db>,
node: InFile<&SyntaxNode>,
- ) -> SourceAnalyzer {
+ ) -> SourceAnalyzer<'db> {
SourceAnalyzer { resolver, body_or_sig: None, file_id: node.file_id }
}
@@ -216,11 +218,7 @@ impl SourceAnalyzer {
})
}
- pub(crate) fn expansion(&self, node: InFile<&ast::MacroCall>) -> Option<MacroCallId> {
- self.store_sm()?.expansion(node)
- }
-
- fn trait_environment(&self, db: &dyn HirDatabase) -> Arc<TraitEnvironment> {
+ fn trait_environment(&self, db: &'db dyn HirDatabase) -> Arc<TraitEnvironment> {
self.body_().map(|(def, ..)| def).map_or_else(
|| TraitEnvironment::empty(self.resolver.krate()),
|def| db.trait_environment_for_body(def),
@@ -259,7 +257,7 @@ impl SourceAnalyzer {
infer.expr_adjustments.get(&expr_id).map(|v| &**v)
}
- pub(crate) fn type_of_type(&self, db: &dyn HirDatabase, ty: &ast::Type) -> Option<Type> {
+ pub(crate) fn type_of_type(&self, db: &'db dyn HirDatabase, ty: &ast::Type) -> Option<Type> {
let type_ref = self.type_id(ty)?;
let ty = TyLoweringContext::new(
db,
@@ -277,7 +275,7 @@ impl SourceAnalyzer {
pub(crate) fn type_of_expr(
&self,
- db: &dyn HirDatabase,
+ db: &'db dyn HirDatabase,
expr: &ast::Expr,
) -> Option<(Type, Option<Type>)> {
let expr_id = self.expr_id(expr.clone())?;
@@ -293,7 +291,7 @@ impl SourceAnalyzer {
pub(crate) fn type_of_pat(
&self,
- db: &dyn HirDatabase,
+ db: &'db dyn HirDatabase,
pat: &ast::Pat,
) -> Option<(Type, Option<Type>)> {
let expr_or_pat_id = self.pat_id(pat)?;
@@ -316,7 +314,7 @@ impl SourceAnalyzer {
pub(crate) fn type_of_binding_in_pat(
&self,
- db: &dyn HirDatabase,
+ db: &'db dyn HirDatabase,
pat: &ast::IdentPat,
) -> Option<Type> {
let binding_id = self.binding_id_of_pat(pat)?;
@@ -328,7 +326,7 @@ impl SourceAnalyzer {
pub(crate) fn type_of_self(
&self,
- db: &dyn HirDatabase,
+ db: &'db dyn HirDatabase,
_param: &ast::SelfParam,
) -> Option<Type> {
let binding = self.body()?.self_param?;
@@ -338,7 +336,7 @@ impl SourceAnalyzer {
pub(crate) fn binding_mode_of_pat(
&self,
- _db: &dyn HirDatabase,
+ _db: &'db dyn HirDatabase,
pat: &ast::IdentPat,
) -> Option<BindingMode> {
let id = self.pat_id(&pat.clone().into())?;
@@ -353,7 +351,7 @@ impl SourceAnalyzer {
}
pub(crate) fn pattern_adjustments(
&self,
- db: &dyn HirDatabase,
+ db: &'db dyn HirDatabase,
pat: &ast::Pat,
) -> Option<SmallVec<[Type; 1]>> {
let pat_id = self.pat_id(pat)?;
@@ -370,7 +368,7 @@ impl SourceAnalyzer {
pub(crate) fn resolve_method_call_as_callable(
&self,
- db: &dyn HirDatabase,
+ db: &'db dyn HirDatabase,
call: &ast::MethodCallExpr,
) -> Option<Callable> {
let expr_id = self.expr_id(call.clone().into())?.as_expr()?;
@@ -384,7 +382,7 @@ impl SourceAnalyzer {
pub(crate) fn resolve_method_call(
&self,
- db: &dyn HirDatabase,
+ db: &'db dyn HirDatabase,
call: &ast::MethodCallExpr,
) -> Option<Function> {
let expr_id = self.expr_id(call.clone().into())?.as_expr()?;
@@ -395,7 +393,7 @@ impl SourceAnalyzer {
pub(crate) fn resolve_method_call_fallback(
&self,
- db: &dyn HirDatabase,
+ db: &'db dyn HirDatabase,
call: &ast::MethodCallExpr,
) -> Option<(Either<Function, Field>, Option<GenericSubstitution>)> {
let expr_id = self.expr_id(call.clone().into())?.as_expr()?;
@@ -419,7 +417,7 @@ impl SourceAnalyzer {
pub(crate) fn resolve_expr_as_callable(
&self,
- db: &dyn HirDatabase,
+ db: &'db dyn HirDatabase,
call: &ast::Expr,
) -> Option<Callable> {
let (orig, adjusted) = self.type_of_expr(db, &call.clone())?;
@@ -441,7 +439,7 @@ impl SourceAnalyzer {
&self,
field_expr: ExprId,
infer: &InferenceResult,
- db: &dyn HirDatabase,
+ db: &'db dyn HirDatabase,
) -> Option<GenericSubstitution> {
let body = self.store()?;
if let Expr::Field { expr: object_expr, name: _ } = body[field_expr] {
@@ -457,7 +455,7 @@ impl SourceAnalyzer {
pub(crate) fn resolve_field_fallback(
&self,
- db: &dyn HirDatabase,
+ db: &'db dyn HirDatabase,
field: &ast::FieldExpr,
) -> Option<(Either<Either<Field, TupleField>, Function>, Option<GenericSubstitution>)> {
let (def, ..) = self.body_()?;
@@ -490,7 +488,7 @@ impl SourceAnalyzer {
pub(crate) fn resolve_range_pat(
&self,
- db: &dyn HirDatabase,
+ db: &'db dyn HirDatabase,
range_pat: &ast::RangePat,
) -> Option<StructId> {
let path: ModPath = match (range_pat.op_kind()?, range_pat.start(), range_pat.end()) {
@@ -509,7 +507,7 @@ impl SourceAnalyzer {
pub(crate) fn resolve_range_expr(
&self,
- db: &dyn HirDatabase,
+ db: &'db dyn HirDatabase,
range_expr: &ast::RangeExpr,
) -> Option<StructId> {
let path: ModPath = match (range_expr.op_kind()?, range_expr.start(), range_expr.end()) {
@@ -529,7 +527,7 @@ impl SourceAnalyzer {
pub(crate) fn resolve_await_to_poll(
&self,
- db: &dyn HirDatabase,
+ db: &'db dyn HirDatabase,
await_expr: &ast::AwaitExpr,
) -> Option<FunctionId> {
let mut ty = self.ty_of_expr(await_expr.expr()?)?.clone();
@@ -566,7 +564,7 @@ impl SourceAnalyzer {
pub(crate) fn resolve_prefix_expr(
&self,
- db: &dyn HirDatabase,
+ db: &'db dyn HirDatabase,
prefix_expr: &ast::PrefixExpr,
) -> Option<FunctionId> {
let (op_trait, op_fn) = match prefix_expr.op_kind()? {
@@ -608,7 +606,7 @@ impl SourceAnalyzer {
pub(crate) fn resolve_index_expr(
&self,
- db: &dyn HirDatabase,
+ db: &'db dyn HirDatabase,
index_expr: &ast::IndexExpr,
) -> Option<FunctionId> {
let base_ty = self.ty_of_expr(index_expr.base()?)?;
@@ -640,7 +638,7 @@ impl SourceAnalyzer {
pub(crate) fn resolve_bin_expr(
&self,
- db: &dyn HirDatabase,
+ db: &'db dyn HirDatabase,
binop_expr: &ast::BinExpr,
) -> Option<FunctionId> {
let op = binop_expr.op_kind()?;
@@ -661,7 +659,7 @@ impl SourceAnalyzer {
pub(crate) fn resolve_try_expr(
&self,
- db: &dyn HirDatabase,
+ db: &'db dyn HirDatabase,
try_expr: &ast::TryExpr,
) -> Option<FunctionId> {
let ty = self.ty_of_expr(try_expr.expr()?)?;
@@ -680,7 +678,7 @@ impl SourceAnalyzer {
pub(crate) fn resolve_record_field(
&self,
- db: &dyn HirDatabase,
+ db: &'db dyn HirDatabase,
field: &ast::RecordExprField,
) -> Option<(Field, Option<Local>, Type, GenericSubstitution)> {
let record_expr = ast::RecordExpr::cast(field.syntax().parent().and_then(|p| p.parent())?)?;
@@ -724,7 +722,7 @@ impl SourceAnalyzer {
pub(crate) fn resolve_record_pat_field(
&self,
- db: &dyn HirDatabase,
+ db: &'db dyn HirDatabase,
field: &ast::RecordPatField,
) -> Option<(Field, Type, GenericSubstitution)> {
let field_name = field.field_name()?.as_name();
@@ -743,25 +741,9 @@ impl SourceAnalyzer {
))
}
- pub(crate) fn resolve_macro_call(
- &self,
- db: &dyn HirDatabase,
- macro_call: InFile<&ast::MacroCall>,
- ) -> Option<Macro> {
- let bs = self.store_sm()?;
- bs.expansion(macro_call).and_then(|it| {
- // FIXME: Block def maps
- let def = it.lookup(db).def;
- db.crate_def_map(def.krate)
- .macro_def_to_macro_id
- .get(&def.kind.erased_ast_id())
- .map(|it| (*it).into())
- })
- }
-
pub(crate) fn resolve_bind_pat_to_const(
&self,
- db: &dyn HirDatabase,
+ db: &'db dyn HirDatabase,
pat: &ast::IdentPat,
) -> Option<ModuleDef> {
let expr_or_pat_id = self.pat_id(&pat.clone().into())?;
@@ -795,7 +777,7 @@ impl SourceAnalyzer {
pub(crate) fn resolve_offset_of_field(
&self,
- db: &dyn HirDatabase,
+ db: &'db dyn HirDatabase,
name_ref: &ast::NameRef,
) -> Option<(Either<crate::Variant, crate::Field>, GenericSubstitution)> {
let offset_of_expr = ast::OffsetOfExpr::cast(name_ref.syntax().parent()?)?;
@@ -867,7 +849,7 @@ impl SourceAnalyzer {
pub(crate) fn resolve_path(
&self,
- db: &dyn HirDatabase,
+ db: &'db dyn HirDatabase,
path: &ast::Path,
) -> Option<(PathResolution, Option<GenericSubstitution>)> {
let parent = path.syntax().parent();
@@ -1159,7 +1141,9 @@ impl SourceAnalyzer {
prefer_value_ns,
name_hygiene(db, InFile::new(self.file_id, path.syntax())),
Some(&store),
- )?;
+ false,
+ )
+ .any()?;
let subst = (|| {
let parent = parent()?;
let ty = if let Some(expr) = ast::Expr::cast(parent.clone()) {
@@ -1209,9 +1193,29 @@ impl SourceAnalyzer {
}
}
- pub(crate) fn record_literal_missing_fields(
+ pub(crate) fn resolve_hir_path_per_ns(
&self,
db: &dyn HirDatabase,
+ path: &ast::Path,
+ ) -> Option<PathResolutionPerNs> {
+ let mut collector = ExprCollector::new(db, self.resolver.module(), self.file_id);
+ let hir_path =
+ collector.lower_path(path.clone(), &mut ExprCollector::impl_trait_error_allocator)?;
+ let store = collector.store.finish();
+ Some(resolve_hir_path_(
+ db,
+ &self.resolver,
+ &hir_path,
+ false,
+ name_hygiene(db, InFile::new(self.file_id, path.syntax())),
+ Some(&store),
+ true,
+ ))
+ }
+
+ pub(crate) fn record_literal_missing_fields(
+ &self,
+ db: &'db dyn HirDatabase,
literal: &ast::RecordExpr,
) -> Option<Vec<(Field, Type)>> {
let body = self.store()?;
@@ -1234,7 +1238,7 @@ impl SourceAnalyzer {
pub(crate) fn record_pattern_missing_fields(
&self,
- db: &dyn HirDatabase,
+ db: &'db dyn HirDatabase,
pattern: &ast::RecordPat,
) -> Option<Vec<(Field, Type)>> {
let body = self.store()?;
@@ -1251,7 +1255,7 @@ impl SourceAnalyzer {
fn missing_fields(
&self,
- db: &dyn HirDatabase,
+ db: &'db dyn HirDatabase,
substs: &Substitution,
variant: VariantId,
missing_fields: Vec<LocalFieldId>,
@@ -1268,18 +1272,6 @@ impl SourceAnalyzer {
.collect()
}
- pub(crate) fn expand(
- &self,
- db: &dyn HirDatabase,
- macro_call: InFile<&ast::MacroCall>,
- ) -> Option<MacroCallId> {
- self.store_sm().and_then(|bs| bs.expansion(macro_call)).or_else(|| {
- self.resolver.item_scope().macro_invoc(
- macro_call.with_value(db.ast_id_map(macro_call.file_id).ast_id(macro_call.value)),
- )
- })
- }
-
pub(crate) fn resolve_variant(&self, record_lit: ast::RecordExpr) -> Option<VariantId> {
let infer = self.infer()?;
let expr_id = self.expr_id(record_lit.into())?;
@@ -1288,7 +1280,7 @@ impl SourceAnalyzer {
pub(crate) fn is_unsafe_macro_call_expr(
&self,
- db: &dyn HirDatabase,
+ db: &'db dyn HirDatabase,
macro_expr: InFile<&ast::MacroExpr>,
) -> bool {
if let Some((def, body, sm, Some(infer))) = self.body_() {
@@ -1311,9 +1303,10 @@ impl SourceAnalyzer {
false
}
+ /// Returns the range of the implicit template argument and its resolution at the given `offset`
pub(crate) fn resolve_offset_in_format_args(
&self,
- db: &dyn HirDatabase,
+ db: &'db dyn HirDatabase,
format_args: InFile<&ast::FormatArgsExpr>,
offset: TextSize,
) -> Option<(TextRange, Option<PathResolution>)> {
@@ -1384,7 +1377,7 @@ impl SourceAnalyzer {
fn resolve_impl_method_or_trait_def(
&self,
- db: &dyn HirDatabase,
+ db: &'db dyn HirDatabase,
func: FunctionId,
substs: Substitution,
) -> FunctionId {
@@ -1393,7 +1386,7 @@ impl SourceAnalyzer {
fn resolve_impl_method_or_trait_def_with_subst(
&self,
- db: &dyn HirDatabase,
+ db: &'db dyn HirDatabase,
func: FunctionId,
substs: Substitution,
) -> (FunctionId, Substitution) {
@@ -1407,7 +1400,7 @@ impl SourceAnalyzer {
fn resolve_impl_const_or_trait_def_with_subst(
&self,
- db: &dyn HirDatabase,
+ db: &'db dyn HirDatabase,
const_id: ConstId,
subs: Substitution,
) -> (ConstId, Substitution) {
@@ -1421,7 +1414,7 @@ impl SourceAnalyzer {
fn lang_trait_fn(
&self,
- db: &dyn HirDatabase,
+ db: &'db dyn HirDatabase,
lang_trait: LangItem,
method_name: &Name,
) -> Option<(TraitId, FunctionId)> {
@@ -1527,18 +1520,18 @@ fn adjust(
#[inline]
pub(crate) fn resolve_hir_path(
db: &dyn HirDatabase,
- resolver: &Resolver,
+ resolver: &Resolver<'_>,
path: &Path,
hygiene: HygieneId,
store: Option<&ExpressionStore>,
) -> Option<PathResolution> {
- resolve_hir_path_(db, resolver, path, false, hygiene, store)
+ resolve_hir_path_(db, resolver, path, false, hygiene, store, false).any()
}
#[inline]
pub(crate) fn resolve_hir_path_as_attr_macro(
db: &dyn HirDatabase,
- resolver: &Resolver,
+ resolver: &Resolver<'_>,
path: &Path,
) -> Option<Macro> {
resolver
@@ -1549,12 +1542,13 @@ pub(crate) fn resolve_hir_path_as_attr_macro(
fn resolve_hir_path_(
db: &dyn HirDatabase,
- resolver: &Resolver,
+ resolver: &Resolver<'_>,
path: &Path,
prefer_value_ns: bool,
hygiene: HygieneId,
store: Option<&ExpressionStore>,
-) -> Option<PathResolution> {
+ resolve_per_ns: bool,
+) -> PathResolutionPerNs {
let types = || {
let (ty, unresolved) = match path.type_anchor() {
Some(type_ref) => resolver.generic_def().and_then(|def| {
@@ -1635,14 +1629,36 @@ fn resolve_hir_path_(
.map(|(def, _)| PathResolution::Def(ModuleDef::Macro(def.into())))
};
- if prefer_value_ns { values().or_else(types) } else { types().or_else(values) }
- .or_else(items)
- .or_else(macros)
+ if resolve_per_ns {
+ PathResolutionPerNs {
+ type_ns: types().or_else(items),
+ value_ns: values(),
+ macro_ns: macros(),
+ }
+ } else {
+ let res = if prefer_value_ns {
+ values()
+ .map(|value_ns| PathResolutionPerNs::new(None, Some(value_ns), None))
+ .unwrap_or_else(|| PathResolutionPerNs::new(types(), None, None))
+ } else {
+ types()
+ .map(|type_ns| PathResolutionPerNs::new(Some(type_ns), None, None))
+ .unwrap_or_else(|| PathResolutionPerNs::new(None, values(), None))
+ };
+
+ if res.any().is_some() {
+ res
+ } else if let Some(type_ns) = items() {
+ PathResolutionPerNs::new(Some(type_ns), None, None)
+ } else {
+ PathResolutionPerNs::new(None, None, macros())
+ }
+ }
}
fn resolve_hir_value_path(
db: &dyn HirDatabase,
- resolver: &Resolver,
+ resolver: &Resolver<'_>,
body_owner: Option<DefWithBodyId>,
path: &Path,
hygiene: HygieneId,
@@ -1680,7 +1696,7 @@ fn resolve_hir_value_path(
/// then we know that `foo` in `my::foo::Bar` refers to the module, not the function.
fn resolve_hir_path_qualifier(
db: &dyn HirDatabase,
- resolver: &Resolver,
+ resolver: &Resolver<'_>,
path: &Path,
store: &ExpressionStore,
) -> Option<PathResolution> {