about summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--crates/hir-ty/src/consteval/tests.rs27
-rw-r--r--crates/hir-ty/src/method_resolution.rs22
2 files changed, 42 insertions, 7 deletions
diff --git a/crates/hir-ty/src/consteval/tests.rs b/crates/hir-ty/src/consteval/tests.rs
index de792a6c5ae..98ebe557245 100644
--- a/crates/hir-ty/src/consteval/tests.rs
+++ b/crates/hir-ty/src/consteval/tests.rs
@@ -1941,6 +1941,33 @@ fn dyn_trait() {
         "#,
         900,
     );
+    check_number(
+        r#"
+    //- minicore: coerce_unsized, index, slice
+    trait A {
+        fn x(&self) -> i32;
+    }
+
+    trait B: A {}
+
+    impl A for i32 {
+        fn x(&self) -> i32 {
+            5
+        }
+    }
+
+    impl B for i32 {
+
+    }
+
+    const fn f(x: &dyn B) -> i32 {
+        x.x()
+    }
+
+    const GOAL: i32 = f(&2i32);
+        "#,
+        5,
+    );
 }
 
 #[test]
diff --git a/crates/hir-ty/src/method_resolution.rs b/crates/hir-ty/src/method_resolution.rs
index 5e1040bc6aa..95ebc706270 100644
--- a/crates/hir-ty/src/method_resolution.rs
+++ b/crates/hir-ty/src/method_resolution.rs
@@ -665,13 +665,21 @@ pub fn is_dyn_method(
     };
     let self_ty = trait_ref.self_type_parameter(Interner);
     if let TyKind::Dyn(d) = self_ty.kind(Interner) {
-        let is_my_trait_in_bounds =
-            d.bounds.skip_binders().as_slice(Interner).iter().any(|it| match it.skip_binders() {
-                // rustc doesn't accept `impl Foo<2> for dyn Foo<5>`, so if the trait id is equal, no matter
-                // what the generics are, we are sure that the method is come from the vtable.
-                WhereClause::Implemented(tr) => tr.trait_id == trait_ref.trait_id,
-                _ => false,
-            });
+        let is_my_trait_in_bounds = d
+            .bounds
+            .skip_binders()
+            .as_slice(Interner)
+            .iter()
+            .map(|it| it.skip_binders())
+            .flat_map(|it| match it {
+                WhereClause::Implemented(tr) => {
+                    all_super_traits(db.upcast(), from_chalk_trait_id(tr.trait_id))
+                }
+                _ => smallvec![],
+            })
+            // rustc doesn't accept `impl Foo<2> for dyn Foo<5>`, so if the trait id is equal, no matter
+            // what the generics are, we are sure that the method is come from the vtable.
+            .any(|x| x == trait_id);
         if is_my_trait_in_bounds {
             return Some(fn_params);
         }