RFA-630 · Case file with fixtures · Case 602 of 694 · Compiler evidence
Inner Documentation Comments Belong Before the Enclosing Items
Use //! at the start of a crate or module to explain the container, and /// immediately before an item to document that item. Treat placement as part of the public documentation structure.
- Reviewed
- Rust
- Rust 1.98.1, edition 2024
- Targets
- all Rust targets
- Profiles
- dev, release, test
Direct answer
What this Rust failure means
- Why it happens
- Documentation punctuation was treated as formatting even though inner and outer comments attach explanations to different syntax owners.
- First discriminating check
- Decide whether the text documents the container or next item, then place //! at the start or /// directly before its item.
Rust documentation comments have a target. //! documents the enclosing crate or module, while /// documents the item that follows it. Placement is therefore syntax, not only typography. The failing fixture puts an inner comment after a function and receives E0753 because the comment cannot retroactively become module documentation there.
Decide what the paragraph explains
I start by asking whether the text introduces a container or one item. A crate-level inner comment should explain the crate’s purpose, important concepts, entry points, and a first useful example. A module inner comment should explain why that group of items exists and how its pieces work together.
An outer comment belongs directly before a function, type, field, trait, or other documentable item. The official E0753 explanation shows both forms and their valid positions. The Reference specifies documentation comments as forms of the doc attribute.
Moving punctuation without deciding the target may make code compile while attaching the explanation to the wrong thing.
The repair can change the target deliberately
The repaired fixture uses /// immediately before prepare, so the sentence documents that function. If the original intent had been module guidance, the correct repair would move //! to the beginning of the module before its items.
I read the generated rustdoc after such a change. A syntactically accepted comment may appear on an unexpected page, be hidden with a private item, or leave a public function unexplained.
For large modules, I put the inner overview at the top and keep item docs focused on contracts. Repeating the same introduction above every function weakens both navigation and maintenance.
Documentation is part of interface design
Good API docs say what a caller needs that the type signature cannot: invariants, errors, panics, cancellation, safety conditions, performance boundaries, and examples. They do not translate each identifier into a longer sentence.
On unsafe functions and traits, the # Safety section defines obligations. On fallible operations, examples include meaningful failure paths. Async functions document cancellation points and whether dropping the future may leave external work running.
Rustdoc links make relationships navigable. I prefer resolved intra-doc links for Rust items and run documentation tests so examples remain compilable. The rustdoc guide on writing documentation provides conventions for useful API pages.
Included and generated docs keep the same rules
#[doc = include_str!(...)] can keep a long module introduction in another file, but it still attaches at the attribute’s location. The included Markdown does not choose its target. I place the attribute before the crate, module, or item it describes and test the generated output.
Macros that emit inner comments are sensitive to invocation context. Tokens valid at the start of an inline module may be invalid after items generated by another macro. Library macros should usually emit outer documentation for the items they create, or accept caller-provided attributes and preserve their order.
When E0753 originates in expanded code, I inspect the expansion and the order of generated items. Editing a visible nearby comment may not touch the actual failing token.
Examples must reflect the real audience
Crate docs can show the happy path from a user’s perspective. Item docs can then show specialised configurations without rebuilding the whole setup. I avoid examples that compile only because hidden imports or private helpers exist.
Doctests can use hidden lines for setup while keeping visible code focused, but too much hidden machinery makes the example misleading. Integration examples are better for multi-file or runtime-heavy behaviour.
Documentation coverage percentages are a weak target by themselves. One clear module overview and a few strong contract pages create more value than boilerplate on every private helper. E0753 is an opportunity to attach the explanation where readers will actually look.
My E0753 checklist
- Does the text explain the enclosing crate or module, or the next item?
- If it is inner documentation, is it before the relevant module contents?
- If it is outer documentation, is it immediately attached to the intended item?
- Did changing comment style alter where rustdoc displays the text?
- Are safety, errors, panics, cancellation, and invariants documented where applicable?
- Do intra-doc links resolve and examples compile?
- Did a macro or included file change the attribute order?
- Does generated documentation tell one coherent story without repeated filler?
The core principle is that documentation syntax establishes ownership of an explanation. E0753 catches text with no valid enclosing target at its position. I choose the audience first, then use inner or outer form so rustdoc places the evidence beside the contract it supports.