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:
@@ -1,6 +1,27 @@
|
||||
# 0189 — non-type expression in type position silently fabricates an empty struct
|
||||
|
||||
**Status:** OPEN
|
||||
**Status:** RESOLVED
|
||||
|
||||
> **RESOLVED.** Root cause: two distinct type-resolution paths silently
|
||||
> fabricated a zero-field `{}` struct for a non-type AST node used in type
|
||||
> position — (1) a dotted `type_expr` / field-access (`g.a`, `g` a runtime
|
||||
> value) whose prefix is not a namespace alias, and (2) an `error_type_expr`
|
||||
> (`!Name`) whose `Name` is not a declared error set (an undeclared name or a
|
||||
> value). Both reached codegen as a real empty struct with no diagnostic.
|
||||
>
|
||||
> Fix: (1) the dotted-name guard in `resolveTypeWithBindings`
|
||||
> (`src/ir/lower.zig` ~1071–1093) rejects a value field-access in type position
|
||||
> ("expected a type, found a value '<name>' in type position"); (2) a new
|
||||
> `.error_type_expr` arm in `checkTypeNodeForUnknown`
|
||||
> (`src/ir/semantic_diagnostics.zig`) validates a named `!E` against a
|
||||
> collected set of declared error-set names — "unknown error set '<name>'" for
|
||||
> an undeclared/value name, "expected an error set after '!', found type
|
||||
> '<name>'" for a declared non-error-set type. A bare `!` (void channel) and a
|
||||
> declared `!E` in return position stay valid.
|
||||
>
|
||||
> Regression test: `examples/diagnostics/1195-diagnostics-non-type-in-type-position.sx`
|
||||
> (covers both the `g.a`/`Tuple(i32, g.a)` field-access path and the
|
||||
> `!Nonexistent` / nested-tuple / nested-closure error-set path).
|
||||
|
||||
## Symptom
|
||||
|
||||
|
||||
Reference in New Issue
Block a user