Skip to content

Commit e5f8598

Browse files
committed
feat: show type bounds from containers for functions
1 parent 80a2ac5 commit e5f8598

File tree

1 file changed

+47
-5
lines changed

1 file changed

+47
-5
lines changed

src/tools/rust-analyzer/crates/hir/src/display.rs

+47-5
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ use hir_def::{
88
},
99
lang_item::LangItem,
1010
type_ref::{TypeBound, TypeRef},
11-
AdtId, GenericDefId,
11+
AdtId, GenericDefId, ItemContainerId, ItemTreeLoc, Lookup,
1212
};
1313
use hir_ty::{
1414
display::{
@@ -22,7 +22,7 @@ use itertools::Itertools;
2222

2323
use crate::{
2424
Adt, AsAssocItem, AssocItem, AssocItemContainer, Const, ConstParam, Enum, ExternCrateDecl,
25-
Field, Function, GenericParam, HasCrate, HasVisibility, LifetimeParam, Macro, Module,
25+
Field, Function, GenericParam, HasCrate, HasVisibility, Impl, LifetimeParam, Macro, Module,
2626
SelfParam, Static, Struct, Trait, TraitAlias, TupleField, TyBuilder, Type, TypeAlias,
2727
TypeOrConstParam, TypeParam, Union, Variant,
2828
};
@@ -35,11 +35,18 @@ impl HirDisplay for Function {
3535
let mut module = self.module(db);
3636

3737
match container {
38-
Some(AssocItemContainer::Impl(_)) => {
38+
Some(AssocItemContainer::Trait(trait_)) => {
39+
write_trait_header(&trait_, f)?;
40+
f.write_str("\n")?;
41+
}
42+
Some(AssocItemContainer::Impl(impl_)) => {
43+
write_impl_header(&impl_, f)?;
44+
f.write_str("\n")?;
45+
3946
// Block-local impls are "hoisted" to the nearest (non-block) module.
4047
module = module.nearest_non_block_module(db);
4148
}
42-
_ => {}
49+
None => {}
4350
}
4451
let module_id = module.id;
4552
write_visibility(module_id, self.visibility(db), f)?;
@@ -129,6 +136,24 @@ impl HirDisplay for Function {
129136
}
130137
}
131138

139+
fn write_impl_header(impl_: &Impl, f: &mut HirFormatter<'_>) -> Result<(), HirDisplayError> {
140+
let db = f.db;
141+
142+
f.write_str("impl")?;
143+
let def_id = GenericDefId::ImplId(impl_.id);
144+
write_generic_params(def_id, f)?;
145+
146+
if let Some(trait_) = impl_.trait_(db) {
147+
let trait_data = db.trait_data(trait_.id);
148+
write!(f, " {} for", trait_data.name.display(db.upcast()))?;
149+
}
150+
151+
f.write_char(' ')?;
152+
impl_.self_ty(db).hir_fmt(f)?;
153+
154+
Ok(())
155+
}
156+
132157
impl HirDisplay for SelfParam {
133158
fn hir_fmt(&self, f: &mut HirFormatter<'_>) -> Result<(), HirDisplayError> {
134159
let data = f.db.function_data(self.func);
@@ -562,6 +587,16 @@ fn write_where_clause(
562587
) -> Result<bool, HirDisplayError> {
563588
let params = f.db.generic_params(def);
564589

590+
let container = match def {
591+
GenericDefId::FunctionId(id) => match id.lookup(f.db.upcast()).container() {
592+
ItemContainerId::ImplId(it) => Some(("impl", it.into())),
593+
ItemContainerId::TraitId(it) => Some(("trait", it.into())),
594+
_ => None,
595+
}
596+
.map(|(name, def)| (name, f.db.generic_params(def))),
597+
_ => None,
598+
};
599+
565600
let no_displayable_pred = |params: &Interned<GenericParams>| {
566601
params.where_predicates.iter().all(|pred| {
567602
matches!(
@@ -572,13 +607,20 @@ fn write_where_clause(
572607
})
573608
};
574609

575-
if no_displayable_pred(&params) {
610+
if no_displayable_pred(&params)
611+
&& container.as_ref().map_or(true, |(_, p)| no_displayable_pred(p))
612+
{
576613
return Ok(false);
577614
}
578615

579616
f.write_str("\nwhere")?;
580617
write_where_predicates(&params, f)?;
581618

619+
if let Some((name, container_params)) = container {
620+
write!(f, "\n // Bounds from {}:", name)?;
621+
write_where_predicates(&container_params, f)?;
622+
}
623+
582624
Ok(true)
583625
}
584626

0 commit comments

Comments
 (0)