about summary refs log tree commit diff
diff options
context:
space:
mode:
authorroife <roifewu@gmail.com>2024-06-08 03:16:22 +0800
committerroife <roifewu@gmail.com>2024-06-11 21:02:13 +0800
commite5f859868e18f78073330d5d05548c98f7ce192a (patch)
tree26780c49bc8df63b984ac7f7bd6d78ee7765ffc7
parent80a2ac568108dbe1af674a7ac6f48adf74b0619e (diff)
downloadrust-e5f859868e18f78073330d5d05548c98f7ce192a.tar.gz
rust-e5f859868e18f78073330d5d05548c98f7ce192a.zip
feat: show type bounds from containers for functions
-rw-r--r--src/tools/rust-analyzer/crates/hir/src/display.rs52
1 files changed, 47 insertions, 5 deletions
diff --git a/src/tools/rust-analyzer/crates/hir/src/display.rs b/src/tools/rust-analyzer/crates/hir/src/display.rs
index 1d8bbf9de6d..7e16fbf21e9 100644
--- a/src/tools/rust-analyzer/crates/hir/src/display.rs
+++ b/src/tools/rust-analyzer/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<bool, HirDisplayError> {
     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>| {
         params.where_predicates.iter().all(|pred| {
             matches!(
@@ -572,13 +607,20 @@ fn write_where_clause(
         })
     };
 
-    if no_displayable_pred(&params) {
+    if no_displayable_pred(&params)
+        && container.as_ref().map_or(true, |(_, p)| no_displayable_pred(p))
+    {
         return Ok(false);
     }
 
     f.write_str("\nwhere")?;
     write_where_predicates(&params, f)?;
 
+    if let Some((name, container_params)) = container {
+        write!(f, "\n    // Bounds from {}:", name)?;
+        write_where_predicates(&container_params, f)?;
+    }
+
     Ok(true)
 }