Merge pull request #18950 from Veykril/push-okmsynnltxts

Generalize some type walking in hover type actions
This commit is contained in:
Lukas Wirth 2025-01-16 10:19:37 +00:00 committed by GitHub
commit 2ca2e56d51
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
3 changed files with 47 additions and 31 deletions

View File

@ -5582,6 +5582,7 @@ impl Type {
walk_substs(db, type_, &opaque_ty.substitution, cb); walk_substs(db, type_, &opaque_ty.substitution, cb);
} }
TyKind::Placeholder(_) => { TyKind::Placeholder(_) => {
cb(type_.derived(ty.clone()));
if let Some(bounds) = ty.impl_trait_bounds(db) { if let Some(bounds) = ty.impl_trait_bounds(db) {
walk_bounds(db, &type_.derived(ty.clone()), &bounds, cb); walk_bounds(db, &type_.derived(ty.clone()), &bounds, cb);
} }

View File

@ -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(()),
}
}
}

View File

@ -6,7 +6,9 @@ mod tests;
use std::{iter, ops::Not}; use std::{iter, ops::Not};
use either::Either; 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::{ use ide_db::{
defs::{Definition, IdentClass, NameRefClass, OperatorClass}, defs::{Definition, IdentClass, NameRefClass, OperatorClass},
famous_defs::FamousDefs, famous_defs::FamousDefs,
@ -548,40 +550,29 @@ fn goto_type_action_for_def(
}); });
} }
if let Definition::GenericParam(hir::GenericParam::TypeParam(it)) = def { if let Ok(generic_def) = GenericDef::try_from(def) {
let krate = it.module(db).krate(); generic_def.type_or_const_params(db).into_iter().for_each(|it| {
let sized_trait = walk_and_push_ty(db, &it.ty(db), &mut push_new_def);
db.lang_item(krate.into(), LangItem::Sized).and_then(|lang_item| lang_item.as_trait()); });
}
it.trait_bounds(db) let ty = match def {
.into_iter() Definition::Local(it) => Some(it.ty(db)),
.filter(|&it| Some(it.into()) != sized_trait) Definition::Field(field) => Some(field.ty(db)),
.for_each(|it| push_new_def(it.into())); Definition::TupleField(field) => Some(field.ty(db)),
} else if let Definition::Function(function) = def { Definition::Const(it) => Some(it.ty(db)),
walk_and_push_ty(db, &function.ret_type(db), &mut push_new_def); Definition::Static(it) => Some(it.ty(db)),
Definition::Function(func) => {
let krate = function.module(db).krate(); for param in func.assoc_fn_params(db) {
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 {
walk_and_push_ty(db, param.ty(), &mut push_new_def); walk_and_push_ty(db, param.ty(), &mut push_new_def);
} }
Some(func.ret_type(db))
} }
} else { Definition::GenericParam(hir::GenericParam::ConstParam(it)) => Some(it.ty(db)),
let ty = match def { Definition::GenericParam(hir::GenericParam::TypeParam(it)) => Some(it.ty(db)),
Definition::Local(it) => it.ty(db), _ => None,
Definition::GenericParam(hir::GenericParam::ConstParam(it)) => it.ty(db), };
Definition::Field(field) => field.ty(db), if let Some(ty) = ty {
_ => return HoverAction::goto_type_from_targets(db, targets, edition),
};
walk_and_push_ty(db, &ty, &mut push_new_def); 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())); traits.for_each(|it| push_new_def(it.into()));
} else if let Some(trait_) = t.as_associated_type_parent_trait(db) { } else if let Some(trait_) = t.as_associated_type_parent_trait(db) {
push_new_def(trait_.into()); 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()));
} }
}); });
} }