docs / Miri for Agents / Traps & Differences

Traps & Differences

These are the mistakes that cost agents the most in our trials. They are in the miri-lang pack, and are worth a read before you review Miri code an agent wrote.

Where Miri differs

  • Bindings are let (immutable) and var (mutable); there is no let mut. Parameters are immutable too; mutate a collection argument with .set(i, v).
  • Types follow the name with a space: let x int = 5, fn f(a int) int. No : before a type, no ->, no literal suffixes (42i32); cast with as.
  • Logic is and, or, not. Nullable is T? with bare Some/None; Result patterns need the prefix: Result.Ok(v), Result.Err.
  • List([1, 2]) builds from a literal, List<int>() is empty, Map<K, V>() and Set<T>() likewise. [1, 2, 3] alone is a fixed Array; {} is a Map.
  • A for over a Map walks its keys; there is no .keys().
  • An f-string is the only int → String conversion: f"{n}", never n.to_string() or "n=" + n.
  • main() int returns an exit status; panic(message) stops with status 1. There is no exit.
  • Stdlib modules are imported by name (use system.collections.list).

Traps

  • Quotes inside f-string braces must be the other quote character: f"{m['a']}". The same quote ends the string (MER_LEX_012).
  • Positions count characters, in length(), substring, element_at, code_at and regex matches alike; only size() counts bytes. A substring range outside the text stops the program (or fails to compile, if constant).
  • Integer overflow stops the program (MER_RT_003) instead of wrapping. Where wrapping is meant — a hash, a checksum — write wrapping_add, wrapping_sub or wrapping_mul from system.math.
  • Walk with for, not by position. for ch in s and for k in m are one pass; indexing a String, Map or Set by a counter repeats lookups.
  • Every statement lives in a function. A statement beside main never runs and is refused (MER_TYP_069); put the script’s body inside main.
  • Integer widths do not convert implicitly. An int value stored into an i32/u32 slot, element or field needs as i32; the same holds between float and f32. miri fix --apply writes the cast.
  • Format specs follow Python: f"{x:.2f}", f"{n:>8}", f"{n:08x}". A precision needs f ({x:.2} is refused); x/b/o take integers only.
  • Imports are explicit. A name from another module needs its use line; miri fix main.mi --apply --yes adds one that resolves in exactly one module.