about summary refs log tree commit diff
diff options
context:
space:
mode:
authorLukas Wirth <lukastw97@gmail.com>2021-02-08 19:13:54 +0100
committerLukas Wirth <lukastw97@gmail.com>2021-02-08 19:13:54 +0100
commit965d31ce5b8315e39f72e40da283d2f3d1367e87 (patch)
treec13f2f34f50295fd96e3e27b8139c239076333eb
parent4cc333c889af82931222d5cdf7a5107df1afa834 (diff)
Check for dyn impls in method resolution
-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 a302456b090..b3d1fe9a44e 100644
--- a/crates/hir_ty/src/method_resolution.rs
+++ b/crates/hir_ty/src/method_resolution.rs
@@ -10,25 +10,26 @@ use hir_def::{
     builtin_type::{IntBitness, Signedness},
     lang_item::LangItemTarget,
     type_ref::Mutability,
-    AssocContainerId, AssocItemId, FunctionId, HasModule, ImplId, Lookup, TraitId,
+    AssocContainerId, AssocItemId, FunctionId, GenericDefId, HasModule, ImplId, Lookup, ModuleId,
+    TraitId,
 };
 use hir_expand::name::Name;
 use rustc_hash::{FxHashMap, FxHashSet};
 
-use super::Substs;
 use crate::{
     autoderef,
     db::HirDatabase,
     primitive::{FloatBitness, FloatTy, IntTy},
     utils::all_super_traits,
-    ApplicationTy, Canonical, DebruijnIndex, InEnvironment, TraitEnvironment, TraitRef, Ty, TyKind,
-    TypeCtor, TypeWalk,
+    ApplicationTy, Canonical, DebruijnIndex, InEnvironment, Substs, TraitEnvironment, TraitRef, Ty,
+    TyKind, TypeCtor, TypeWalk,
 };
 
 /// This is used as a key for indexing impls.
 #[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
 pub enum TyFingerprint {
     Apply(TypeCtor),
+    Dyn(TraitId),
 }
 
 impl TyFingerprint {
@@ -38,6 +39,7 @@ impl TyFingerprint {
     pub(crate) fn for_impl(ty: &Ty) -> Option<TyFingerprint> {
         match ty {
             Ty::Apply(a_ty) => Some(TyFingerprint::Apply(a_ty.ctor)),
+            Ty::Dyn(_) => ty.dyn_trait().map(|trait_| TyFingerprint::Dyn(trait_)),
             _ => None,
         }
     }
@@ -245,18 +247,15 @@ impl Ty {
             }};
         }
 
+        let mod_to_crate_ids = |module: ModuleId| Some(std::iter::once(module.krate()).collect());
+
         let lang_item_targets = match self {
             Ty::Apply(a_ty) => match a_ty.ctor {
                 TypeCtor::Adt(def_id) => {
-                    return Some(std::iter::once(def_id.module(db.upcast()).krate()).collect())
+                    return mod_to_crate_ids(def_id.module(db.upcast()));
                 }
                 TypeCtor::ForeignType(type_alias_id) => {
-                    return Some(
-                        std::iter::once(
-                            type_alias_id.lookup(db.upcast()).module(db.upcast()).krate(),
-                        )
-                        .collect(),
-                    )
+                    return mod_to_crate_ids(type_alias_id.lookup(db.upcast()).module(db.upcast()));
                 }
                 TypeCtor::Bool => lang_item_crate!("bool"),
                 TypeCtor::Char => lang_item_crate!("char"),
@@ -272,6 +271,11 @@ impl Ty {
                 TypeCtor::RawPtr(Mutability::Mut) => lang_item_crate!("mut_ptr"),
                 _ => return None,
             },
+            Ty::Dyn(_) => {
+                return self.dyn_trait().and_then(|trait_| {
+                    mod_to_crate_ids(GenericDefId::TraitId(trait_).module(db.upcast()))
+                });
+            }
             _ => return None,
         };
         let res = lang_item_targets
@@ -285,6 +289,7 @@ impl Ty {
         Some(res)
     }
 }
+
 /// Look up the method with the given name, returning the actual autoderefed
 /// receiver type (but without autoref applied yet).
 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 a6a54e542a9..80e795fbfd4 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() {
 "#,
     );
 }
+
+#[test]
+fn method_on_dyn_impl() {
+    check_types(
+        r#"
+trait Foo {}
+
+impl Foo for u32 {}
+impl dyn Foo {
+    pub fn dyn_foo(&self) -> u32 {
+        0
+    }
+}
+
+fn main() {
+    let f = &42u32 as &dyn Foo<u32>;
+    f.dyn_foo();
+  // ^u32
+}
+"#,
+    );
+}