The signature/field check missed body-level type positions: a local annotation naming a non-existent type flowed through the empty-struct stub untouched, so `v: Coordnate = 5` silently compiled and ran (the value dropped) — an invalid program accepted with no diagnostic. `checkUnknownTypeNames` now also walks each main-file function body (`checkBodyTypes`): local var/const type annotations — including inside if / loop / match / push / defer / onfail blocks and decl-value blocks — are validated with the enclosing function's generic params in scope, and body-local `T :: struct/enum/union` declarations are collected first (`collectBodyDeclNames`) so legitimate locals aren't false-flagged. Nested function/closure bodies are their own scope and are not descended (safe under-coverage); explicit `cast(T)` already surfaces its own `unresolved` diagnostic and is left to it. Regression: examples/1113 (local annotation of a non-existent type, exit 1).
11 lines
520 B
Plaintext
11 lines
520 B
Plaintext
// An identifier used in a LOCAL variable's type annotation that names no
|
|
// declared type is rejected, exactly like a signature or struct-field use.
|
|
// Previously a body-level annotation bypassed the check: the type resolver's
|
|
// empty-struct stub silently gave the local a 0-field type, so `v: Coordnate
|
|
// = 5` compiled and ran (the `5` dropped) with no diagnostic. Regression
|
|
// (issue 0064, body-level positions). Expected: error at the annotation; exit 1.
|
|
main :: () -> s32 {
|
|
v: Coordnate = 5;
|
|
return 0;
|
|
}
|