Unnamed repository; edit this file 'description' to name the repository.
Diffstat (limited to 'crates/hir-ty/src/method_resolution.rs')
-rw-r--r--crates/hir-ty/src/method_resolution.rs54
1 files changed, 33 insertions, 21 deletions
diff --git a/crates/hir-ty/src/method_resolution.rs b/crates/hir-ty/src/method_resolution.rs
index 41fcef73d9..a79efeb6da 100644
--- a/crates/hir-ty/src/method_resolution.rs
+++ b/crates/hir-ty/src/method_resolution.rs
@@ -1,7 +1,7 @@
//! This module is concerned with finding methods that a given type provides.
//! For details about how this works in rustc, see the method lookup page in the
//! [rustc guide](https://rust-lang.github.io/rustc-guide/method-lookup.html)
-//! and the corresponding code mostly in librustc_typeck/check/method/probe.rs.
+//! and the corresponding code mostly in rustc_hir_analysis/check/method/probe.rs.
use std::{iter, ops::ControlFlow, sync::Arc};
use arrayvec::ArrayVec;
@@ -654,7 +654,7 @@ fn find_matching_impl(
let r = table.run_in_snapshot(|table| {
let impl_data = db.impl_data(impl_);
let substs =
- TyBuilder::subst_for_def(db, impl_).fill_with_inference_vars(table).build();
+ TyBuilder::subst_for_def(db, impl_, None).fill_with_inference_vars(table).build();
let impl_ty = db.impl_self_ty(impl_).substitute(Interner, &substs);
table
@@ -1111,6 +1111,24 @@ pub fn resolve_indexing_op(
}
None
}
+/// Returns the receiver type for the try branch trait call.
+pub fn resolve_branch_op(
+ db: &dyn HirDatabase,
+ env: Arc<TraitEnvironment>,
+ ty: Canonical<Ty>,
+ try_trait: TraitId,
+) -> Option<ReceiverAdjustments> {
+ let mut table = InferenceTable::new(db, env.clone());
+ let ty = table.instantiate_canonical(ty);
+ let (deref_chain, adj) = autoderef_method_receiver(&mut table, ty);
+ for (ty, adj) in deref_chain.into_iter().zip(adj) {
+ let goal = generic_implements_goal(db, env.clone(), try_trait, &ty);
+ if db.trait_solve(env.krate, goal.cast(Interner)).is_some() {
+ return Some(adj);
+ }
+ }
+ None
+}
macro_rules! check_that {
($cond:expr) => {
@@ -1147,10 +1165,9 @@ fn is_valid_candidate(
}));
if let ItemContainerId::ImplId(impl_id) = c.lookup(db.upcast()).container {
let self_ty_matches = table.run_in_snapshot(|table| {
- let subst =
- TyBuilder::subst_for_def(db, c).fill_with_inference_vars(table).build();
- let expected_self_ty =
- subst.apply(db.impl_self_ty(impl_id).skip_binders().clone(), Interner);
+ let expected_self_ty = TyBuilder::impl_self_ty(db, impl_id)
+ .fill_with_inference_vars(table)
+ .build();
table.unify(&expected_self_ty, &self_ty)
});
if !self_ty_matches {
@@ -1186,31 +1203,26 @@ fn is_valid_fn_candidate(
table.run_in_snapshot(|table| {
let container = fn_id.lookup(db.upcast()).container;
- let impl_subst = match container {
+ let (impl_subst, expect_self_ty) = match container {
ItemContainerId::ImplId(it) => {
- TyBuilder::subst_for_def(db, it).fill_with_inference_vars(table).build()
+ let subst =
+ TyBuilder::subst_for_def(db, it, None).fill_with_inference_vars(table).build();
+ let self_ty = db.impl_self_ty(it).substitute(Interner, &subst);
+ (subst, self_ty)
}
ItemContainerId::TraitId(it) => {
- TyBuilder::subst_for_def(db, it).fill_with_inference_vars(table).build()
+ let subst =
+ TyBuilder::subst_for_def(db, it, None).fill_with_inference_vars(table).build();
+ let self_ty = subst.at(Interner, 0).assert_ty_ref(Interner).clone();
+ (subst, self_ty)
}
_ => unreachable!(),
};
- let fn_subst = TyBuilder::subst_for_def(db, fn_id)
- .use_parent_substs(&impl_subst)
+ let fn_subst = TyBuilder::subst_for_def(db, fn_id, Some(impl_subst.clone()))
.fill_with_inference_vars(table)
.build();
- let expect_self_ty = match container {
- ItemContainerId::TraitId(_) => fn_subst.at(Interner, 0).assert_ty_ref(Interner).clone(),
- ItemContainerId::ImplId(impl_id) => {
- fn_subst.apply(db.impl_self_ty(impl_id).skip_binders().clone(), Interner)
- }
- // We should only get called for associated items (impl/trait)
- ItemContainerId::ModuleId(_) | ItemContainerId::ExternBlockId(_) => {
- unreachable!()
- }
- };
check_that!(table.unify(&expect_self_ty, self_ty));
if let Some(receiver_ty) = receiver_ty {