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.rs | 54 |
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 { |