From 808f6687f7b796dd2c171e3be3829f1dedb6d537 Mon Sep 17 00:00:00 2001 From: austaras Date: Fri, 17 Nov 2023 16:47:46 +0800 Subject: [PATCH] address comment --- crates/hir-ty/src/infer/unify.rs | 31 +-------------- crates/hir-ty/src/method_resolution.rs | 53 +++++++++++++++++--------- crates/hir-ty/src/tests/traits.rs | 28 ++++++++++++++ 3 files changed, 63 insertions(+), 49 deletions(-) diff --git a/crates/hir-ty/src/infer/unify.rs b/crates/hir-ty/src/infer/unify.rs index 78bdd62a276..ac39bdf5bf5 100644 --- a/crates/hir-ty/src/infer/unify.rs +++ b/crates/hir-ty/src/infer/unify.rs @@ -43,7 +43,7 @@ where } impl> Canonicalized { - pub(super) fn apply_solution( + pub(crate) fn apply_solution( &self, ctx: &mut InferenceTable<'_>, solution: Canonical, @@ -495,35 +495,6 @@ impl<'a> InferenceTable<'a> { solution } - pub(crate) fn try_resolve_alias(&mut self, goal: Goal) -> bool { - let in_env = InEnvironment::new(&self.trait_env.env, goal); - let canonicalized = self.canonicalize(in_env); - let solution = self.db.trait_solve( - self.trait_env.krate, - self.trait_env.block, - canonicalized.value.clone(), - ); - - match solution { - Some(Solution::Unique(canonical_subst)) => { - canonicalized.apply_solution( - self, - Canonical { - binders: canonical_subst.binders, - value: canonical_subst.value.subst, - }, - ); - true - } - Some(Solution::Ambig(Guidance::Definite(substs))) => { - canonicalized.apply_solution(self, substs); - true - } - Some(_) => true, - None => false, - } - } - pub(crate) fn register_obligation(&mut self, goal: Goal) { let in_env = InEnvironment::new(&self.trait_env.env, goal); self.register_obligation_in_env(in_env) diff --git a/crates/hir-ty/src/method_resolution.rs b/crates/hir-ty/src/method_resolution.rs index 04a55c3536d..732643566a2 100644 --- a/crates/hir-ty/src/method_resolution.rs +++ b/crates/hir-ty/src/method_resolution.rs @@ -27,8 +27,9 @@ use crate::{ primitive::{FloatTy, IntTy, UintTy}, static_lifetime, to_chalk_trait_id, utils::all_super_traits, - AdtId, Canonical, CanonicalVarKinds, DebruijnIndex, DynTyExt, ForeignDefId, InEnvironment, - Interner, Scalar, Substitution, TraitEnvironment, TraitRef, TraitRefExt, Ty, TyBuilder, TyExt, + AdtId, Canonical, CanonicalVarKinds, DebruijnIndex, DynTyExt, ForeignDefId, Goal, Guidance, + InEnvironment, Interner, Scalar, Solution, Substitution, TraitEnvironment, TraitRef, + TraitRefExt, Ty, TyBuilder, TyExt, }; /// This is used as a key for indexing impls. @@ -1478,11 +1479,8 @@ fn is_valid_fn_candidate( // We need to consider the bounds on the impl to distinguish functions of the same name // for a type. let predicates = db.generic_predicates(impl_id.into()); - let mut alias = Vec::new(); - let mut other_predicate = Vec::new(); - - for predicate in predicates.iter() { - let (p, b) = predicate + let goals = predicates.iter().map(|p| { + let (p, b) = p .clone() .substitute(Interner, &impl_subst) // Skipping the inner binders is ok, as we don't handle quantified where @@ -1490,21 +1488,38 @@ fn is_valid_fn_candidate( .into_value_and_skipped_binders(); stdx::always!(b.len(Interner) == 0); - if let WhereClause::AliasEq(_) = p { - alias.push(p); - } else { - other_predicate.push(p); + p.cast::(Interner) + }); + + for goal in goals.clone() { + let in_env = InEnvironment::new(&table.trait_env.env, goal); + let canonicalized = table.canonicalize(in_env); + let solution = table.db.trait_solve( + table.trait_env.krate, + table.trait_env.block, + canonicalized.value.clone(), + ); + + match solution { + Some(Solution::Unique(canonical_subst)) => { + canonicalized.apply_solution( + table, + Canonical { + binders: canonical_subst.binders, + value: canonical_subst.value.subst, + }, + ); + } + Some(Solution::Ambig(Guidance::Definite(substs))) => { + canonicalized.apply_solution(table, substs); + } + Some(_) => (), + None => return IsValidCandidate::No, } } - for p in alias { - if !table.try_resolve_alias(p.cast(Interner)) { - return IsValidCandidate::No; - } - } - - for p in other_predicate { - if table.try_obligation(p.cast(Interner)).is_none() { + for goal in goals { + if table.try_obligation(goal).is_none() { return IsValidCandidate::No; } } diff --git a/crates/hir-ty/src/tests/traits.rs b/crates/hir-ty/src/tests/traits.rs index 48dd9540329..003ae60e8e5 100644 --- a/crates/hir-ty/src/tests/traits.rs +++ b/crates/hir-ty/src/tests/traits.rs @@ -2597,6 +2597,34 @@ fn test() { ); } +#[test] +fn associated_type_in_type_bound() { + check_types( + r#" +//- minicore: deref +fn fb(f: Foo<&u8>) { + f.foobar(); + //^^^^^^^^^^ u8 +} +trait Bar { + fn bar(&self) -> u8; +} +impl Bar for u8 { + fn bar(&self) -> u8 { *self } +} + +struct Foo { + foo: F, +} +impl> Foo { + fn foobar(&self) -> u8 { + self.foo.deref().bar() + } +} +"#, + ) +} + #[test] fn dyn_trait_through_chalk() { check_types(