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.rs89
1 files changed, 54 insertions, 35 deletions
diff --git a/crates/hir/src/source_analyzer.rs b/crates/hir/src/source_analyzer.rs
index c24d196e1b..1374fa332c 100644
--- a/crates/hir/src/source_analyzer.rs
+++ b/crates/hir/src/source_analyzer.rs
@@ -5,21 +5,19 @@
//!
//! So, this modules should not be used during hir construction, it exists
//! purely for "IDE needs".
-use std::{
- iter::{self, once},
- sync::Arc,
-};
+use std::iter::{self, once};
use either::Either;
use hir_def::{
body::{
- self,
scope::{ExprScopes, ScopeId},
Body, BodySourceMap,
},
- expr::{ExprId, Pat, PatId},
+ hir::{BindingId, ExprId, Pat, PatId},
lang_item::LangItem,
+ lower::LowerCtx,
macro_id_to_def_id,
+ nameres::MacroSubNs,
path::{ModPath, Path, PathKind},
resolver::{resolver_for_scope, Resolver, TypeNs, ValueNs},
type_ref::Mutability,
@@ -39,7 +37,8 @@ use hir_ty::{
record_literal_missing_fields, record_pattern_missing_fields, unsafe_expressions,
UnsafeExpr,
},
- method_resolution::{self, lang_items_for_bin_op},
+ lang_items::lang_items_for_bin_op,
+ method_resolution::{self},
Adjustment, InferenceResult, Interner, Substitution, Ty, TyExt, TyKind, TyLoweringContext,
};
use itertools::Itertools;
@@ -48,6 +47,7 @@ use syntax::{
ast::{self, AstNode},
SyntaxKind, SyntaxNode, TextRange, TextSize,
};
+use triomphe::Arc;
use crate::{
db::HirDatabase, semantics::PathResolution, Adt, AssocItem, BindingMode, BuiltinAttr,
@@ -134,13 +134,22 @@ impl SourceAnalyzer {
self.body_source_map()?.node_pat(src)
}
+ fn binding_id_of_pat(&self, pat: &ast::IdentPat) -> Option<BindingId> {
+ let pat_id = self.pat_id(&pat.clone().into())?;
+ if let Pat::Bind { id, .. } = self.body()?.pats[pat_id] {
+ Some(id)
+ } else {
+ None
+ }
+ }
+
fn expand_expr(
&self,
db: &dyn HirDatabase,
expr: InFile<ast::MacroCall>,
) -> Option<InFile<ast::Expr>> {
let macro_file = self.body_source_map()?.node_macro_file(expr.as_ref())?;
- let expanded = db.parse_or_expand(macro_file)?;
+ let expanded = db.parse_or_expand(macro_file);
let res = if let Some(stmts) = ast::MacroStmts::cast(expanded.clone()) {
match stmts.expr()? {
ast::Expr::MacroExpr(mac) => {
@@ -199,6 +208,18 @@ impl SourceAnalyzer {
Some((mk_ty(ty), coerced.map(mk_ty)))
}
+ pub(crate) fn type_of_binding_in_pat(
+ &self,
+ db: &dyn HirDatabase,
+ pat: &ast::IdentPat,
+ ) -> Option<Type> {
+ let binding_id = self.binding_id_of_pat(pat)?;
+ let infer = self.infer.as_ref()?;
+ let ty = infer[binding_id].clone();
+ let mk_ty = |ty| Type::new_with_resolver(db, &self.resolver, ty);
+ Some(mk_ty(ty))
+ }
+
pub(crate) fn type_of_self(
&self,
db: &dyn HirDatabase,
@@ -215,9 +236,9 @@ impl SourceAnalyzer {
_db: &dyn HirDatabase,
pat: &ast::IdentPat,
) -> Option<BindingMode> {
- let pat_id = self.pat_id(&pat.clone().into())?;
+ let binding_id = self.binding_id_of_pat(pat)?;
let infer = self.infer.as_ref()?;
- infer.pat_binding_modes.get(&pat_id).map(|bm| match bm {
+ infer.binding_modes.get(binding_id).map(|bm| match bm {
hir_ty::BindingMode::Move => BindingMode::Move,
hir_ty::BindingMode::Ref(hir_ty::Mutability::Mut) => BindingMode::Ref(Mutability::Mut),
hir_ty::BindingMode::Ref(hir_ty::Mutability::Not) => {
@@ -420,7 +441,10 @@ impl SourceAnalyzer {
None
} else {
// Shorthand syntax, resolve to the local
- let path = ModPath::from_segments(PathKind::Plain, once(local_name.clone()));
+ let path = Path::from_known_path_with_no_generic(ModPath::from_segments(
+ PathKind::Plain,
+ once(local_name.clone()),
+ ));
match self.resolver.resolve_path_in_value_ns_fully(db.upcast(), &path) {
Some(ValueNs::LocalBinding(binding_id)) => {
Some(Local { binding_id, parent: self.resolver.body_owner()? })
@@ -459,9 +483,11 @@ impl SourceAnalyzer {
db: &dyn HirDatabase,
macro_call: InFile<&ast::MacroCall>,
) -> Option<Macro> {
- let ctx = body::LowerCtx::new(db.upcast(), macro_call.file_id);
+ let ctx = LowerCtx::with_file_id(db.upcast(), macro_call.file_id);
let path = macro_call.value.path().and_then(|ast| Path::from_src(ast, &ctx))?;
- self.resolver.resolve_path_as_macro(db.upcast(), path.mod_path()).map(|it| it.into())
+ self.resolver
+ .resolve_path_as_macro(db.upcast(), path.mod_path()?, Some(MacroSubNs::Bang))
+ .map(|it| it.into())
}
pub(crate) fn resolve_bind_pat_to_const(
@@ -571,7 +597,7 @@ impl SourceAnalyzer {
// This must be a normal source file rather than macro file.
let hygiene = Hygiene::new(db.upcast(), self.file_id);
- let ctx = body::LowerCtx::with_hygiene(db.upcast(), &hygiene);
+ let ctx = LowerCtx::with_hygiene(db.upcast(), &hygiene);
let hir_path = Path::from_src(path.clone(), &ctx)?;
// Case where path is a qualifier of a use tree, e.g. foo::bar::{Baz, Qux} where we are
@@ -655,7 +681,7 @@ impl SourceAnalyzer {
}
}
}
- return match resolve_hir_path_as_macro(db, &self.resolver, &hir_path) {
+ return match resolve_hir_path_as_attr_macro(db, &self.resolver, &hir_path) {
Some(m) => Some(PathResolution::Def(ModuleDef::Macro(m))),
// this labels any path that starts with a tool module as the tool itself, this is technically wrong
// but there is no benefit in differentiating these two cases for the time being
@@ -733,7 +759,7 @@ impl SourceAnalyzer {
let krate = self.resolver.krate();
let macro_call_id = macro_call.as_call_id(db.upcast(), krate, |path| {
self.resolver
- .resolve_path_as_macro(db.upcast(), &path)
+ .resolve_path_as_macro(db.upcast(), &path, Some(MacroSubNs::Bang))
.map(|it| macro_id_to_def_id(db.upcast(), it))
})?;
Some(macro_call_id.as_file()).filter(|it| it.expansion_level(db.upcast()) < 64)
@@ -801,15 +827,11 @@ impl SourceAnalyzer {
func: FunctionId,
substs: Substitution,
) -> FunctionId {
- let krate = self.resolver.krate();
let owner = match self.resolver.body_owner() {
Some(it) => it,
None => return func,
};
- let env = owner.as_generic_def_id().map_or_else(
- || Arc::new(hir_ty::TraitEnvironment::empty(krate)),
- |d| db.trait_environment(d),
- );
+ let env = db.trait_environment_for_body(owner);
method_resolution::lookup_impl_method(db, env, func, substs).0
}
@@ -819,15 +841,11 @@ impl SourceAnalyzer {
const_id: ConstId,
subs: Substitution,
) -> ConstId {
- let krate = self.resolver.krate();
let owner = match self.resolver.body_owner() {
Some(it) => it,
None => return const_id,
};
- let env = owner.as_generic_def_id().map_or_else(
- || Arc::new(hir_ty::TraitEnvironment::empty(krate)),
- |d| db.trait_environment(d),
- );
+ let env = db.trait_environment_for_body(owner);
method_resolution::lookup_impl_const(db, env, const_id, subs).0
}
@@ -941,12 +959,14 @@ pub(crate) fn resolve_hir_path(
}
#[inline]
-pub(crate) fn resolve_hir_path_as_macro(
+pub(crate) fn resolve_hir_path_as_attr_macro(
db: &dyn HirDatabase,
resolver: &Resolver,
path: &Path,
) -> Option<Macro> {
- resolver.resolve_path_as_macro(db.upcast(), path.mod_path()).map(Into::into)
+ resolver
+ .resolve_path_as_macro(db.upcast(), path.mod_path()?, Some(MacroSubNs::Attr))
+ .map(Into::into)
}
fn resolve_hir_path_(
@@ -962,8 +982,7 @@ fn resolve_hir_path_(
res.map(|ty_ns| (ty_ns, path.segments().first()))
}
None => {
- let (ty, remaining_idx) =
- resolver.resolve_path_in_type_ns(db.upcast(), path.mod_path())?;
+ let (ty, remaining_idx) = resolver.resolve_path_in_type_ns(db.upcast(), path)?;
match remaining_idx {
Some(remaining_idx) => {
if remaining_idx + 1 == path.segments().len() {
@@ -1019,7 +1038,7 @@ fn resolve_hir_path_(
let body_owner = resolver.body_owner();
let values = || {
- resolver.resolve_path_in_value_ns_fully(db.upcast(), path.mod_path()).and_then(|val| {
+ resolver.resolve_path_in_value_ns_fully(db.upcast(), path).and_then(|val| {
let res = match val {
ValueNs::LocalBinding(binding_id) => {
let var = Local { parent: body_owner?, binding_id };
@@ -1039,14 +1058,14 @@ fn resolve_hir_path_(
let items = || {
resolver
- .resolve_module_path_in_items(db.upcast(), path.mod_path())
+ .resolve_module_path_in_items(db.upcast(), path.mod_path()?)
.take_types()
.map(|it| PathResolution::Def(it.into()))
};
let macros = || {
resolver
- .resolve_path_as_macro(db.upcast(), path.mod_path())
+ .resolve_path_as_macro(db.upcast(), path.mod_path()?, None)
.map(|def| PathResolution::Def(ModuleDef::Macro(def.into())))
};
@@ -1074,7 +1093,7 @@ fn resolve_hir_path_qualifier(
path: &Path,
) -> Option<PathResolution> {
resolver
- .resolve_path_in_type_ns_fully(db.upcast(), path.mod_path())
+ .resolve_path_in_type_ns_fully(db.upcast(), &path)
.map(|ty| match ty {
TypeNs::SelfType(it) => PathResolution::SelfType(it.into()),
TypeNs::GenericParam(id) => PathResolution::TypeParam(id.into()),
@@ -1089,7 +1108,7 @@ fn resolve_hir_path_qualifier(
})
.or_else(|| {
resolver
- .resolve_module_path_in_items(db.upcast(), path.mod_path())
+ .resolve_module_path_in_items(db.upcast(), path.mod_path()?)
.take_types()
.map(|it| PathResolution::Def(it.into()))
})