Skip to content

Commit f9e2ac5

Browse files
committed
fix: handle trait methods as inherent methods for trait object types
1 parent f02cd0a commit f9e2ac5

File tree

2 files changed

+35
-4
lines changed

2 files changed

+35
-4
lines changed

crates/hir-ty/src/method_resolution.rs

+18-4
Original file line numberDiff line numberDiff line change
@@ -914,9 +914,6 @@ fn iterate_trait_method_candidates(
914914
let db = table.db;
915915
let env = table.trait_env.clone();
916916
let self_is_array = matches!(self_ty.kind(Interner), chalk_ir::TyKind::Array(..));
917-
// if ty is `dyn Trait`, the trait doesn't need to be in scope
918-
let inherent_trait =
919-
self_ty.dyn_trait().into_iter().flat_map(|t| all_super_traits(db.upcast(), t));
920917
let env_traits = matches!(self_ty.kind(Interner), TyKind::Placeholder(_))
921918
// if we have `T: Trait` in the param env, the trait doesn't need to be in scope
922919
.then(|| {
@@ -925,7 +922,7 @@ fn iterate_trait_method_candidates(
925922
})
926923
.into_iter()
927924
.flatten();
928-
let traits = inherent_trait.chain(env_traits).chain(traits_in_scope.iter().copied());
925+
let traits = env_traits.chain(traits_in_scope.iter().copied());
929926

930927
let canonical_self_ty = table.canonicalize(self_ty.clone()).value;
931928

@@ -990,6 +987,23 @@ fn iterate_inherent_methods(
990987
VisibleFromModule::None => (None, None),
991988
};
992989

990+
// For trait object types, methods of the trait and its super traits are considered inherent
991+
// methods. This matters because these trait methods have higher priority than the other
992+
// traits' methods, which would be considered in `iterate_trait_method_candidates()` after this
993+
// function.
994+
let inherent_traits =
995+
self_ty.dyn_trait().into_iter().flat_map(|t| all_super_traits(db.upcast(), t));
996+
for t in inherent_traits {
997+
let data = db.trait_data(t);
998+
for &(_, item) in data.items.iter() {
999+
// We don't pass `visible_from_module` as all trait items should be visible from the
1000+
// trait object.
1001+
if is_valid_candidate(table, name, receiver_ty, item, self_ty, None) {
1002+
callback(receiver_adjustments.clone().unwrap_or_default(), item)?;
1003+
}
1004+
}
1005+
}
1006+
9931007
if let Some(block_id) = block {
9941008
if let Some(impls) = db.inherent_impls_in_block(block_id) {
9951009
impls_for_self_ty(

crates/hir-ty/src/tests/method_resolution.rs

+17
Original file line numberDiff line numberDiff line change
@@ -1218,6 +1218,23 @@ fn main() {
12181218
);
12191219
}
12201220

1221+
#[test]
1222+
fn dyn_trait_method_priority() {
1223+
check_types(
1224+
r#"
1225+
//- minicore: from
1226+
trait Trait {
1227+
fn into(&self) -> usize { 0 }
1228+
}
1229+
1230+
fn foo(a: &dyn Trait) {
1231+
let _ = a.into();
1232+
//^usize
1233+
}
1234+
"#,
1235+
);
1236+
}
1237+
12211238
#[test]
12221239
fn autoderef_visibility_field() {
12231240
check(

0 commit comments

Comments
 (0)