# RustDoc: Group methods for easy of navigation

**URL:** <https://internals.rust-lang.org/t/rustdoc-group-methods-for-easy-of-navigation/20392>\
**Category:** documentation\
**Created:** [February 26, 2024, 3:49pm UTC](https://internals.rust-lang.org/t/rustdoc-group-methods-for-easy-of-navigation/20392 "2024-02-26T15:49:14Z")\
**Posts on this page:** 19\
**Page:** 1

<div class="post-metadata">

**Author:** ![hack.augusto](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/hack.augusto/32/11855_2.png) [@hack.augusto](https://internals.rust-lang.org/u/hack.augusto)\
**Post date:** [February 26, 2024, 3:49pm UTC](https://internals.rust-lang.org/t/rustdoc-group-methods-for-easy-of-navigation/20392/1 "2024-02-26T15:49:14Z")

</div>

I couldn't find an issue/topic about this, pardon me if I missed it.

This is a small feature request, to categorize a trait/impl methods by receiver type. The rationale is that when exploring the docs of a new crate, one usually has a goal in mind, for example "I want to find the constructor for this struct". Currently all Method are in the same list, so one has to read all method names. The search would be slightly easier if the methods would be grouped, for example, a constructor would usually have no self (Ignoring builders). It seems like a small change that could make learning new crates a tiny little bit easier.

---

<div class="post-metadata">

**Author:** ![dlight](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/dlight/32/8462_2.png) [@dlight](https://internals.rust-lang.org/u/dlight)\
**Post date:** [February 26, 2024, 5:28pm UTC](https://internals.rust-lang.org/t/rustdoc-group-methods-for-easy-of-navigation/20392/2 "2024-02-26T17:28:45Z")

</div>

Currently they are grouped by impl blocks (which normally implies they are grouped by generic constraints). There could be a button to change the way methods are grouped.

I'm not sure if changing the default grouping is the right choice. For non-generic structs maybe, but it's often useful to know that sometimes a certain set of methods can't be called at all (for example methods implemented for `Struct<SomeType>` and you have a `Struct<OtherType>`)

---

<div class="post-metadata">

**Author:** ![CAD97](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/cad97/32/3460_2.png) [@CAD97](https://internals.rust-lang.org/u/CAD97)\
**Post date:** [February 27, 2024, 12:54am UTC](https://internals.rust-lang.org/t/rustdoc-group-methods-for-easy-of-navigation/20392/3 "2024-02-27T00:54:54Z")

</div>

Ordering _between_ impl blocks is borderline arbitrary (it depends on what order rustdoc discovers the impls), but I'm fairly sure that ordering of items from a single file is always source order. This makes it a choice of the library what order to present functions in, and _typically_ convenient source order corresponds to a reasonable doc discovery order.

If you collapse-all (the `[-]` button), you then get an okay outline of methods displaying name and signature in a presumably relation-clustered order.

I do wish it were more common for types with lots of methods to split (and document!) impl blocks based on conceptual purpose, though. Rustdoc always creates at least reasonable API reference documentation, but it takes specific intent to help it generate _good_ documentation.

---

<div class="post-metadata">

**Author:** ![ehuss](https://avatars.discourse-cdn.com/v4/letter/e/9de0a6/32.png) [@ehuss](https://internals.rust-lang.org/u/ehuss)\
**Post date:** [February 27, 2024, 11:47am UTC](https://internals.rust-lang.org/t/rustdoc-group-methods-for-easy-of-navigation/20392/4 "2024-02-27T11:47:30Z")

</div>

> [@hack.augusto](#):
>
> I couldn't find an issue/topic about this, pardon me if I missed it.

[Consider different page layouts for rustdoc · Issue #74758 · rust-lang/rust · GitHub](https://github.com/rust-lang/rust/issues/74758) is a similar request, which suggests a dynamic way to select different layouts such as by receiver type.

---

<div class="post-metadata">

**Author:** ![hack.augusto](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/hack.augusto/32/11855_2.png) [@hack.augusto](https://internals.rust-lang.org/u/hack.augusto)\
**Post date:** [February 27, 2024, 2:49pm UTC](https://internals.rust-lang.org/t/rustdoc-group-methods-for-easy-of-navigation/20392/5 "2024-02-27T14:49:51Z")

</div>

@ehuss the issue is indeed very similar in spirit, thank you for the ref.

I was trying to propose something much simpler though. Instead of supporting many layouts, just changing the default from:

 ![image](https://us1.discourse-cdn.com/flex002/uploads/rustlang/original/2X/5/5b1c6014982e645aca14a1b9b67dcf5e79305378.png)

From having a single `Methods` subheader into collapsible categories, say `Functions`, `Methods (&self)`, `Methods (&mut self)`, `Methods (self)` would IMO already improve navigation without having to do all the work to support many different visualizations.

This would preserve the maintainer's control to define the order in the content section, as described by @CAD97 , while having extra structure, in addition to the lexical ordering, to easy navigation.

---

<div class="post-metadata">

**Author:** ![kornel](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/kornel/32/2711_2.png) [@kornel](https://internals.rust-lang.org/u/kornel)\
**Post date:** [February 27, 2024, 5:31pm UTC](https://internals.rust-lang.org/t/rustdoc-group-methods-for-easy-of-navigation/20392/6 "2024-02-27T17:31:18Z")

</div>

Xcode supports special comments:

```plaintext
// MARK: Section label goes here

```

which it inserts between methods in its navigation panel.

Rustdoc could have a similar feature for manual grouping of methods.

 ![image](https://us1.discourse-cdn.com/flex002/uploads/rustlang/original/2X/c/cddb2176c348278e6521496f9853b8291b5de23b.jpeg)

`&self` separate from `&mut self` may unnecessarily separate `foo` and `foo_mut` methods, which are often the same thing.

I think source code order is underappreciate by rustdoc. That's the order that must be already logical for the maintainer. Preserving it gives full control to the author.

---

<div class="post-metadata">

**Author:** ![jjpe](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/jjpe/32/9779_2.png) [@jjpe](https://internals.rust-lang.org/u/jjpe)\
**Post date:** [February 27, 2024, 6:26pm UTC](https://internals.rust-lang.org/t/rustdoc-group-methods-for-easy-of-navigation/20392/7 "2024-02-27T18:26:16Z")

</div>

> [@CAD97](#):
>
> I do wish it were more common for types with lots of methods to split (and document!) impl blocks based on conceptual purpose, though.

That sounds at the same time really nice to have, and borderline impossible to implement correctly.

Simple example of what I mean: Constructors are by convention called `new()`, but not all types (can) adhere to that. For example a type that has multiple constructors, to initialize the type in different ways. One could do fuzzy matching there, and it might work reasonably, or it might not e.g. for types that ignore the convention altogether, perhaps because it's a wrapper for a C api where `make_*()`-like constructors are not unheard of.

---

<div class="post-metadata">

**Author:** ![mathstuf](https://avatars.discourse-cdn.com/v4/letter/m/958977/32.png) [@mathstuf](https://internals.rust-lang.org/u/mathstuf)\
**Post date:** [February 27, 2024, 7:02pm UTC](https://internals.rust-lang.org/t/rustdoc-group-methods-for-easy-of-navigation/20392/8 "2024-02-27T19:02:19Z")

</div>

Maybe some way to assign tags to methods for documentation purposes would be good? Some JS (with graceful fallbacks) to do filtering based on tags might be useful. For example "constructors", "helpers", "mutations", "queries", etc.

Also note that receivers can also be `Arc<T>` or `Rc<T>`.

---

<div class="post-metadata">

**Author:** ![CAD97](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/cad97/32/3460_2.png) [@CAD97](https://internals.rust-lang.org/u/CAD97)\
**Post date:** [February 27, 2024, 9:01pm UTC](https://internals.rust-lang.org/t/rustdoc-group-methods-for-easy-of-navigation/20392/9 "2024-02-27T21:01:35Z")

</div>

I'm not saying for rustdoc to create this grouping, but for the source to the authored with this grouping. Example: my [cstr8](https://docs.rs/cstr8/latest/cstr8/struct.CStr8.html) crate could put all the methods into a single `impl` block, but instead does

```rust
/// Explicit conversions.
impl CStr8 {
    pub const fn as_str(&self) -> &str;
    pub const fn as_c_str(&self) -> &CStr;
    // …
}

/// Constructors.
impl CStr8 {
    pub fn from_utf8_with_nul(v: &[u8]) -> Result<&CStr8, CStr8Error>;
    pub fn from_utf8_until_nul(v: &[u8]) -> Result<&CStr8, CStr8Error>;
    // …
}

```

Also, FWIW, the compiler already uses a "constructorish" heuristic that it uses for error help (roughly that it returns `Self` or `Result<Self, _>` and doesn't have any parameter types that mention `Self`).

---

<div class="post-metadata">

**Author:** ![hack.augusto](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/hack.augusto/32/11855_2.png) [@hack.augusto](https://internals.rust-lang.org/u/hack.augusto)\
**Post date:** [February 28, 2024, 2:42pm UTC](https://internals.rust-lang.org/t/rustdoc-group-methods-for-easy-of-navigation/20392/10 "2024-02-28T14:42:11Z")

</div>

Just one thing that I'd like to point out.

Having the maintainers authoring the code such that the documentation is easy to use is great. This gives control to professionally developed and maintained libraries, which is great.

But focusing only on that type of maintenance excludes a lot of the code out there. The motivation for me to start this thread was exactly because I was using rust embedded libraries. A lot of these libraries are hacked together and maintained as a hobby project, and don't have that level of attention to detail.

I think it is great to have control over how things are displayed by rustdoc when I'm writing code for my full time job, and I appreciate having control over the docs. But at the same time, I don't think it should be assumed that every library out there will have that level of attention to detail, and "lack of attention" can exist for very fair reasons, like someone that reverse engineer some obscure protocol and wanted to share the results with the community.

Adding features to make navigation on these cases IMO benefits everyone.

---

<div class="post-metadata">

**Author:** ![DragonDev1906](https://avatars.discourse-cdn.com/v4/letter/d/e68b1a/32.png) [@DragonDev1906](https://internals.rust-lang.org/u/DragonDev1906)\
**Post date:** [March 1, 2024, 9:42am UTC](https://internals.rust-lang.org/t/rustdoc-group-methods-for-easy-of-navigation/20392/11 "2024-03-01T09:42:06Z")

</div>

Wouldn't something like this be the simplest/most flexible solution (macro/attribute name chosen arbitrarily, doc probably can't be used), which doesn't require heuristics?

```rust
impl CStr8 {
    #[doc(group = "Constructors", priority = 2)] // Obvisouly not a constructor
    pub const fn a(&self) -> &str;
    #[doc(group = "SomeOtherGroupName", priority = 3)]
    pub const fn b(&self) -> &CStr;
    #[doc(group = "Conversion Methods", priority = 3)]
    pub const fn c(&self) -> &CStr;
    #[doc(group = "Constructors", priority = 6)]
    pub const fn d(&self) -> &CStr;

    pub const fn e(&self) -> &CStr;
    #[doc(priority = 4)]
    pub const fn f(&self) -> &CStr;
    pub const fn g(&self) -> &CStr;
}

```

This would let the author decide how it should be displayed, under which groups, how they should be named and in which order, regardless of the implementation order in the files or how they're put into impl blocks.

Since this allows setting multiple priorities for a group the following would have to be decided for group ordering:

- Group Priority = max(priorities) // Probably best and easiest to understand
- Group Priority = min(priorities) // Not sure why you'd want that
- Group Priority = average(priorities)

In the following I'm going to assume max(priorities):

This would result in the following:

- `Constuctors` Because it has the highest group priority: max(2, 6) = 8
  - `d` Because the priority (6) is higher than that of `a` (2)
  - `a`

- `SomeOtherGroupName` They have the same priority, so it's up to the compiler which will probably choose based on the order in the file
  - `b`

- `Conversion Methods`
  - `c`

- Ungrouped
  - `f` Because it's the only one with a priority set
  - `e` Order between `e` and `g` is up to the compiler again
  - `g`

Basically if `group` is not set put it into ungrouped (which could be sorted by impl block) and if the priority is not set read it as 0.

If it can be set on an entire impl block (especially the group one would be useful) it works the same and applies to all below it that don't overwrite `category` or `priority`, thus giving you the per-impl-block sorting we have but with a way to give it a name and a priority to set which group shows up higher in the docs.

---

<div class="post-metadata">

**Author:** ![jpleyer](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/jpleyer/32/10849_2.png) [@jpleyer](https://internals.rust-lang.org/u/jpleyer)\
**Post date:** [March 1, 2024, 9:50am UTC](https://internals.rust-lang.org/t/rustdoc-group-methods-for-easy-of-navigation/20392/12 "2024-03-01T09:50:09Z")

</div>

> [@hack.augusto](#):
>
> I think it is great to have control over how things are displayed by rustdoc when I'm writing code for my full time job, and I appreciate having control over the docs. But at the same time, I don't think it should be assumed that every library out there will have that level of attention to detail, and "lack of attention" can exist for very fair reasons, like someone that reverse engineer some obscure protocol and wanted to share the results with the community.
> 
> Adding features to make navigation on these cases IMO benefits everyone.

This is very important I believe. Sensible defaults for simple use-cases such that it "just works" for all the basic cases are so important in development of any new project.

I am so glad that this topic gets some attention. ❤

---

<div class="post-metadata">

**Author:** ![jpleyer](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/jpleyer/32/10849_2.png) [@jpleyer](https://internals.rust-lang.org/u/jpleyer)\
**Post date:** [March 3, 2024, 6:29am UTC](https://internals.rust-lang.org/t/rustdoc-group-methods-for-easy-of-navigation/20392/13 "2024-03-03T06:29:31Z")

</div>

Maybe we could have a config file for which groups do exist such that linters can easily check for typos. Something along the lines of

```toml
# DocGroups.toml
[groups]
# Set inheritance of groups to false by default
inherit = false

[crate]
groups = [
    # This group will be available for every submodule of the crate
    { name = "config", inherit = true },
]

# These are module-specific groups
[crate.module1.submodule_alpha]
groups = [
    "Methods",
    { name = "methods-ref-self", display = "Methods `(&self)`" },
    { "methods-ref-mut-self", display = "Methods `(&mut self)`" },
]

```

This would avoid typos such as

```rust
impl MyConfig {
    #[doc_groups("Config")]
    fn new() -> Self {...}

    #[doc_groups("methods_ref_self")]
    fn uuid(&self) -> u64 {...}
}

```

and they can be caught directly inside an IDE since every valid group needs to be specified.

I am very open for feedback on this.

---

<div class="post-metadata">

**Author:** ![jpleyer](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/jpleyer/32/10849_2.png) [@jpleyer](https://internals.rust-lang.org/u/jpleyer)\
**Post date:** [March 3, 2024, 6:38am UTC](https://internals.rust-lang.org/t/rustdoc-group-methods-for-easy-of-navigation/20392/14 "2024-03-03T06:38:32Z")

</div>

I always organize my crate into submodules which contain encapsulated functionality (at least aim to do so). This structure is more difficult when importing from this crate and I usually prefer a flat layout structure without any prelude where I either provide every public object or at least every commonly used one a bit like [syn](https://docs.rs/syn/latest/syn/).

I would love to also have the option to group at this level of documentation.

---

<div class="post-metadata">

**Author:** ![vague](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/vague/32/9179_2.png) [@vague](https://internals.rust-lang.org/u/vague)\
**Post date:** [March 7, 2024, 7:24am UTC](https://internals.rust-lang.org/t/rustdoc-group-methods-for-easy-of-navigation/20392/15 "2024-03-07T07:24:29Z")

</div>

I really want a new interface for rustdoc to have the feature in OP, and more opinionated functionalities.

So I'm working on [GitHub - zjp-CN/term-rustdoc: [WIP] A TUI for Rust docs that aims to improve the UX on tree view and generic code.](https://github.com/zjp-CN/term-rustdoc)

Specifically for the topic here, I drew the desgin in repo before seeing OP.

```rust
                                                                                                     
   ┌───────────┐ Navigation Panel    
   │Item Detail│ ┌────────────────────┐
   └─────┬─────┘ │Module Tree │
         │ ┌───────┐ │Field/Variant Tree │
         ├─────────┤Modules│ │ITAB Impl Tree │
         │ └───────┘ │Args Type Tree │
         │ │Return Type Tree │
         │ ┌───────────────────┐ ┌───────────────┐ │Construct Fn Tree │
         │ │Data Structures ├─┬────►│Fields/Varaints│ │Non-receiver Fn Tree│
         ├─────────┤(struct/enum/union)│ │ └───────────────┘ └────────────────────┘
         │ └───────────────────┘ │                                                           
         │ ▲ │                                                           
         │ │ │ ┌─────┐ For methods in all Impls                      
         │ │ ├────►│Impls├────────────────────────┐                      
         │ ┌────────┐ │ │ └───┬─┘ │                      
         ├───│Funcions│ │ │ ├─────► Inherent methods │                      
         │ └──┬─────┘ │ │ │ │                      
         │ │ ┌──────────┐ │ │ Sort ├─────► Trait methods │                      
         │ ├──►│Args Types├───┐ │ │ By Name │ │                      
         │ │ └──────────┘ ├─┤ │ In kinds├─────► Auto traits │                      
         │ │ ┌───────────┐ ├─┤ │ │ │                      
         │ └──►│Return Type├──┘ │ │ └─────► Blanket traits │                      
         │ └───────────┘ │ │ │                      
         │ │ │ ┌───────┘                      
         │ │ │ │ ┌──────────────────┐      
         │ ┌──────┐ │ │ ├───►│Sort By Args Types├───┐  
         └───┤Traits│ │ │ No │ └──────────────────┘ │  
             └─┬────┘ TODO │ │ ITAB│ ┌───────────────────┐ │  
               │ ┌────────────────┐ │ │ └───►│Sort By Return Type├──┤  
               │ │Sub/Super traits│ │ │ └───────────────────┘ │  
               │ │Assoc Types │ │ │ ┌───────────────────┐ │  
               └──┤Type Parameters │ │ ├─────│Construct Functions│ fn(...) -> Self │  
                  │Method Args │ │ │ └───────────────────┘ │ │  
                  │Method Return │ │ │ ┌───────────────────┐ │ │  
                  └───────┬────────┘ │ └─────│Used as an argument│ │ │  
                          │ │ └───────────────────┘ │ │  
                          │ │ fn(.., Self) -> ... │ │  
                          │ │ i.e. non-receiver fn │ │  
                          ▼ ▼ │ │ │  
  ┌────────────────────────────────────────────┐ │ │ │  
  │ ┌──► Concrete Types │ │ │ │  
  │ │ │ │ │ │  
  │Types──┤ │ │ │ │  
  │ │ ┌─► Semi Generic │◄────────┴───────────────────────┴────────────────┘  
  │ └──► Generic Types──┤ │                                                     
  │ └─► Fully Generic│                                                     
  └────────────────────────────────────────────┘                                                     

```

---

<div class="post-metadata">

**Author:** ![jpleyer](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/jpleyer/32/10849_2.png) [@jpleyer](https://internals.rust-lang.org/u/jpleyer)\
**Post date:** [March 7, 2024, 12:05pm UTC](https://internals.rust-lang.org/t/rustdoc-group-methods-for-easy-of-navigation/20392/16 "2024-03-07T12:05:31Z")

</div>

I like your project but I personally will probably not use it. I would much rather prefer a tool that generates a static website such as rustdoc such that I can upload the documentation where everyone can see it and still keep it customized.

---

<div class="post-metadata">

**Author:** ![jpleyer](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/jpleyer/32/10849_2.png) [@jpleyer](https://internals.rust-lang.org/u/jpleyer)\
**Post date:** [March 13, 2024, 9:31am UTC](https://internals.rust-lang.org/t/rustdoc-group-methods-for-easy-of-navigation/20392/17 "2024-03-13T09:31:45Z")

</div>

I am not familiar with the structure of rustdoc but I would like to get started and just see how far I can come. Can anyone point me into the right direction where to look initially to possibly get started on this topic?

---

<div class="post-metadata">

**Author:** ![Uther](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/uther/32/6225_2.png) [@Uther](https://internals.rust-lang.org/u/Uther)\
**Post date:** [March 14, 2024, 7:28am UTC](https://internals.rust-lang.org/t/rustdoc-group-methods-for-easy-of-navigation/20392/18 "2024-03-14T07:28:28Z")

</div>

Long time ago, I had an idea to redesign the Rust doc. I made [a prototype in full JavaScript](https://utherii.github.io/new2.html?item=std/borrow/enum.Cow.html) (not for real use: incomplete and with a lot of bugs) to let me test quickly alternatives before submitting contribution, It helped me eliminate a lot of bad ideas.

If I talk about it there, it is because I added a summary section with different ways to group the methods (name, implementation, self type, return type). I had not enough spare time to turn that in actual contribution. I plan to do that soon, but there is still much to discuss.

---

<div class="post-metadata">

**Author:** ![system](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/system/32/14092_2.png) [@system](https://internals.rust-lang.org/u/system)\
**Post date:** [June 12, 2024, 7:29am UTC](https://internals.rust-lang.org/t/rustdoc-group-methods-for-easy-of-navigation/20392/19 "2024-06-12T07:29:20Z")

</div>

Closed on June 12, 2024, 7:29am UTC

This topic was automatically closed 90 days after the last reply. New replies are no longer allowed.
