about summary refs log tree commit diff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/tools/rust-analyzer/crates/hir/src/lib.rs1
-rw-r--r--src/tools/rust-analyzer/crates/ide-db/src/defs.rs16
-rw-r--r--src/tools/rust-analyzer/crates/ide/src/hover.rs61
3 files changed, 47 insertions, 31 deletions
diff --git a/src/tools/rust-analyzer/crates/hir/src/lib.rs b/src/tools/rust-analyzer/crates/hir/src/lib.rs
index 0d2728bb613..930f47e8cc2 100644
--- a/src/tools/rust-analyzer/crates/hir/src/lib.rs
+++ b/src/tools/rust-analyzer/crates/hir/src/lib.rs
@@ -5582,6 +5582,7 @@ impl Type {
                     walk_substs(db, type_, &opaque_ty.substitution, cb);
                 }
                 TyKind::Placeholder(_) => {
+                    cb(type_.derived(ty.clone()));
                     if let Some(bounds) = ty.impl_trait_bounds(db) {
                         walk_bounds(db, &type_.derived(ty.clone()), &bounds, cb);
                     }
diff --git a/src/tools/rust-analyzer/crates/ide-db/src/defs.rs b/src/tools/rust-analyzer/crates/ide-db/src/defs.rs
index 32d242e8f24..49d26dfe25c 100644
--- a/src/tools/rust-analyzer/crates/ide-db/src/defs.rs
+++ b/src/tools/rust-analyzer/crates/ide-db/src/defs.rs
@@ -989,3 +989,19 @@ impl From<GenericDef> for Definition {
         }
     }
 }
+
+impl TryFrom<Definition> for GenericDef {
+    type Error = ();
+    fn try_from(def: Definition) -> Result<Self, Self::Error> {
+        match def {
+            Definition::Function(it) => Ok(it.into()),
+            Definition::Adt(it) => Ok(it.into()),
+            Definition::Trait(it) => Ok(it.into()),
+            Definition::TraitAlias(it) => Ok(it.into()),
+            Definition::TypeAlias(it) => Ok(it.into()),
+            Definition::SelfType(it) => Ok(it.into()),
+            Definition::Const(it) => Ok(it.into()),
+            _ => Err(()),
+        }
+    }
+}
diff --git a/src/tools/rust-analyzer/crates/ide/src/hover.rs b/src/tools/rust-analyzer/crates/ide/src/hover.rs
index 87f666fa408..18a3fed07ec 100644
--- a/src/tools/rust-analyzer/crates/ide/src/hover.rs
+++ b/src/tools/rust-analyzer/crates/ide/src/hover.rs
@@ -6,7 +6,9 @@ mod tests;
 use std::{iter, ops::Not};
 
 use either::Either;
-use hir::{db::DefDatabase, GenericSubstitution, HasCrate, HasSource, LangItem, Semantics};
+use hir::{
+    db::DefDatabase, GenericDef, GenericSubstitution, HasCrate, HasSource, LangItem, Semantics,
+};
 use ide_db::{
     defs::{Definition, IdentClass, NameRefClass, OperatorClass},
     famous_defs::FamousDefs,
@@ -548,40 +550,29 @@ fn goto_type_action_for_def(
         });
     }
 
-    if let Definition::GenericParam(hir::GenericParam::TypeParam(it)) = def {
-        let krate = it.module(db).krate();
-        let sized_trait =
-            db.lang_item(krate.into(), LangItem::Sized).and_then(|lang_item| lang_item.as_trait());
+    if let Ok(generic_def) = GenericDef::try_from(def) {
+        generic_def.type_or_const_params(db).into_iter().for_each(|it| {
+            walk_and_push_ty(db, &it.ty(db), &mut push_new_def);
+        });
+    }
 
-        it.trait_bounds(db)
-            .into_iter()
-            .filter(|&it| Some(it.into()) != sized_trait)
-            .for_each(|it| push_new_def(it.into()));
-    } else if let Definition::Function(function) = def {
-        walk_and_push_ty(db, &function.ret_type(db), &mut push_new_def);
-
-        let krate = function.module(db).krate();
-        let sized_trait =
-            db.lang_item(krate.into(), LangItem::Sized).and_then(|lang_item| lang_item.as_trait());
-        for param in function.params_without_self(db) {
-            if let Some(type_param) = param.ty().as_type_param(db) {
-                type_param
-                    .trait_bounds(db)
-                    .into_iter()
-                    .filter(|&it| Some(it.into()) != sized_trait)
-                    .for_each(|it| push_new_def(it.into()));
-            } else {
+    let ty = match def {
+        Definition::Local(it) => Some(it.ty(db)),
+        Definition::Field(field) => Some(field.ty(db)),
+        Definition::TupleField(field) => Some(field.ty(db)),
+        Definition::Const(it) => Some(it.ty(db)),
+        Definition::Static(it) => Some(it.ty(db)),
+        Definition::Function(func) => {
+            for param in func.assoc_fn_params(db) {
                 walk_and_push_ty(db, param.ty(), &mut push_new_def);
             }
+            Some(func.ret_type(db))
         }
-    } else {
-        let ty = match def {
-            Definition::Local(it) => it.ty(db),
-            Definition::GenericParam(hir::GenericParam::ConstParam(it)) => it.ty(db),
-            Definition::Field(field) => field.ty(db),
-            _ => return HoverAction::goto_type_from_targets(db, targets, edition),
-        };
-
+        Definition::GenericParam(hir::GenericParam::ConstParam(it)) => Some(it.ty(db)),
+        Definition::GenericParam(hir::GenericParam::TypeParam(it)) => Some(it.ty(db)),
+        _ => None,
+    };
+    if let Some(ty) = ty {
         walk_and_push_ty(db, &ty, &mut push_new_def);
     }
 
@@ -608,6 +599,14 @@ fn walk_and_push_ty(
             traits.for_each(|it| push_new_def(it.into()));
         } else if let Some(trait_) = t.as_associated_type_parent_trait(db) {
             push_new_def(trait_.into());
+        } else if let Some(tp) = t.as_type_param(db) {
+            let sized_trait = db
+                .lang_item(t.krate(db).into(), LangItem::Sized)
+                .and_then(|lang_item| lang_item.as_trait());
+            tp.trait_bounds(db)
+                .into_iter()
+                .filter(|&it| Some(it.into()) != sized_trait)
+                .for_each(|it| push_new_def(it.into()));
         }
     });
 }