diff options
-rw-r--r-- | crates/hir_ty/src/method_resolution.rs | 27 | ||||
-rw-r--r-- | crates/hir_ty/src/tests/method_resolution.rs | 22 |
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 | }; |
15 | use hir_expand::name::Name; | 16 | use hir_expand::name::Name; |
16 | use rustc_hash::{FxHashMap, FxHashSet}; | 17 | use rustc_hash::{FxHashMap, FxHashSet}; |
17 | 18 | ||
18 | use super::Substs; | ||
19 | use crate::{ | 19 | use 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)] |
30 | pub enum TyFingerprint { | 30 | pub enum TyFingerprint { |
31 | Apply(TypeCtor), | 31 | Apply(TypeCtor), |
32 | Dyn(TraitId), | ||
32 | } | 33 | } |
33 | 34 | ||
34 | impl TyFingerprint { | 35 | impl 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). |
290 | pub(crate) fn lookup_method( | 295 | pub(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] | ||
1111 | fn method_on_dyn_impl() { | ||
1112 | check_types( | ||
1113 | r#" | ||
1114 | trait Foo {} | ||
1115 | |||
1116 | impl Foo for u32 {} | ||
1117 | impl dyn Foo { | ||
1118 | pub fn dyn_foo(&self) -> u32 { | ||
1119 | 0 | ||
1120 | } | ||
1121 | } | ||
1122 | |||
1123 | fn main() { | ||
1124 | let f = &42u32 as &dyn Foo<u32>; | ||
1125 | f.dyn_foo(); | ||
1126 | // ^u32 | ||
1127 | } | ||
1128 | "#, | ||
1129 | ); | ||
1130 | } | ||