mirror of
https://github.com/rust-lang/rust-analyzer
synced 2025-01-14 06:03:58 +00:00
feat: show type bounds from containers for functions
This commit is contained in:
parent
af1291bbf3
commit
184ddc6f5b
1 changed files with 47 additions and 5 deletions
|
@ -8,7 +8,7 @@ use hir_def::{
|
||||||
},
|
},
|
||||||
lang_item::LangItem,
|
lang_item::LangItem,
|
||||||
type_ref::{TypeBound, TypeRef},
|
type_ref::{TypeBound, TypeRef},
|
||||||
AdtId, GenericDefId,
|
AdtId, GenericDefId, ItemContainerId, ItemTreeLoc, Lookup,
|
||||||
};
|
};
|
||||||
use hir_ty::{
|
use hir_ty::{
|
||||||
display::{
|
display::{
|
||||||
|
@ -22,7 +22,7 @@ use itertools::Itertools;
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
Adt, AsAssocItem, AssocItem, AssocItemContainer, Const, ConstParam, Enum, ExternCrateDecl,
|
Adt, AsAssocItem, AssocItem, AssocItemContainer, Const, ConstParam, Enum, ExternCrateDecl,
|
||||||
Field, Function, GenericParam, HasCrate, HasVisibility, LifetimeParam, Macro, Module,
|
Field, Function, GenericParam, HasCrate, HasVisibility, Impl, LifetimeParam, Macro, Module,
|
||||||
SelfParam, Static, Struct, Trait, TraitAlias, TupleField, TyBuilder, Type, TypeAlias,
|
SelfParam, Static, Struct, Trait, TraitAlias, TupleField, TyBuilder, Type, TypeAlias,
|
||||||
TypeOrConstParam, TypeParam, Union, Variant,
|
TypeOrConstParam, TypeParam, Union, Variant,
|
||||||
};
|
};
|
||||||
|
@ -35,11 +35,18 @@ impl HirDisplay for Function {
|
||||||
let mut module = self.module(db);
|
let mut module = self.module(db);
|
||||||
|
|
||||||
match container {
|
match container {
|
||||||
Some(AssocItemContainer::Impl(_)) => {
|
Some(AssocItemContainer::Trait(trait_)) => {
|
||||||
|
write_trait_header(&trait_, f)?;
|
||||||
|
f.write_str("\n")?;
|
||||||
|
}
|
||||||
|
Some(AssocItemContainer::Impl(impl_)) => {
|
||||||
|
write_impl_header(&impl_, f)?;
|
||||||
|
f.write_str("\n")?;
|
||||||
|
|
||||||
// Block-local impls are "hoisted" to the nearest (non-block) module.
|
// Block-local impls are "hoisted" to the nearest (non-block) module.
|
||||||
module = module.nearest_non_block_module(db);
|
module = module.nearest_non_block_module(db);
|
||||||
}
|
}
|
||||||
_ => {}
|
None => {}
|
||||||
}
|
}
|
||||||
let module_id = module.id;
|
let module_id = module.id;
|
||||||
write_visibility(module_id, self.visibility(db), f)?;
|
write_visibility(module_id, self.visibility(db), f)?;
|
||||||
|
@ -129,6 +136,24 @@ impl HirDisplay for Function {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn write_impl_header(impl_: &Impl, f: &mut HirFormatter<'_>) -> Result<(), HirDisplayError> {
|
||||||
|
let db = f.db;
|
||||||
|
|
||||||
|
f.write_str("impl")?;
|
||||||
|
let def_id = GenericDefId::ImplId(impl_.id);
|
||||||
|
write_generic_params(def_id, f)?;
|
||||||
|
|
||||||
|
if let Some(trait_) = impl_.trait_(db) {
|
||||||
|
let trait_data = db.trait_data(trait_.id);
|
||||||
|
write!(f, " {} for", trait_data.name.display(db.upcast()))?;
|
||||||
|
}
|
||||||
|
|
||||||
|
f.write_char(' ')?;
|
||||||
|
impl_.self_ty(db).hir_fmt(f)?;
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
impl HirDisplay for SelfParam {
|
impl HirDisplay for SelfParam {
|
||||||
fn hir_fmt(&self, f: &mut HirFormatter<'_>) -> Result<(), HirDisplayError> {
|
fn hir_fmt(&self, f: &mut HirFormatter<'_>) -> Result<(), HirDisplayError> {
|
||||||
let data = f.db.function_data(self.func);
|
let data = f.db.function_data(self.func);
|
||||||
|
@ -562,6 +587,16 @@ fn write_where_clause(
|
||||||
) -> Result<bool, HirDisplayError> {
|
) -> Result<bool, HirDisplayError> {
|
||||||
let params = f.db.generic_params(def);
|
let params = f.db.generic_params(def);
|
||||||
|
|
||||||
|
let container = match def {
|
||||||
|
GenericDefId::FunctionId(id) => match id.lookup(f.db.upcast()).container() {
|
||||||
|
ItemContainerId::ImplId(it) => Some(("impl", it.into())),
|
||||||
|
ItemContainerId::TraitId(it) => Some(("trait", it.into())),
|
||||||
|
_ => None,
|
||||||
|
}
|
||||||
|
.map(|(name, def)| (name, f.db.generic_params(def))),
|
||||||
|
_ => None,
|
||||||
|
};
|
||||||
|
|
||||||
let no_displayable_pred = |params: &Interned<GenericParams>| {
|
let no_displayable_pred = |params: &Interned<GenericParams>| {
|
||||||
params.where_predicates.iter().all(|pred| {
|
params.where_predicates.iter().all(|pred| {
|
||||||
matches!(
|
matches!(
|
||||||
|
@ -572,13 +607,20 @@ fn write_where_clause(
|
||||||
})
|
})
|
||||||
};
|
};
|
||||||
|
|
||||||
if no_displayable_pred(¶ms) {
|
if no_displayable_pred(¶ms)
|
||||||
|
&& container.as_ref().map_or(true, |(_, p)| no_displayable_pred(p))
|
||||||
|
{
|
||||||
return Ok(false);
|
return Ok(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
f.write_str("\nwhere")?;
|
f.write_str("\nwhere")?;
|
||||||
write_where_predicates(¶ms, f)?;
|
write_where_predicates(¶ms, f)?;
|
||||||
|
|
||||||
|
if let Some((name, container_params)) = container {
|
||||||
|
write!(f, "\n // Bounds from {}:", name)?;
|
||||||
|
write_where_predicates(&container_params, f)?;
|
||||||
|
}
|
||||||
|
|
||||||
Ok(true)
|
Ok(true)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue