Repository navigation
Closed
Labels
P1NextNextcompilerParser, IR, CASParser, IR, CASenhancementNew feature or requestNew feature or request
Description
@validators = [StringBounds(...)] on an s32 field builds without error today. The design note says applying a validator to a type it doesn't fit should be a build error at that field, but nothing checks it.
Proposal
A validator declares the type(s) it applies to:
validator StringBounds for string {
...
}
comline buildrejects a validator applied to a different type, at the field (or alias, Validators on type aliases #99) that applies it: "StringBoundsapplies tostring, nots32".value.*paths are type-checked once, at the declaration, instead of separately at every use.- The editor can offer only the validators that fit a field's type.
- Resolution: aliases resolve to their target first; an
optional Tfield checks againstT. - Arrays: a validator applies to exactly the declared type.
StringBoundson astring[]field is an error, not "check each element". To check each element, put the validator on an alias of the element type and useName[](Validators on type aliases #99). - A list of targets (
for string, T[]) can come later if a validator really fits several kinds of type. - A target written explicitly is preferred over inferring it from the accessors used. Inference would accept
StringBoundson arrays too (both have alength), where its "characters" messages are wrong.
Decided (2026-10-18)
foris required. A validator without it is a build error (validation::validator-missing-target) with a fix-it hint. There's no deprecation period; the grammar keepsforoptional only so the error can be specific.- Several targets as a list:
validator Range for u8, u16, u32, s32, s64. No type categories (integer,array) and no generics for now. "Any array" is left to bounds on types (Bounds written on types: T[a..b], string[..n] #98). - Targets are primitives, arrays of them, and aliases (resolved to the type they stand for). Struct targets (checks across fields via
value.<field>) come later. - Matching is exact after resolving aliases and stripping
optional:u8doesn't matchu32. - Numbers compare by mathematical value in
validateconditions (e.g. au8value against ans64parameter). Generators emit lossless comparisons (widen or check the conversion), never a narrowing cast. Implemented with Run validators in generated code: TypeScript and cross-schema validators (phase 4d) #96. - Imported validators are checked too, not skipped as they are today (
maybe_imported).std::validators::StringBoundsis the main case. Resolution goes through a lookup the caller supplies (likesize.rs'sSizeLookup): overProjectContextin the build, over the project in the language server.
value.length
Define it in core: for string, the number of Unicode scalar values; for arrays, the number of elements. Generators follow this definition (#96).
Tasks
- Grammar: optional
for TYPEonvalidator - Freeze the target on
FrozenUnit::Validator - Check at every application site, and check
value.*against the target - Error on a validator with no
for; migratestd::validators::StringBoundstofor string - Check imported validators through a caller-supplied lookup (build:
ProjectContext; LSP: project) - Update
guide/idl/validator.mdanddesign/validators.md
Metadata
Metadata
Assignees
Labels
P1NextNextcompilerParser, IR, CASParser, IR, CASenhancementNew feature or requestNew feature or request
Activity
Kinflou commentedon Oct 18, 2026
Done in core#105:
validator X for T[, T]*, required. Mismatched fields, a missingfor, andvalueaccessors a target doesn't have are build errors. Imported validators and aliases are checked throughImportLookup:ProjectImportsin the build, and the project lookup in the language server (language-server#61). Docs: docs#35. Numbers comparing by value is recorded indesign/validators.mdand gets implemented with #96.