mirror of
https://github.com/rust-lang/rust-analyzer.git
synced 2025-10-01 11:31:15 +00:00
Merge pull request #18950 from Veykril/push-okmsynnltxts
Generalize some type walking in hover type actions
This commit is contained in:
commit
2ca2e56d51
@ -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);
|
||||||
}
|
}
|
||||||
|
@ -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(()),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@ -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()));
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user