Unnamed repository; edit this file 'description' to name the repository.
address comment
austaras 2023-11-17
parent e95ec55 · commit 808f668
-rw-r--r--crates/hir-ty/src/infer/unify.rs31
-rw-r--r--crates/hir-ty/src/method_resolution.rs51
-rw-r--r--crates/hir-ty/src/tests/traits.rs28
3 files changed, 62 insertions, 48 deletions
diff --git a/crates/hir-ty/src/infer/unify.rs b/crates/hir-ty/src/infer/unify.rs
index 78bdd62a27..ac39bdf5bf 100644
--- a/crates/hir-ty/src/infer/unify.rs
+++ b/crates/hir-ty/src/infer/unify.rs
@@ -43,7 +43,7 @@ where
}
impl<T: HasInterner<Interner = Interner>> Canonicalized<T> {
- pub(super) fn apply_solution(
+ pub(crate) fn apply_solution(
&self,
ctx: &mut InferenceTable<'_>,
solution: Canonical<Substitution>,
@@ -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 04a55c3536..732643566a 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::<Goal>(Interner)
+ });
- for p in alias {
- if !table.try_resolve_alias(p.cast(Interner)) {
- return IsValidCandidate::No;
+ 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 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 48dd954032..003ae60e8e 100644
--- a/crates/hir-ty/src/tests/traits.rs
+++ b/crates/hir-ty/src/tests/traits.rs
@@ -2598,6 +2598,34 @@ fn test<T: Trait>() {
}
#[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<F> {
+ foo: F,
+}
+impl<F: core::ops::Deref<Target = impl Bar>> Foo<F> {
+ fn foobar(&self) -> u8 {
+ self.foo.deref().bar()
+ }
+}
+"#,
+ )
+}
+
+#[test]
fn dyn_trait_through_chalk() {
check_types(
r#"