Strict by default
UpdatedEvery .aly file checks in Luau strict mode unless the project says otherwise. alloy init writes one Luau configuration with languageMode = "strict", and the language server gives a workspace with neither file the same setting. A --!nonstrict or --!nocheck line at the top of a file still wins for that file.
On top of the checker, the compiler holds these at compile time:
alloy lint adds the nil discipline and, under [lint] strict = true, which is on unless the project turns it off, the no-implicit-any rules (alloy doc lints).
Exhaustive match
A match with no default covers every variant. The error names the one with no arm.
match msg with case Join(p) then greet(p) case Chat(p, t) then say(p, t) end -- `Msg` has no arm for `Leave`; add it or a `default` arm
Struct construction
The fields form sets every field without a default and names no field the struct lacks.
struct P x: number y: number = 0 end local a = new P { y = 1 } -- `new P { ... }` leaves `x` unset
Trait contract
An impl writes every method the trait declares without a body, with the trait's arity.
trait Shape function area(self): number end impl Shape for Sq end -- `impl Shape for Sq` does not write `area`
Sealed structs
A struct is open: a typo in a field name makes a new key in silence. @sealed makes it an error, at runtime and at check time. A `read` field is the one that cannot be written.
@sealed struct Config volume: number end local c = new Config { volume = 1 } c.volume = 2 -- fine: declared c.volme = 2 -- error: Config has no field volme
Wire types
A remote carries data. A function, a thread, a Future, or a Signal in a parameter is an error.
remote Ping(cb: () -> ()) from client -- parameter `cb` has type `() -> ()`, which is a -- function type; a remote carries only data
