Skip to content

Commit 6a992be

Browse files
olwangclaude
andcommitted
selfhost Phase 3: rss checker reaches RS0005 parity (546/546)
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
1 parent 3cc988d commit 6a992be

2 files changed

Lines changed: 1229 additions & 7 deletions

File tree

docs/ledgers/rss-selfhost-ledger.md

Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -574,3 +574,48 @@ gap is VM value-representation / intrinsic-dispatch cost (the next big lever).
574574
- **Tests / bench:** `crate::selfhost_parity::lexer_perf_corpus`
575575
(`--release -- --ignored`).
576576
- **Status:** open (VM/stdlib lever identified; feeds perf roadmap).
577+
578+
### SH-023 — self-hosted checker reaches RS0005 parity at declaration level; the merged callable namespace is the load-bearing rule
579+
580+
- **Tool:** self-hosted checker (`selfhost/check.rss`) run on the reg-VM vs
581+
`crate::analyze_source` filtered to error-severity `RS0005`
582+
(DUPLICATE_DECLARATION), over the whole 546-file corpus.
583+
- **Symptom (positive):** the checker reproduces RS0005 with **546/546** parity
584+
using ONLY top-level declaration structure — no statement/expression/pattern
585+
body parsing (confirms SH-021: RS0005 is decidable from declaration shape). It
586+
reuses the proven `selfhost/parser.rss` recognizer verbatim; the sole addition
587+
is carrying identifier TEXT on each token so names can be compared (the parser
588+
only kept a keyword/word id, which is 0 for all user identifiers).
589+
- **Namespace grouping replicated (the interesting part — truth per
590+
`crate::hir::lower::collect_item_signatures`):** duplicates are detected across
591+
exactly three groups —
592+
1. **callable namespace = fn names + type CONSTRUCTOR names.** Every
593+
`struct`/`resource`/`class`/`opaque` type registers BOTH a type-namespace
594+
entry AND a constructor entry into the SAME map that free functions use, so
595+
`fn Foo` collides with `struct Foo` (not "separate namespaces"). In the
596+
corpus this only matters via `fn`-vs-`fn` (fixture `duplicate-declarations`),
597+
but the faithful rule is the merge.
598+
2. **type namespace = type names + sum names.** Sums register a type entry only
599+
(no constructor, so sums never collide with functions), and sum variant
600+
fields are NOT field-checked.
601+
3. **per-type field names** for `struct`/`resource`/`class`/`opaque` only
602+
(fixture `duplicate-fields`). Implemented as: the token immediately before
603+
each `:` that sits at body-top-level (paren/bracket/angle/brace depth 0),
604+
which cleanly skips `drop { ... }` bodies, fn-typed field params, and
605+
generic type args.
606+
- **Backend:** vm (checker is intrinsic/collection-bound like the lexer, cf.
607+
SH-022; not native-eligible).
608+
- **Root cause / gaps:** none new. All prior constraints held without surprise —
609+
no char literals (SH-016), single-line boolean chains (SH-017), positionally
610+
threaded cursors returned by value (SH-018). `Set<String>` (`Set<String>.new()`,
611+
`Set.contains<String>`, `Set.insert<String>`) worked as the duplicate detector;
612+
`features: local` was NOT needed (no `StringBuilder`/`local` bindings). The
613+
scanner conservatively STOPS on the first malformed/unknown top-level item
614+
(mirroring the recognizer), which can only under-report on syntactically broken
615+
files — safe, since the analyzer emits RS0005 on exactly the 2 well-formed
616+
fixtures and the other 544 files stay CLEAN (zero false positives).
617+
- **Classification:** docs (records the analyzer's duplicate-symbol namespace
618+
rule and that RS0005 is a declaration-only property).
619+
- **Tests:** `crate::selfhost_parity::checker_parity_tiny_sample` and
620+
`crate::selfhost_parity::checker_parity_corpus` (`--ignored`).
621+
- **Status:** done.

0 commit comments

Comments
 (0)