Unnamed repository; edit this file 'description' to name the repository.
Merge pull request #18950 from Veykril/push-okmsynnltxts
Generalize some type walking in hover type actions
Lukas Wirth 2025-01-16
parent 954ed7b · parent 3361b57 · commit 2ca2e56
-rw-r--r--crates/hir/src/lib.rs1
-rw-r--r--crates/ide-db/src/defs.rs16
-rw-r--r--crates/ide/src/hover.rs61
3 files changed, 47 insertions, 31 deletions
diff --git a/crates/hir/src/lib.rs b/crates/hir/src/lib.rs
index 0d2728bb61..930f47e8cc 100644
--- a/crates/hir/src/lib.rs
+++ b/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/crates/ide-db/src/defs.rs b/crates/ide-db/src/defs.rs
index 32d242e8f2..49d26dfe25 100644
--- a/crates/ide-db/src/defs.rs
+++ b/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/crates/ide/src/hover.rs b/crates/ide/src/hover.rs
index 87f666fa40..18a3fed07e 100644
--- a/crates/ide/src/hover.rs
+++ b/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()));
}
});
}