]> git.lizzy.rs Git - rust.git/blobdiff - crates/hir-ty/src/method_resolution.rs
Auto merge of #13223 - lowr:fix/hir-proj-normalization, r=flodiebold
[rust.git] / crates / hir-ty / src / method_resolution.rs
index 9a63d5013b4671274e8c93747049a5aa11fd33c7..dbf2750032074b76500605929db7c232a6360b06 100644 (file)
@@ -914,22 +914,10 @@ fn iterate_trait_method_candidates(
     let db = table.db;
     let env = table.trait_env.clone();
     let self_is_array = matches!(self_ty.kind(Interner), chalk_ir::TyKind::Array(..));
-    // if ty is `dyn Trait`, the trait doesn't need to be in scope
-    let inherent_trait =
-        self_ty.dyn_trait().into_iter().flat_map(|t| all_super_traits(db.upcast(), t));
-    let env_traits = matches!(self_ty.kind(Interner), TyKind::Placeholder(_))
-        // if we have `T: Trait` in the param env, the trait doesn't need to be in scope
-        .then(|| {
-            env.traits_in_scope_from_clauses(self_ty.clone())
-                .flat_map(|t| all_super_traits(db.upcast(), t))
-        })
-        .into_iter()
-        .flatten();
-    let traits = inherent_trait.chain(env_traits).chain(traits_in_scope.iter().copied());
 
     let canonical_self_ty = table.canonicalize(self_ty.clone()).value;
 
-    'traits: for t in traits {
+    'traits: for &t in traits_in_scope {
         let data = db.trait_data(t);
 
         // Traits annotated with `#[rustc_skip_array_during_method_dispatch]` are skipped during
@@ -979,6 +967,43 @@ fn iterate_inherent_methods(
 ) -> ControlFlow<()> {
     let db = table.db;
     let env = table.trait_env.clone();
+
+    // For trait object types and placeholder types with trait bounds, the methods of the trait and
+    // its super traits are considered inherent methods. This matters because these methods have
+    // higher priority than the other traits' methods, which would be considered in
+    // `iterate_trait_method_candidates()` only after this function.
+    match self_ty.kind(Interner) {
+        TyKind::Placeholder(_) => {
+            let env = table.trait_env.clone();
+            let traits = env
+                .traits_in_scope_from_clauses(self_ty.clone())
+                .flat_map(|t| all_super_traits(db.upcast(), t));
+            iterate_inherent_trait_methods(
+                self_ty,
+                table,
+                name,
+                receiver_ty,
+                receiver_adjustments.clone(),
+                callback,
+                traits,
+            )?;
+        }
+        TyKind::Dyn(_) => {
+            let principal_trait = self_ty.dyn_trait().unwrap();
+            let traits = all_super_traits(db.upcast(), principal_trait);
+            iterate_inherent_trait_methods(
+                self_ty,
+                table,
+                name,
+                receiver_ty,
+                receiver_adjustments.clone(),
+                callback,
+                traits.into_iter(),
+            )?;
+        }
+        _ => {}
+    }
+
     let def_crates = match def_crates(db, self_ty, env.krate) {
         Some(k) => k,
         None => return ControlFlow::Continue(()),
@@ -1020,6 +1045,28 @@ fn iterate_inherent_methods(
     }
     return ControlFlow::Continue(());
 
+    fn iterate_inherent_trait_methods(
+        self_ty: &Ty,
+        table: &mut InferenceTable<'_>,
+        name: Option<&Name>,
+        receiver_ty: Option<&Ty>,
+        receiver_adjustments: Option<ReceiverAdjustments>,
+        callback: &mut dyn FnMut(ReceiverAdjustments, AssocItemId) -> ControlFlow<()>,
+        traits: impl Iterator<Item = TraitId>,
+    ) -> ControlFlow<()> {
+        let db = table.db;
+        for t in traits {
+            let data = db.trait_data(t);
+            for &(_, item) in data.items.iter() {
+                // We don't pass `visible_from_module` as all trait items should be visible.
+                if is_valid_candidate(table, name, receiver_ty, item, self_ty, None) {
+                    callback(receiver_adjustments.clone().unwrap_or_default(), item)?;
+                }
+            }
+        }
+        ControlFlow::Continue(())
+    }
+
     fn impls_for_self_ty(
         impls: &InherentImpls,
         self_ty: &Ty,