Background
Raised during review of PR #248 (implement-unused-variable-diagnostics).
The design document docs/ddlint-design.md currently states that rule-local Symbol::span() values are coarse provenance (pointing to the enclosing rule or literal site). This is correct for the current implementation. However, nothing in the document makes explicit:
- that
Span → TextRange conversion is the linter's responsibility, not the semantic model's;
- that the coarse semantics of
Symbol::span() must not be silently changed when exact identifier locations become desirable;
- that exact identifier-token spans are a deferred milestone, not an oversight.
Without this written contract, the author of the next correctness rule may either duplicate the local conversion glue or quietly change Symbol::span() to point at the identifier token, breaking the coarse-provenance contract relied on by maps and debugging tooling.
Concern (Doggylump & Telefono)
Write the contract down before the next rule is started. One short addition to the design document is cheaper than a post-hoc migration.
Recommended change
Add a subsection to the relevant section of docs/ddlint-design.md (the semantic-model or diagnostic-rendering section) covering:
- Conversion ownership: the linter crate owns
Span → rowan::TextRange conversion. The semantic model stores Span as coarse provenance; it does not vend TextRange.
- Stability of
Symbol::span(): the existing span() accessor returns the coarse declaration or literal site. Its meaning must not change. If exact identifier-token location is required, a separate field (e.g. name_span or identifier_span) must be added additively.
- Deferred milestone: exact identifier-token spans are a planned but deferred semantic-model enhancement. Rules written before that milestone use coarse spans; rules written after may opt in to the precise field without breaking earlier rules.
Example wording (illustrative, not prescriptive)
Diagnostic range conversion. The semantic model stores all span information as Span (byte-offset pairs). Converting a Span to a rowan::TextRange for use in a LintDiagnostic is the linter's responsibility and is performed by the shared helper in src/linter/support/span.rs.
Symbol::span() returns coarse provenance — the enclosing rule or literal site — and its semantics are stable. When precise identifier-token location is required, add an additive name_span field to the relevant semantic record rather than redefining span().
Exact identifier-token spans are a deferred milestone; see roadmap item TBD.
Acceptance criteria
Related
Background
Raised during review of PR #248 (implement-unused-variable-diagnostics).
The design document
docs/ddlint-design.mdcurrently states that rule-localSymbol::span()values are coarse provenance (pointing to the enclosing rule or literal site). This is correct for the current implementation. However, nothing in the document makes explicit:Span → TextRangeconversion is the linter's responsibility, not the semantic model's;Symbol::span()must not be silently changed when exact identifier locations become desirable;Without this written contract, the author of the next correctness rule may either duplicate the local conversion glue or quietly change
Symbol::span()to point at the identifier token, breaking the coarse-provenance contract relied on by maps and debugging tooling.Concern (Doggylump & Telefono)
Write the contract down before the next rule is started. One short addition to the design document is cheaper than a post-hoc migration.
Recommended change
Add a subsection to the relevant section of
docs/ddlint-design.md(the semantic-model or diagnostic-rendering section) covering:Span → rowan::TextRangeconversion. The semantic model storesSpanas coarse provenance; it does not vendTextRange.Symbol::span(): the existingspan()accessor returns the coarse declaration or literal site. Its meaning must not change. If exact identifier-token location is required, a separate field (e.g.name_spanoridentifier_span) must be added additively.Example wording (illustrative, not prescriptive)
Acceptance criteria
docs/ddlint-design.mdcontains an explicit statement thatSpan → TextRangeconversion belongs to the linter.Symbol::span()semantics are stable and must not be silently changed.Related
Span → TextRangehelper (see companion issue).