diff --git a/crates/hir/src/lib.rs b/crates/hir/src/lib.rs index 0d2728bb613d..930f47e8cc25 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 32d242e8f24c..49d26dfe25c1 100644 --- a/crates/ide-db/src/defs.rs +++ b/crates/ide-db/src/defs.rs @@ -989,3 +989,19 @@ impl From for Definition { } } } + +impl TryFrom for GenericDef { + type Error = (); + fn try_from(def: Definition) -> Result { + 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 87f666fa4085..18a3fed07ece 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())); } }); }