Skip to content

Commit

Permalink
Generalize some type walking in hover type actions
Browse files Browse the repository at this point in the history
  • Loading branch information
Veykril committed Jan 16, 2025
1 parent 9c7d8bb commit 3361b57
Show file tree
Hide file tree
Showing 3 changed files with 47 additions and 31 deletions.
1 change: 1 addition & 0 deletions crates/hir/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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);
}
Expand Down
16 changes: 16 additions & 0 deletions crates/ide-db/src/defs.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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(()),
}
}
}
61 changes: 30 additions & 31 deletions crates/ide/src/hover.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand Down Expand Up @@ -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);
}

Expand All @@ -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()));
}
});
}
Expand Down

0 comments on commit 3361b57

Please sign in to comment.