fix: reject non-type expression in type position instead of fabricating {} (issue 0189)
Two type-resolution paths silently resolved a non-type AST node in type
position to a zero-field `{}` struct that reached codegen with no
diagnostic:
- a dotted `type_expr` / field-access (`g.a`, `g` a runtime value) whose
prefix is not a namespace alias
- an `error_type_expr` (`!Name`) whose `Name` is not a declared error set
Now both reject loudly:
- `resolveTypeWithBindings` (lower.zig): "expected a type, found a value
'<name>' in type position" + `.unresolved`
- `checkTypeNodeForUnknown` (semantic_diagnostics.zig): validates a named
`!E` against the declared error-set names — "unknown error set
'<name>'" / "expected an error set after '!', found type '<name>'".
A bare `!` (void channel) and a declared `!E` in return position stay
valid; namespace-qualified types (`pkg.Type`) are unaffected.
Regression: examples/diagnostics/1195-diagnostics-non-type-in-type-position.
This commit is contained in:
@@ -0,0 +1,35 @@
|
||||
// Regression (issue 0189): a non-type expression used in TYPE position must be
|
||||
// rejected with a clear diagnostic — never silently resolved to a fabricated
|
||||
// zero-field empty struct `{}` that ships to codegen as a real type.
|
||||
//
|
||||
// Two fabrication paths are covered:
|
||||
//
|
||||
// 1. A dotted `type_expr` / field-access (`g.a`, `g` a runtime VALUE, `a` a
|
||||
// field) in type position — both the bare annotation `x : g.a = ---;` and
|
||||
// the `Tuple(i32, g.a)` element form hit the same `resolveTypeWithBindings`
|
||||
// dotted-name guard. A dotted name whose prefix is not a namespace alias is
|
||||
// a value field access, not a qualified `pkg.Type` path → "expected a type,
|
||||
// found a value".
|
||||
//
|
||||
// 2. A named `!E` (error-set type) whose `E` is not a declared error set —
|
||||
// an undeclared name or a value name after `!` silently fabricated a `{}`
|
||||
// stub via `resolveErrorType` -> `resolveNominalLeaf`. The
|
||||
// `error_type_expr` arm of `checkTypeNodeForUnknown` now validates it →
|
||||
// "unknown error set" (undeclared / value) or "expected an error set"
|
||||
// (a declared non-error-set type).
|
||||
//
|
||||
// A bare `!` (the void failable channel) and a DECLARED `!E` in return position
|
||||
// stay valid — exercised in examples/errors and not flagged here.
|
||||
#import "modules/std.sx";
|
||||
|
||||
S :: struct { a: i32; }
|
||||
g : S = .{ a = 1 };
|
||||
|
||||
main :: () -> i32 {
|
||||
x : g.a = ---; // field-access value in type position
|
||||
y : Tuple(i32, g.a) = ---; // same, as a tuple element
|
||||
z : !Nonexistent = ---; // `!` of an undeclared name
|
||||
w : Tuple(i32, !Nonexistent) = ---; // nested in a tuple
|
||||
v : Closure(!Nonexistent) -> i32 = ---; // nested in a closure param
|
||||
0
|
||||
}
|
||||
@@ -0,0 +1 @@
|
||||
1
|
||||
@@ -0,0 +1,29 @@
|
||||
error: unknown error set 'Nonexistent'
|
||||
--> examples/diagnostics/1195-diagnostics-non-type-in-type-position.sx:31:9
|
||||
|
|
||||
31 | z : !Nonexistent = ---; // `!` of an undeclared name
|
||||
| ^^^^^^^^^^^^
|
||||
|
||||
error: unknown error set 'Nonexistent'
|
||||
--> examples/diagnostics/1195-diagnostics-non-type-in-type-position.sx:32:20
|
||||
|
|
||||
32 | w : Tuple(i32, !Nonexistent) = ---; // nested in a tuple
|
||||
| ^^^^^^^^^^^^
|
||||
|
||||
error: unknown error set 'Nonexistent'
|
||||
--> examples/diagnostics/1195-diagnostics-non-type-in-type-position.sx:33:17
|
||||
|
|
||||
33 | v : Closure(!Nonexistent) -> i32 = ---; // nested in a closure param
|
||||
| ^^^^^^^^^^^^
|
||||
|
||||
error: expected a type, found a value 'g.a' in type position
|
||||
--> examples/diagnostics/1195-diagnostics-non-type-in-type-position.sx:29:9
|
||||
|
|
||||
29 | x : g.a = ---; // field-access value in type position
|
||||
| ^^^
|
||||
|
||||
error: expected a type, found a value 'g.a' in type position
|
||||
--> examples/diagnostics/1195-diagnostics-non-type-in-type-position.sx:30:20
|
||||
|
|
||||
30 | y : Tuple(i32, g.a) = ---; // same, as a tuple element
|
||||
| ^^^
|
||||
@@ -0,0 +1 @@
|
||||
|
||||
Reference in New Issue
Block a user