go: types.sx — interface satisfaction (structural method-set check) + 7 tests [shapes-static-types-bidirectional]
Some checks failed
Test, Build, and Deploy / test-build-deploy (push) Failing after 23s

Phase 3 cont. The headline Go-distinguishing typing feature: interfaces
are satisfied *structurally and silently* — no `implements` declaration,
no nominal subtyping. Any type whose method set contains all the
interface's methods (with matching signatures) satisfies it.

Method declarations now type-check via go-check-method-decl:

  * Receiver type extracted (T or *T → "T") via go-extract-recv-ty-name.
  * Method signature (:ty-func PARAMS RESULTS) bound under a mangled
    key "#method/RECV-NAME/METHOD-NAME" in ctx.
  * Body checked with receiver + params extended into the body ctx.

go-iface-satisfies? CTX TY-NAME IFACE-TYPE walks the interface's
:method elements; for each, looks up #method/TY-NAME/METHOD-NAME and
compares (PARAMS, RESULTS) tuples. Embedded interfaces (:embed
elements) skipped in v0 — recursive interface resolution later.

Tests:
  * method-decl binds under #method/Point/String
  * pointer-receiver method also keys the base type
  * Point with String() satisfies interface { String() string }
  * empty type does NOT satisfy Stringer
  * arity-mismatch method fails satisfaction
  * multi-method satisfaction works
  * partial method-set fails

types 72/72, total 377/377. Phase 3 sub-deliverable list is now
substantially complete; only AST-path error context remains as a UX
sharpener.

Sister-plan static-types-bidirectional diary updated with the
**constraint-satisfies? pluggable predicate** kit-API proposal —
third pluggable point after synth/check + assignable?. Go interfaces,
Haskell typeclasses, Rust traits, and TS structural subtyping all
answer "does this value-type fit this constraint-type?" with
different machinery; the kit's check uses constraint-satisfies? when
EXPECTED is itself a constraint type.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
2026-05-27 21:05:08 +00:00
parent 4bd9262060
commit 21bb17e4a6
6 changed files with 243 additions and 9 deletions

View File

@@ -250,13 +250,17 @@ Progress-log line → push `origin/loops/go`.
index-keyed shorthand). Nested composite literals work
(`[][]int{[]int{1,2}, []int{3,4}}`). Named-type composite
literals (`Point{...}`) need type-decl resolution; deferred.
- [ ] Interface satisfaction (structural match against method sets).
- [x] Interface satisfaction (structural match against method sets).
Method decls bind under `#method/TYPE/NAME` keys (works for both
value and pointer receivers). `go-iface-satisfies?` walks an
interface's `:method` elements and looks each up; partial sets
and arity-mismatches fail. Embedded interfaces deferred.
- [ ] Short variable declaration `:=` (synth RHS into LHS bindings).
- Defer: generics (Phase 7), full conversion rules, type assertions,
type switches.
- **Acceptance:** types/ suite at 60+ tests. **Bar crossed: 65/65.**
Remaining sub-items (interface satisfaction, error reporting carrying
AST paths) refine but don't gate Phase 4. Chisel note
- **Acceptance:** types/ suite at 60+ tests. **Bar crossed: 72/72.**
Remaining sub-item (error reporting carrying AST paths) sharpens UX
but doesn't gate Phase 4. Chisel note
`shapes-static-types-bidirectional` — sister-plan design diary is the
cross-language record.
@@ -557,6 +561,20 @@ Minimal repro: see `lib/go/lex.sx#gl-oct-digit?` and `#gl-match-op`.
_Newest first. Append one dated entry per commit._
- 2026-05-27 — Phase 3 cont.: **interface satisfaction** — the headline
Go-distinguishing typing feature this loop set out to validate.
Method decls record under `#method/TYPE-NAME/METHOD-NAME` keys in
ctx (value-receiver and pointer-receiver both key the base type).
`go-iface-satisfies? CTX TY-NAME IFACE-TYPE` walks the interface's
`:method` elements and verifies each one is present with a matching
(PARAMS, RESULTS) signature. Embedded interfaces in iface elements
are silently skipped in v0 (recursive interface resolution comes
later). Partial method sets and arity mismatches correctly return
false. types 72/72, total 377/377. `[shapes-static-types-
bidirectional]` — sister-plan diary updated with the structural-
satisfaction primitive the kit should ship.
Sister-plan diary update follows.
- 2026-05-27 — Phase 3 cont.: composite-literal element checking.
`go-synth-composite` dispatches on the literal's type expression:
`:ty-slice` and `:ty-array` check each element assignable to the

View File

@@ -282,6 +282,40 @@ The kits compose; design accordingly.
_Newest first. Append one dated entry per milestone landed._
- 2026-05-27 — From Go-on-SX Phase 3 — **interface satisfaction** is the
third pluggable predicate the kit should ship, alongside `assignable?`
and the synth/check skeleton. Go's structural-and-silent
satisfaction is one instance; Haskell's typeclass dictionary
resolution, Rust's trait `impl` lookup, and TS's structural subtyping
are others — all answer the same question with different machinery:
"does this value-type fit this constraint-type?"
Kit proposal:
```
(constraint-satisfies? CTX VALUE-TY CONSTRAINT-TY) → bool
```
Different consumers plug in different implementations:
* Go: walk interface methods, lookup `#method/T/NAME`.
* Haskell: typeclass instance resolution (with global instance table).
* Rust: trait impl lookup with where-clause bound check.
* TS: structural subtyping with property-by-property comparison.
The judgment skeleton uses it during `check` when the expected type
is itself an interface/constraint:
```
check Γ e EXPECTED →
if EXPECTED is a constraint type:
let GOT = synth Γ e
if constraint-satisfies? Γ GOT EXPECTED then :ok else mismatch
else: use the assignable? path
```
Source: Go-on-SX commit landing `go-iface-satisfies?` in
`lib/go/types.sx` with the `#method/T/NAME` mangled-key storage scheme.
- 2026-05-27 — Follow-up from Phase 3 scaffold: **assignability** has
landed as a separate relation from structural equality. Go's
untyped-constant flow (`var x float64 = 42 / 7` — 42/7 stays untyped