Skip to main content
v0.14.0

record declarations are not implemented

Limitation​

The grammar has no record keyword. decl's alternatives accept struct, enum, aspect, extend, fun and type, but not record — writing record Handle { fd: i64 } is a parse error today, not a declaration of a structurally-visible nominal type. Reproduced against current develop:

record Handle { fd: i64 }
[P0001] parse error: expected a declaration (`struct`, `enum`, `aspect`, `extend`,
`fun`, or `type`), found `record`

The Language Spec specifies named records (spec.declarations.records.*), so this is an implementation shortfall against the spec, not a spec gap.

Impact​

Visible to Metel programmers: there is no way to declare a nominal type whose row is structurally visible to row bounds or row-conditional impl resolution — every struct's row stays private to structural matching (RFC-0137 §3), with no opt-in to publish it. Row-conditional impl resolution itself is additionally gated on RFC-0121 (Open Rows), not implemented either (see LIMIT-TYPES-* once RFC-0121 integrates).

Affects​

Resolution​

Implemented 2026-10-01, tracked by metel-core#1300, landed in metel-core#1303 (merge commit 3797758d6dc2fa068939f9ca8877c144555fe2cc). metel-frontend/src/ grammar.pest gained a record_decl production (decl's alternatives now include record_decl); Decl::Struct carries a StructKind::{Struct, Record} discriminant, and the parser rejects a non-public field inside a record as P0001. A new TypeDefinitionRegistry::record_structs: HashSet<SymbolId> tracks which struct ids were declared record, and visible_type_kind resolves VisibleTypeKind::Record for them (by brand name, uniformly for Type::Named and Type::Residual, per RFC-0137 §3) — a record's row is now structurally visible to row bounds exactly as this record's "Impact" section described it should be. Row-conditional impl resolution is implemented by RFC-0121. Verified directly: record Handle { fd: i64 } parses and typechecks (a record's fields are public by construction), a public written on a record field is rejected as P0001, and a function generic over <record T: { fd: i64, .. }> accepts Handle and its narrowed residuals but rejects an equivalent struct. This record's exemptions on the four affected rules below are removed now that real fixtures cover them (metel-interpreter/tests/integration/sources/evaluator/structs/112-114_*, parsing/negative_record_private_field_is_parse_error).