aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--crates/hir_ty/src/method_resolution.rs27
-rw-r--r--crates/hir_ty/src/tests/method_resolution.rs22
2 files changed, 38 insertions, 11 deletions
diff --git a/crates/hir_ty/src/method_resolution.rs b/crates/hir_ty/src/method_resolution.rs
index a302456b0..b3d1fe9a4 100644
--- a/crates/hir_ty/src/method_resolution.rs
+++ b/crates/hir_ty/src/method_resolution.rs
@@ -10,25 +10,26 @@ use hir_def::{
10 builtin_type::{IntBitness, Signedness}, 10 builtin_type::{IntBitness, Signedness},
11 lang_item::LangItemTarget, 11 lang_item::LangItemTarget,
12 type_ref::Mutability, 12 type_ref::Mutability,
13 AssocContainerId, AssocItemId, FunctionId, HasModule, ImplId, Lookup, TraitId, 13 AssocContainerId, AssocItemId, FunctionId, GenericDefId, HasModule, ImplId, Lookup, ModuleId,
14 TraitId,
14}; 15};
15use hir_expand::name::Name; 16use hir_expand::name::Name;
16use rustc_hash::{FxHashMap, FxHashSet}; 17use rustc_hash::{FxHashMap, FxHashSet};
17 18
18use super::Substs;
19use crate::{ 19use crate::{
20 autoderef, 20 autoderef,
21 db::HirDatabase, 21 db::HirDatabase,
22 primitive::{FloatBitness, FloatTy, IntTy}, 22 primitive::{FloatBitness, FloatTy, IntTy},
23 utils::all_super_traits, 23 utils::all_super_traits,
24 ApplicationTy, Canonical, DebruijnIndex, InEnvironment, TraitEnvironment, TraitRef, Ty, TyKind, 24 ApplicationTy, Canonical, DebruijnIndex, InEnvironment, Substs, TraitEnvironment, TraitRef, Ty,
25 TypeCtor, TypeWalk, 25 TyKind, TypeCtor, TypeWalk,
26}; 26};
27 27
28/// This is used as a key for indexing impls. 28/// This is used as a key for indexing impls.
29#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)] 29#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
30pub enum TyFingerprint { 30pub enum TyFingerprint {
31 Apply(TypeCtor), 31 Apply(TypeCtor),
32 Dyn(TraitId),
32} 33}
33 34
34impl TyFingerprint { 35impl TyFingerprint {
@@ -38,6 +39,7 @@ impl TyFingerprint {
38 pub(crate) fn for_impl(ty: &Ty) -> Option<TyFingerprint> { 39 pub(crate) fn for_impl(ty: &Ty) -> Option<TyFingerprint> {
39 match ty { 40 match ty {
40 Ty::Apply(a_ty) => Some(TyFingerprint::Apply(a_ty.ctor)), 41 Ty::Apply(a_ty) => Some(TyFingerprint::Apply(a_ty.ctor)),
42 Ty::Dyn(_) => ty.dyn_trait().map(|trait_| TyFingerprint::Dyn(trait_)),
41 _ => None, 43 _ => None,
42 } 44 }
43 } 45 }
@@ -245,18 +247,15 @@ impl Ty {
245 }}; 247 }};
246 } 248 }
247 249
250 let mod_to_crate_ids = |module: ModuleId| Some(std::iter::once(module.krate()).collect());
251
248 let lang_item_targets = match self { 252 let lang_item_targets = match self {
249 Ty::Apply(a_ty) => match a_ty.ctor { 253 Ty::Apply(a_ty) => match a_ty.ctor {
250 TypeCtor::Adt(def_id) => { 254 TypeCtor::Adt(def_id) => {
251 return Some(std::iter::once(def_id.module(db.upcast()).krate()).collect()) 255 return mod_to_crate_ids(def_id.module(db.upcast()));
252 } 256 }
253 TypeCtor::ForeignType(type_alias_id) => { 257 TypeCtor::ForeignType(type_alias_id) => {
254 return Some( 258 return mod_to_crate_ids(type_alias_id.lookup(db.upcast()).module(db.upcast()));
255 std::iter::once(
256 type_alias_id.lookup(db.upcast()).module(db.upcast()).krate(),
257 )
258 .collect(),
259 )
260 } 259 }
261 TypeCtor::Bool => lang_item_crate!("bool"), 260 TypeCtor::Bool => lang_item_crate!("bool"),
262 TypeCtor::Char => lang_item_crate!("char"), 261 TypeCtor::Char => lang_item_crate!("char"),
@@ -272,6 +271,11 @@ impl Ty {
272 TypeCtor::RawPtr(Mutability::Mut) => lang_item_crate!("mut_ptr"), 271 TypeCtor::RawPtr(Mutability::Mut) => lang_item_crate!("mut_ptr"),
273 _ => return None, 272 _ => return None,
274 }, 273 },
274 Ty::Dyn(_) => {
275 return self.dyn_trait().and_then(|trait_| {
276 mod_to_crate_ids(GenericDefId::TraitId(trait_).module(db.upcast()))
277 });
278 }
275 _ => return None, 279 _ => return None,
276 }; 280 };
277 let res = lang_item_targets 281 let res = lang_item_targets
@@ -285,6 +289,7 @@ impl Ty {
285 Some(res) 289 Some(res)
286 } 290 }
287} 291}
292
288/// Look up the method with the given name, returning the actual autoderefed 293/// Look up the method with the given name, returning the actual autoderefed
289/// receiver type (but without autoref applied yet). 294/// receiver type (but without autoref applied yet).
290pub(crate) fn lookup_method( 295pub(crate) fn lookup_method(
diff --git a/crates/hir_ty/src/tests/method_resolution.rs b/crates/hir_ty/src/tests/method_resolution.rs
index a6a54e542..80e795fbf 100644
--- a/crates/hir_ty/src/tests/method_resolution.rs
+++ b/crates/hir_ty/src/tests/method_resolution.rs
@@ -1106,3 +1106,25 @@ fn main() {
1106"#, 1106"#,
1107 ); 1107 );
1108} 1108}
1109
1110#[test]
1111fn method_on_dyn_impl() {
1112 check_types(
1113 r#"
1114trait Foo {}
1115
1116impl Foo for u32 {}
1117impl dyn Foo {
1118 pub fn dyn_foo(&self) -> u32 {
1119 0
1120 }
1121}
1122
1123fn main() {
1124 let f = &42u32 as &dyn Foo<u32>;
1125 f.dyn_foo();
1126 // ^u32
1127}
1128"#,
1129 );
1130}