lang: rename signed integer types sN -> iN
Surface rename of the signed integer family: s1..s64 become i1..i64
(u1..u64, usize, isize unchanged). 'string' keeps the s-prefix arm in
name classification; width parsing moves to the i-prefix arm next to
isize.
Internal TypeId tags follow the surface (.s8/.s16/.s32/.s64 ->
.i8/.i16/.i32/.i64), as do mono-key mangle fragments (ptr_i64,
tu_i64_bool) and all display/diagnostic formatting (i{d}).
Migrated in the same sweep: stdlib + examples + issue repros + FFI C
companions (shared symbol names like ffi_id_i64), expected
stdout/stderr/ir snapshots, specs.md, readme.md, CLAUDE.md/AGENTS.md,
implementation_plan.md, docs/, issue writeups. Vendored stb_image and
historical flow state left untouched.
zig build test: 426/426; examples suite: 595/595.
This commit is contained in:
@@ -46,9 +46,9 @@
|
||||
> `Param.name_span`.
|
||||
>
|
||||
> **Regression tests:**
|
||||
> - `examples/0125-types-type-named-var-rejected.sx` — `:=` form (`s2`) rejected.
|
||||
> - `examples/0125-types-type-named-var-rejected.sx` — `:=` form (`i2`) rejected.
|
||||
> - `examples/1119-diagnostics-reserved-type-name-as-identifier.sx` — parameter
|
||||
> (`u8`), typed-local (`s64`, `bool`), and `:=` (`string`) forms rejected.
|
||||
> (`u8`), typed-local (`i64`, `bool`), and `:=` (`string`) forms rejected.
|
||||
> - `examples/1121-diagnostics-reserved-name-control-flow.sx` — destructure name,
|
||||
> `if` / `while` optional bindings, `for` capture + index names, match-arm
|
||||
> capture.
|
||||
@@ -65,12 +65,12 @@
|
||||
> streaming with non-reserved names (`hasher`, `ctx`) accumulates correctly via
|
||||
> both `update(@h, …)` and `h.update(…)`.
|
||||
>
|
||||
> Pre-existing example `examples/0904-...` declared locals `s1`/`s2` (incidental
|
||||
> Pre-existing example `examples/0904-...` declared locals `i1`/`i2` (incidental
|
||||
> names); renamed to `filled`/`empty`.
|
||||
>
|
||||
> **Coverage extension (issue 0077).** The first landing scoped the binding
|
||||
> check to main-file decls (matching the unknown-type check's trusted-imports
|
||||
> convention); an imported module could still declare `s2 := …` and hit the
|
||||
> convention); an imported module could still declare `i2 := …` and hit the
|
||||
> original LLVM verifier abort. The reserved-name binding diagnostic now runs
|
||||
> over EVERY compiled module — imported user modules (descending the
|
||||
> `namespace_decl` an `mod :: #import` wraps) AND the stdlib `library/` — and
|
||||
@@ -81,11 +81,11 @@
|
||||
|
||||
## Symptom (how it first surfaced)
|
||||
|
||||
A local variable whose name is lexically a type — e.g. `s2` (the `sN`
|
||||
arbitrary-width signed-int syntax: `Type.fromName("s2")` → `s(2)`), or `u8`,
|
||||
`s64`, etc. — is accepted as a variable. Because such a name parses as a
|
||||
A local variable whose name is lexically a type — e.g. `i2` (the `sN`
|
||||
arbitrary-width signed-int syntax: `Type.fromName("i2")` → `s(2)`), or `u8`,
|
||||
`i64`, etc. — is accepted as a variable. Because such a name parses as a
|
||||
`.type_expr` (not `.identifier`), the address-of family of lowering sites
|
||||
(`@s2`, the autoref `s2.update(...)` receiver, a bare `f(s2)` at a `*T` param,
|
||||
(`@i2`, the autoref `i2.update(...)` receiver, a bare `f(i2)` at a `*T` param,
|
||||
global function-pointer args) does NOT recognize it as a scoped local and falls
|
||||
through to value lowering — loading the whole aggregate and passing it **by
|
||||
value** to a `ptr` parameter:
|
||||
@@ -104,7 +104,7 @@ any of this — the `.identifier` paths already work correctly.
|
||||
|
||||
The language is **accepting reserved/builtin type names as identifiers** in the
|
||||
first place. `sN`/`uN` (arbitrary-width ints) and the named builtins
|
||||
(`bool`, `string`, `void`, `f32`, `f64`, `s8`/`s16`/`s32`/`s64`,
|
||||
(`bool`, `string`, `void`, `f32`, `f64`, `i8`/`i16`/`i32`/`i64`,
|
||||
`u8`/`u16`/`u32`/`u64`, …) are reserved type names; declaring a variable with
|
||||
such a name is meaningless and produces the mis-lowering above. Patching each
|
||||
address-of site to tolerate the name (the rejected `bareVarName` approach) is
|
||||
@@ -135,14 +135,14 @@ type-shaped name can reach them).
|
||||
|
||||
```sx
|
||||
#import "modules/std.sx";
|
||||
Sha256 :: struct { h:[8]u64; block:[64]u8; block_len:s64=0; total_len:u64=0; }
|
||||
Sha256 :: struct { h:[8]u64; block:[64]u8; block_len:i64=0; total_len:u64=0; }
|
||||
init :: () -> Sha256 { s:Sha256=---; s.block_len=0; s.total_len=0; s }
|
||||
update :: (self:*Sha256, data:string) { self.total_len += data.len; }
|
||||
main :: () -> s32 { s2 := init(); update(@s2, "."); print("total_len={}\n", s2.total_len); return 0; }
|
||||
main :: () -> i32 { i2 := init(); update(@i2, "."); print("total_len={}\n", i2.total_len); return 0; }
|
||||
```
|
||||
|
||||
`./zig-out/bin/sx run <file>` today → LLVM verifier abort.
|
||||
**Expected after fix:** a clean compile-time diagnostic that `s2` is a reserved
|
||||
**Expected after fix:** a clean compile-time diagnostic that `i2` is a reserved
|
||||
type name and cannot be an identifier (exit non-zero, readable error — NOT an
|
||||
LLVM abort, NOT a silent copy). The same program with a non-reserved name
|
||||
(`hasher := init(); update(@hasher, ".")`) must compile and print `total_len=1`.
|
||||
@@ -150,7 +150,7 @@ LLVM abort, NOT a silent copy). The same program with a non-reserved name
|
||||
## Verification
|
||||
|
||||
1. Pinned diagnostics test(s) asserting the error for representative reserved
|
||||
names used as identifiers: `s2`, `u8`, `s64`, `bool`, `string` (declaration
|
||||
names used as identifiers: `i2`, `u8`, `i64`, `bool`, `string` (declaration
|
||||
forms: `:=`, typed local, and a parameter name). Capture the diagnostic text
|
||||
in `expected/`.
|
||||
2. A positive test: the same `*self` streaming pattern with NON-reserved names
|
||||
@@ -165,6 +165,6 @@ LLVM abort, NOT a silent copy). The same program with a non-reserved name
|
||||
## Provenance
|
||||
|
||||
Discovered by the `distribution` flow (P1.2 pure-sx SHA-256), whose minimal repro
|
||||
happened to name a local `s2`. Real SHA-256 code with names like `hasher`/`ctx`
|
||||
happened to name a local `i2`. Real SHA-256 code with names like `hasher`/`ctx`
|
||||
is unaffected on the current compiler — so the P1.2 "blocker" was a
|
||||
naming artifact, and this issue is really a missing-diagnostic correctness bug.
|
||||
|
||||
Reference in New Issue
Block a user