Per Hare convention, `nomem` is a language-level error type — no
import required, in scope alongside void/done/rune/str. ref/hare uses
it bare at errors/string.ha:14, types/c/strings.ha:89, net/uri/parse.ha:17
with no `use`. Precondition for graduating the `alloc` builtin to
`(*T | nomem)` returns.
cstage: ty_nomem is NAMED{under=ty_void, iserror=1}, installed by
typesinit and surfaced via lookup_builtin. wwstage seeds the same
shape in both check.ww (scope) and cgen.ww (aliases) — separate
tables, both consulted; without the cgen seed wwstage drops the
zero-init for `let e: nomem;` locals and breaks byte-identity.
Tests: tagged_ptr_ret.ww and trypromote.ww drop their local
`type nomem = !void;` aliases. 990_selfhost.c adds a regression that
a value named `nomem` does not collide with the predeclared type.
56 lines
1.5 KiB
Plaintext
56 lines
1.5 KiB
Plaintext
// selfhost/test/trypromote.ww — smoke for `?` propagation through a
|
|
// `!void`-shaped alias.
|
|
//
|
|
// Task #2 (ww-strings-redesign): proves cgen's TRYPROP tag-remap works
|
|
// for the exact pattern lib/errors + os.alloc are about to lean on. We
|
|
// cannot smoke this against lib/ today because there are zero lib-side
|
|
// `?` users on a `!void` alias yet. Mirrors the shlex.syntaxerr shape
|
|
// (lib/shlex/shlex.ww:112) for the "nomem" stub.
|
|
//
|
|
// Not table-driven on purpose: same-shape `?` is a single cgen emit
|
|
// pattern, so varying the operand exercises the same asm. The two
|
|
// match arms below cover both runtime outcomes (success unwrap, error
|
|
// propagation); asm-level regressions of task #18 are gated by the
|
|
// byte-identity tests (994_w6c_ww, 995_self_rebuild).
|
|
|
|
package test;
|
|
|
|
import fmt;
|
|
|
|
// #29: `nomem` is predeclared in the universe scope — no local
|
|
// `type nomem = !void;` (or `import errors;`) needed.
|
|
|
|
fn stub(fail: i64) (i64 | nomem) = {
|
|
if (fail != 0i64) { let e: nomem; return e; };
|
|
return 42i64;
|
|
};
|
|
|
|
fn caller(fail: i64) (i64 | nomem) = {
|
|
let v = stub(fail)?;
|
|
return v + 1i64;
|
|
};
|
|
|
|
export fn main() i32 = {
|
|
let rc: i32 = 0;
|
|
match (caller(0i64)) {
|
|
case let n: i64 => {
|
|
fmt.println("ok ", n);
|
|
if (n != 43i64) { rc = 1; };
|
|
};
|
|
case nomem => {
|
|
fmt.println("unexpected nomem on ok path");
|
|
rc = 2;
|
|
};
|
|
};
|
|
match (caller(1i64)) {
|
|
case let n: i64 => {
|
|
fmt.println("unexpected ", n, " on err path");
|
|
rc = 3;
|
|
};
|
|
case nomem => {
|
|
fmt.println("nomem as expected");
|
|
};
|
|
};
|
|
return rc;
|
|
};
|