fix: resolve module-alias-qualified type in reflection arg slot (issue 0147)
size_of(sel.Selection) and the other reflection builtins rejected a module-alias-qualified type: in argument position it parses as a .field_access expression (not the dotted .type_expr a declaration produces), and neither isStaticTypeArg nor resolveTypeArg had a .field_access arm. Add both: a pure namespace-decl scan in isStaticTypeArg, and resolution via namespaceAliasTarget + resolveNominalLeaf in the target module context in resolveTypeArg (mirroring the value-position lowerFieldAccess path). No fabricated-stub fallback. Regression: examples/0192-types-size-of-qualified-alias.sx
This commit is contained in:
68
issues/0147-size-of-qualified-aliased-type-unresolved.md
Normal file
68
issues/0147-size-of-qualified-aliased-type-unresolved.md
Normal file
@@ -0,0 +1,68 @@
|
||||
# 0147 — `size_of(alias.Type)` on a module-aliased type fails: "expects a type, got 'unresolved'"
|
||||
|
||||
> **RESOLVED.** In a reflection-builtin argument slot, a module-alias-qualified
|
||||
> type (`sel.Selection`) parses as a `.field_access` expression (not the dotted
|
||||
> `.type_expr` a declaration annotation produces), and neither `isStaticTypeArg`
|
||||
> nor `resolveTypeArg` (src/ir/lower/generic.zig) had a `.field_access` arm — so
|
||||
> the reflection guard rejected it as a non-type. Both now handle the qualified
|
||||
> form: `isStaticTypeArg` recognizes `alias.Type` when `alias` is a namespace
|
||||
> alias whose target authors a type named `Type` (pure decl scan), and
|
||||
> `resolveTypeArg` resolves it via `namespaceAliasTarget` + `resolveNominalLeaf`
|
||||
> in the target module's context (the same mechanism `lowerFieldAccess` uses for
|
||||
> `alias.Type` in value position). Regression test:
|
||||
> `examples/0192-types-size-of-qualified-alias.sx`.
|
||||
|
||||
## Summary
|
||||
`size_of(T)` does not resolve a type referenced through a module ALIAS
|
||||
(`alias :: #import "..."`), even though that same alias resolves fine everywhere
|
||||
else (declarations, casts, struct-literal construction). The compiler reports the
|
||||
qualified type as `unresolved` only inside `size_of`.
|
||||
|
||||
## Repro
|
||||
```sx
|
||||
sel :: #import "doc/selection.sx"; // selection.sx exports `Selection`
|
||||
|
||||
box :: () -> *sel.Selection {
|
||||
// both of these fail:
|
||||
p : *sel.Selection = xx context.allocator.alloc_bytes(size_of(sel.Selection));
|
||||
memset(xx p, 0, size_of(sel.Selection));
|
||||
p
|
||||
}
|
||||
```
|
||||
|
||||
Error:
|
||||
```
|
||||
error: size_of expects a type, got 'unresolved'
|
||||
|
|
||||
| ... alloc_bytes(size_of(sel.Selection));
|
||||
| ^^^^^^^^^^^^^
|
||||
```
|
||||
|
||||
Note the SAME `sel.Selection` resolves correctly in the variable declaration
|
||||
`p : *sel.Selection` and in calls like `sel.selection_create(...)` — only the
|
||||
`size_of(...)` argument position treats the qualified name as unresolved.
|
||||
|
||||
## Expected
|
||||
`size_of(sel.Selection)` resolves the aliased type and yields its size, exactly
|
||||
as `size_of(Selection)` does for an unqualified/flat-imported type.
|
||||
|
||||
## Workaround (clean)
|
||||
Introduce an unqualified local type alias and feed THAT to `size_of`:
|
||||
```sx
|
||||
sel :: #import "doc/selection.sx";
|
||||
Selection :: sel.Selection; // unqualified alias
|
||||
|
||||
box :: () -> *Selection {
|
||||
p : *Selection = xx context.allocator.alloc_bytes(size_of(Selection));
|
||||
memset(xx p, 0, size_of(Selection));
|
||||
p
|
||||
}
|
||||
```
|
||||
`size_of(Selection)` (the unqualified alias) resolves fine. Used in
|
||||
photo `tests/toolbar.sx`'s `box_sel` (the selection model is imported qualified
|
||||
as `sel` there to avoid a `Point` collision with `modules/ui/types.sx`).
|
||||
|
||||
## Impact
|
||||
Minor. Only bites when a type must be reached through a module alias AND its size
|
||||
is needed (heap-boxing a zeroed value of that type). The unqualified-alias
|
||||
workaround is a one-liner and reads clearly.
|
||||
Reference in New Issue
Block a user