From 184ddc6f5ba020ce78abf6822f450a9028ab89ed Mon Sep 17 00:00:00 2001 From: roife Date: Sat, 8 Jun 2024 03:16:22 +0800 Subject: [PATCH] feat: show type bounds from containers for functions --- crates/hir/src/display.rs | 52 +++++++++++++++++++++++++++++++++++---- 1 file changed, 47 insertions(+), 5 deletions(-) diff --git a/crates/hir/src/display.rs b/crates/hir/src/display.rs index 1d8bbf9de6..7e16fbf21e 100644 --- a/crates/hir/src/display.rs +++ b/crates/hir/src/display.rs @@ -8,7 +8,7 @@ use hir_def::{ }, lang_item::LangItem, type_ref::{TypeBound, TypeRef}, - AdtId, GenericDefId, + AdtId, GenericDefId, ItemContainerId, ItemTreeLoc, Lookup, }; use hir_ty::{ display::{ @@ -22,7 +22,7 @@ use itertools::Itertools; use crate::{ 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, TypeOrConstParam, TypeParam, Union, Variant, }; @@ -35,11 +35,18 @@ impl HirDisplay for Function { let mut module = self.module(db); 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. module = module.nearest_non_block_module(db); } - _ => {} + None => {} } let module_id = module.id; 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 { fn hir_fmt(&self, f: &mut HirFormatter<'_>) -> Result<(), HirDisplayError> { let data = f.db.function_data(self.func); @@ -562,6 +587,16 @@ fn write_where_clause( ) -> Result { 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| { params.where_predicates.iter().all(|pred| { 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); } f.write_str("\nwhere")?; 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) }