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 bar(&self) -> i32 { 700 } "#, 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 bc65fd5bac4..f3a5f69b2a6 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); }