docs(lang): precise reserved-name rule — member-name positions are EXEMPT [F0.6]

AGRA RULING (issue 0089, attempt 7): bare reserved-name MEMBER positions are
intentionally exempt from the reserved-type-name rule, and the implementation
already does the right thing — this is a docs + one-example change, no code.

The exempt member positions are struct FIELD names, union TAG names, and protocol
method-SIGNATURE names: they sit in a member slot, are reached via obj.name (or
dispatched by string), and are never type-classified, so they never mis-lower.
The backtick is optional there. The exemption stops at member DEFINITIONS: an
impl method is a real function (reached through the impl_block -> fn_decl arm), so
a reserved-spelled impl method still needs the backtick, exactly like a free
function (cf. examples/1122) — and every bare reserved-name value binding /
declaration name still errors (0076 preserved).

- specs.md / readme.md: replace the "every binding site" / "any binding site"
  overclaim with the precise rule — required positions (value bindings +
  declaration names + impl method definitions) vs the exempt member-name
  positions (field / tag / protocol signature; backtick optional).
- examples/0158-types-reserved-name-member-exempt.sx: pins the exempt behavior —
  bare reserved-name struct fields + union tag read & written bare AND via
  backtick, and a protocol with a bare reserved-name method dispatched through
  the protocol (impl definition takes the backtick).
- issues/0089: document the member-name exemption in the RESOLVED banner + add
  0158 to the regression list.

Gate: zig build, zig build test, bash tests/run_examples.sh — all green
(430 passed, 0 failed, 0 timed out).
This commit is contained in:
agra
2026-06-04 22:17:53 +03:00
parent 724a919fc1
commit d14e29be02
7 changed files with 118 additions and 16 deletions

View File

@@ -17,14 +17,26 @@ Line comments start with `//` and extend to end of line.
A spelling that names a builtin type — the arbitrary-width integers `s1`..`s64` /
`u1`..`u64`, plus `bool`, `string`, `void`, `f32`, `f64`, `usize`, `isize`, `Any`
is reserved. A bare reserved spelling is rejected at **every binding site**
anywhere handwritten sx introduces a name: a value binding (`:=` / typed local /
parameter), a `::` **constant** or **function** declaration, and a `::` **type**
declaration (`struct` / `enum` / `union` / `error` / type alias / `protocol` /
foreign class / ufcs alias / namespaced import). A value-spelled-as-type parses as
a *type*, not a value, so its address-of / autoref paths would mis-lower; a
type/const/function name spelled as a builtin would shadow the builtin. The only
exemptions are the backtick escape (below) and `#import c` foreign decls.
is reserved. A bare reserved spelling is rejected at **value-binding and
declaration-name sites**: a value binding (`:=` / typed local / parameter), a
`::` **constant** or **function** declaration, an `impl` method **definition**,
and a `::` **type** declaration (`struct` / `enum` / `union` / `error` / type
alias / `protocol` / foreign class / ufcs alias / namespaced import). A
value-spelled-as-type parses as a *type*, not a value, so its address-of /
autoref paths would mis-lower; a type / const / function / method name spelled as
a builtin would shadow the builtin. The exemptions are the backtick escape
(below), `#import c` foreign decls, and **member-name positions** (next) — it is
**not** rejected at every place a name appears.
**Member-name positions are exempt.** A struct **field** name, a union **tag**
name, and a protocol **method-signature** name may be a bare reserved spelling.
These sit in a member slot (`name: T` / `name :: (…)`) and are reached only via
`obj.name` (or dispatched by string), so they are never type-classified and never
mis-lower. The backtick form is optional there and names the same member — `obj.s2`
and `` obj.`s2 `` both resolve. The exemption covers member *signatures* only: an
`impl` method **definition** is a real function (a declaration site, not a member
slot), so a reserved-spelled impl method still needs the backtick
(`` `s2 :: (self) ``), exactly like a free function. See `examples/0158`.
```sx
s2 := 2.5; // ERROR: 's2' is a reserved type name and cannot be used as an identifier
@@ -91,6 +103,12 @@ for xs: (`bool, `u16) { } // for capture + index
x catch `s2 { } // catch tag binding
```
In the **member-name positions** among these — struct field, union tag, and
protocol method signature — the backtick is *optional*: the bare reserved
spelling is already legal there (see "Member-name positions are exempt" above).
Everywhere else (value bindings and declaration names, including an `impl` method
definition) the backtick is *required* to spell a reserved name.
A reserved-spelled **function** is bare-callable: `` `s2 :: (n: s64) -> s64 { … } ``
can be invoked as `s2(10)` (the bare callee spelling parses as a type but resolves
to the function when one of that name is in scope; `TypeName(val)` is not a cast).