Skip to content

rustdoc: rich-text and visibility-aware formatting for constant values #98929

Open
@fmease

Description

@fmease

While types in rustdoc are richly formatted using HTML (most notably for hyperlinks to definitions),
constant expressions and values do not enjoy any such treatment and are printed as plain text (or
sometimes even entirely omitted from the documentation).
With the continuously growing language support for “const” (const fn, const generics, adt_const_params,
generic_const_exprs, const_trait_impl) which allows ever-more-complex constant expressions in
more and more places, it seems very fitting to improve rustdoc's output to help users navigate this complexity.

I propose the following:

  • We start showing the constant value of free const items no matter their type. At present, only integers, bools and string literals are displayed.
  • We try to use constant values as returned by tcx.const_eval_poly as much as possible for pretty-printing and only fall back on hir::Expr (unevaluated expressions) as a last resort. Currently for free and assoc. consts, rustdoc evaluates arbitrary const expressions of any type (arbitrary ADTs) but throws away the result if the type is not an integer (or similar) and instead prints the unevaluated expression.
  • We try to evaluate const arguments and pretty-print the const value. Right now, we just print their unevaluated form, a hir::Expr.
  • Regarding the formatting / pretty-printing of const values (ConstValue / ValTrees eventually (?)):
    • We print struct and enum literals (as one would expect). Examples: S { f: 0 }, Ok(())
    • However, we also hide private and doc(hidden) fields.
      In non-tuple structs, we skip those fields and add the symbol .. (mirroring the syntax of struct patterns).
      In tuple structs, we replace them with _ (just how it's already done today in the code blocks at the top of tuple struct pages)
    • We make paths and struct fields hyperlinks to their definition.
    • We print a placeholder like [/* N elements */] for large arrays to not clutter the documentation
    • We print a placeholder like maybe /* large string */ for large strings
    • ( Maybe we should also introduce a max-depth parameter similar to the one rustdoc has for types )

Unfortunately rustdoc's current reliance on const_eval_poly means that in a quite a lot of cases – namely those where the const expr contains type or const parameters (including the implicit type parameter Self) –, we aren't gonna get the benefits of this proposed richer pretty-printing since the evaluation will fail on those with the error “too generic“ and we'll have to fall back on printing the unevaluated hir::Expr. This is a known limitation of rustdoc and tracked in #82852.

Parts of this proposal aim to solve #97933 properly whereas #98814 is but a hotfix.
I have already partially implemented this proposal in a local patch that is yet to be published as a PR. You can get a visual taste of it below:

Stable Rustdoc Output Nightly Rustdoc Output (#98814) WIP Implementation of this Proposal
ppconst_stable ppconst_after_hotfix ppconst_linkified

@rustbot label T-rustdoc A-rustdoc-ui C-enhancement
@rustbot claim

Metadata

Metadata

Assignees

Labels

A-rustdoc-uiArea: Rustdoc UI (generated HTML)C-enhancementCategory: An issue proposing an enhancement or a PR with one.T-rustdocRelevant to the rustdoc team, which will review and decide on the PR/issue.

Type

No type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions