From c49286ca01e65b88625c7123acad290f705978e7 Mon Sep 17 00:00:00 2001 From: Joseph Ferano Date: Sat, 12 Sep 2026 13:56:24 +0700 Subject: [PATCH] Structural identity is not implicit conversion, and writability decides the layout question --- DISCUSS.md | 25 +++++++++++++++++++------ 1 file changed, 19 insertions(+), 6 deletions(-) diff --git a/DISCUSS.md b/DISCUSS.md index 6bdbbf1..7532df2 100644 --- a/DISCUSS.md +++ b/DISCUSS.md @@ -128,15 +128,28 @@ front-end question, not a data-model change. **Two costs, and the second is the real work:** -- **It cuts against the project's standing instinct.** This language has repeatedly chosen explicit over convenient: no - implicit numeric conversions, a bare integer cannot become an enum, `:spcae` must fail at the call site. Structural - typing says things are compatible when they happen to line up, which is the opposite reflex. Worth deciding - deliberately rather than drifting into — and worth asking whether structural compatibility should be *written* at the - site that relies on it, the way `(GamepadAxis n)` made an enum conversion explicit without making it implicit. +- **Not an "explicit over convenient" question — that framing was wrong and is recorded so it is not repeated.** The + standing rules about implicit numeric conversion and about a bare integer not becoming an enum are about *lossy* + things happening silently. A structural match is not lossy; it is a different notion of type *identity*. The two were + lumped together in conversation and the author rejected the pairing, correctly. Strong typing and nominal typing are + separate choices and this only touches the second. - **Field order is layout, and that is the hard part.** `{x f32, y f32}` and `{y f32, x f32}` have the same fields and different memory. So either field order becomes significant — surprising, since nothing else about a structural type should be — or matching a differently-ordered type requires a copy, which breaks the zero-cost property the whole data - model rests on. This is the question to settle first; the type checking is comparatively easy. + model rests on. Accepted in conversation as a limitation to respect rather than fight. + +**Writability is what decides whether the copy escape exists.** Fields would be writable on the same terms as any struct: +by value you get a copy and writes are local; through a `(Ptr T)` they reach the original. But that settles the layout +question rather than sitting beside it. *Read-only* structural access has an out — the compiler could gather the +requested fields into a temporary, and then field order would not matter at all. *Writable* structural access cannot: +it has to alias the real storage, so the layout must genuinely line up. Decide writability first; the layout answer +follows from it. + +**`defclass` may solve this, for the cases that can afford it.** A class has an implementation-defined representation, so +the compiler owns the layout and access goes through metadata rather than a fixed offset — field order stops being a +user-visible fact. The limit is that a class carries identity and metadata, and a `Vector2` should not pay for either. +So plain structs still need their own answer and classes only cover the cases where the overhead was already accepted. +See item 7. Also unresolved: the shim generates a C typedef per *named* struct, and an anonymous struct has no name to generate one from. Either anonymous structs cannot cross the FFI, or the generator learns to name them.