ADR-307: A Comment Is // or a Nesting /* … */, and a Run of /// Before an Item Is Its Documentation — Prose the Parser Keeps and the Contract Does Not Carry

Status: Accepted Date: October 3, 2026 History: the records this one replaces are archived in docs/history/adr; read them only for how the decision was reached Answers: what a comment is besides // (a block of code commented out, a paragraph above a function, a note inside an argument list), whether a block comment nests, and whether the language has a doc comment, how it is spelled, and what reads it Related: ADR-251 D2 (the contract carries no prose; std.contracts keeps its sentences as # comments); ADR-296 (a grammar { … } block’s vocabulary is its own page, so a /* inside one, or inside a dsl … eod body, is text); ADR-024 (the ledger is what a consumer’s compiler reads about a dependency); Part I chapter 2 (the comment rule as a program follows it); Part III 13.5 (the contract)

1. Question

Which forms of comment does the language have, and is one of them an item’s documentation — and if so, what reads it?

A line comment is enough for a sentence beside a statement and not for commenting out a block of code that already holds a comment, for a paragraph above a function, or for a note inside an argument list. And a package’s surface is read by people and tools that never open its source; whether a sentence written above a function belongs to that function has to be a rule, not a convention, before anything can carry it.

2. How others do it

Language / tool Its answer Source
C, JavaScript /* … */ exists and does not nest: the first */ closes it from memory, not checked
Rust /* … */ nests; /// and /** … */ are doc comments, //! and /*! inner doc comments from memory, not checked
Most languages with both // and /// //// is an ordinary comment from memory, not checked

What does not transfer: Rust has two spellings of a doc comment, and a reader of this language would have to learn which one a project uses. One spelling is enough.

3. Options, weighed

Question Option Verdict
Block comment none (only //) rejected: no way to comment out a block or annotate inside an argument list
  /* … */ that does not nest (C) rejected: commenting out code that already holds a block comment means hunting for the inner close
  /* … */ that nests (Rust) chosen (D1, D2)
Unclosed comment reported where the input ran out rejected: that is the end of the file, which points at nothing the reader must fix
  reported at the /* that opened it chosen (D2)
Doc comment /** … */ as well as /// rejected: two spellings; a block comment stays a comment wherever it stands (D3)
  /// before an item chosen (D4)
Markup @param and directives the compiler reads rejected: prose only (D6)
Where the prose goes a doc column in the contract rejected: the compiler never reads it, and a reworded sentence would fail --locked on a contract that had not changed (ADR-251 D2)
  the source only chosen (D5)

4. Decision

D1 — /* opens a comment that */ closes, across lines, anywhere whitespace may stand.

A block comment may stand between any two tokens, inside an argument list, inside a grammar { … } block, across as many lines as it needs. It is whitespace to the parser, as a line comment is. A /* inside a string literal is text, not a comment; a // inside a block comment is comment, not a second comment.

D2 — Block comments nest, and an unclosed one is reported where it opened.

/* a /* b */ c */ is one comment that ends at the second */, so a block of code that already holds a block comment can be commented out without hunting for the inner close. An unclosed block comment is a parse error reported at the /* that opened it — at the outer opening when a nested one is what is missing — because that is where the reader must fix it, not the end of the file where the parser gave up.

D3 — /** … */ and /*! … */ are block comments and nothing more.

A comment that begins with two stars, or with a star and a bang, is a comment. The language’s one documentation form is D4’s, and it is not spelled with a block comment.

D4 — A run of /// lines immediately before an item is that item’s documentation, and the parser keeps it.

/// The status line for a response code, as HTTP/1.1 writes it.
///
/// An unknown code is `500 Internal Server Error`, which is what a
/// server owes a client it cannot answer.
pub fn status_line(status: i32) -> String { … }

An item here is a fn (a method and a trait method included), a struct, an enum, a trait, a field and a variant. The text is the run’s lines with the slashes and one space taken off, joined by their own line breaks. Anywhere else /// is an ordinary comment, and //// is an ordinary comment everywhere.

An ordinary comment between the run and the item does not end the run: a comment is not code, so the prose is still about the item below it, and a sentence for whoever reaches the item followed by a note for whoever reads the source is a shape worth allowing. What ends a run is code: prose with a statement or another item between it and the next item belongs to nothing, and an item does not inherit the prose of the one above it.

D5 — The contract carries no prose.

A doc comment stays in the source. The compiler does not copy it into nikaia.contracts, for a public item or any other, and a ledger that still has a doc key is refused as a key nothing reads; std.contracts, which is written by hand, keeps its sentences as # comments above the entries they are about (ADR-251 D2). Whether a dependency’s documentation needs a way to travel to a consumer is left to something that addresses the contract’s entries rather than living in them (§6).

D6 — A doc comment is prose, and the compiler does not read it.

No @param, no directive, no link the compiler resolves, and no refusal for a wrong one. A doc comment on a private item is kept exactly as one on a public item is: the source is where both live (D5).

D7 — Changing a doc comment changes no contract.

Because the contract carries no prose (D5), rewording a /// leaves nikaia.contracts byte for byte the same: --locked does not fail on it, and the diff narration, which says what broke a caller, has nothing to say. An edited comment shows only in the record of what the contract was derived from, which names the sources it was built from (Part III 13.5).

5. Consequences

6. What this does not decide

This site is open source. Improve this page.