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.rs116
1 files changed, 111 insertions, 5 deletions
diff --git a/crates/hir/src/source_analyzer.rs b/crates/hir/src/source_analyzer.rs
index 1eb51b20c3..45879ff9c6 100644
--- a/crates/hir/src/source_analyzer.rs
+++ b/crates/hir/src/source_analyzer.rs
@@ -25,15 +25,17 @@ use hir_def::{
Lookup, ModuleDefId, VariantId,
};
use hir_expand::{
- builtin_fn_macro::BuiltinFnLikeExpander, hygiene::Hygiene, name::AsName, HirFileId, InFile,
+ builtin_fn_macro::BuiltinFnLikeExpander, hygiene::Hygiene, name, name::AsName, HirFileId,
+ InFile,
};
use hir_ty::{
diagnostics::{
record_literal_missing_fields, record_pattern_missing_fields, unsafe_expressions,
UnsafeExpr,
},
- method_resolution, Adjust, Adjustment, AutoBorrow, InferenceResult, Interner, Substitution,
- TyExt, TyKind, TyLoweringContext,
+ method_resolution::{self, lang_names_for_bin_op},
+ Adjust, Adjustment, AutoBorrow, InferenceResult, Interner, Substitution, TyExt, TyKind,
+ TyLoweringContext,
};
use itertools::Itertools;
use smallvec::SmallVec;
@@ -255,8 +257,103 @@ impl SourceAnalyzer {
) -> Option<FunctionId> {
let expr_id = self.expr_id(db, &call.clone().into())?;
let (f_in_trait, substs) = self.infer.as_ref()?.method_resolution(expr_id)?;
- let f_in_impl = self.resolve_impl_method(db, f_in_trait, &substs);
- f_in_impl.or(Some(f_in_trait))
+
+ Some(self.resolve_impl_method_or_trait_def(db, f_in_trait, &substs))
+ }
+
+ pub fn resolve_await_to_poll(
+ &self,
+ db: &dyn HirDatabase,
+ await_expr: &ast::AwaitExpr,
+ ) -> Option<FunctionId> {
+ let expr_id = self.expr_id(db, &await_expr.expr()?.into())?;
+ let ty = self.infer.as_ref()?.type_of_expr.get(expr_id)?;
+
+ let op_fn = db
+ .lang_item(self.resolver.krate(), hir_expand::name![poll].to_smol_str())?
+ .as_function()?;
+ let substs = hir_ty::TyBuilder::subst_for_def(db, op_fn).push(ty.clone()).build();
+
+ Some(self.resolve_impl_method_or_trait_def(db, op_fn, &substs))
+ }
+
+ pub fn resolve_prefix_expr(
+ &self,
+ db: &dyn HirDatabase,
+ prefix_expr: &ast::PrefixExpr,
+ ) -> Option<FunctionId> {
+ let lang_item_name = match prefix_expr.op_kind()? {
+ ast::UnaryOp::Deref => name![deref],
+ ast::UnaryOp::Not => name![not],
+ ast::UnaryOp::Neg => name![neg],
+ };
+ let expr_id = self.expr_id(db, &prefix_expr.expr()?.into())?;
+ let ty = self.infer.as_ref()?.type_of_expr.get(expr_id)?;
+
+ let trait_ =
+ db.lang_item(self.resolver.krate(), lang_item_name.to_smol_str())?.as_trait()?;
+ let op_fn = db.trait_data(trait_).method_by_name(&lang_item_name)?;
+ let substs = hir_ty::TyBuilder::subst_for_def(db, op_fn).push(ty.clone()).build();
+
+ Some(self.resolve_impl_method_or_trait_def(db, op_fn, &substs))
+ }
+
+ pub fn resolve_index_expr(
+ &self,
+ db: &dyn HirDatabase,
+ index_expr: &ast::IndexExpr,
+ ) -> Option<FunctionId> {
+ let base_expr_id = self.expr_id(db, &index_expr.base()?.into())?;
+ let index_expr_id = self.expr_id(db, &index_expr.index()?.into())?;
+ let base_ty = self.infer.as_ref()?.type_of_expr.get(base_expr_id)?;
+ let index_ty = self.infer.as_ref()?.type_of_expr.get(index_expr_id)?;
+
+ let lang_item_name = name![index];
+
+ let trait_ =
+ db.lang_item(self.resolver.krate(), lang_item_name.to_smol_str())?.as_trait()?;
+ let op_fn = db.trait_data(trait_).method_by_name(&lang_item_name)?;
+ let substs = hir_ty::TyBuilder::subst_for_def(db, op_fn)
+ .push(base_ty.clone())
+ .push(index_ty.clone())
+ .build();
+ Some(self.resolve_impl_method_or_trait_def(db, op_fn, &substs))
+ }
+
+ pub fn resolve_bin_expr(
+ &self,
+ db: &dyn HirDatabase,
+ binop_expr: &ast::BinExpr,
+ ) -> Option<FunctionId> {
+ let op = binop_expr.op_kind()?;
+ let lhs_expr_id = self.expr_id(db, &binop_expr.lhs()?.into())?;
+ let rhs_expr_id = self.expr_id(db, &binop_expr.rhs()?.into())?;
+ let lhs = self.infer.as_ref()?.type_of_expr.get(lhs_expr_id)?;
+ let rhs = self.infer.as_ref()?.type_of_expr.get(rhs_expr_id)?;
+
+ let op_fn = lang_names_for_bin_op(op).and_then(|(name, lang_item)| {
+ db.trait_data(db.lang_item(self.resolver.krate(), lang_item.to_smol_str())?.as_trait()?)
+ .method_by_name(&name)
+ })?;
+ let substs =
+ hir_ty::TyBuilder::subst_for_def(db, op_fn).push(lhs.clone()).push(rhs.clone()).build();
+
+ Some(self.resolve_impl_method_or_trait_def(db, op_fn, &substs))
+ }
+
+ pub fn resolve_try_expr(
+ &self,
+ db: &dyn HirDatabase,
+ try_expr: &ast::TryExpr,
+ ) -> Option<FunctionId> {
+ let expr_id = self.expr_id(db, &try_expr.expr()?.into())?;
+ let ty = self.infer.as_ref()?.type_of_expr.get(expr_id)?;
+
+ let op_fn =
+ db.lang_item(self.resolver.krate(), name![branch].to_smol_str())?.as_function()?;
+ let substs = hir_ty::TyBuilder::subst_for_def(db, op_fn).push(ty.clone()).build();
+
+ Some(self.resolve_impl_method_or_trait_def(db, op_fn, &substs))
}
pub(crate) fn resolve_field(
@@ -666,6 +763,15 @@ impl SourceAnalyzer {
let fun_data = db.function_data(func);
method_resolution::lookup_impl_method(self_ty, db, trait_env, impled_trait, &fun_data.name)
}
+
+ fn resolve_impl_method_or_trait_def(
+ &self,
+ db: &dyn HirDatabase,
+ func: FunctionId,
+ substs: &Substitution,
+ ) -> FunctionId {
+ self.resolve_impl_method(db, func, substs).unwrap_or(func)
+ }
}
fn scope_for(