E0122: nominal_mismatch
E0122 nominal_mismatch — two nominal types mixed (cell type Lots = Int with Cents), or a plain value where a nominal one is declared.
A compile-time error of soma check, the checker of the Soma programming language (soma explain E0122).
The rule
Two nominal types (cell type Lots = Int, cell type Cents = Int) never mix: adding, comparing or passing one where the other is declared is refused, and so is a plain Int variable where a Lots is declared. Here a cap in cents is applied to a position in lots; with plain Int everywhere, soma check passes and soma verify even proves the bound, on the wrong quantity. Declare the cap in what it counts (const MAX_LOTS = Lots(50)), or write the conversion (Cents(to_int(lots) * to_int(price))); a literal (lots <= 50, ?? 0) takes the type of the other side. The type is erased after soma check: at run time, in storage and in JSON a Lots is an Int, and soma verify proves the same things.
A program that triggers it
wrong.cell
cell type Lots = Int
cell type Cents = Int
cell Risk {
const MAX_EXPOSURE = Cents(5000000)
memory {
position: Map<String, Lots> [persistent]
}
on order(sym: String, lots: Lots) {
let held = position.get(sym) ?? 0
require held + lots <= MAX_EXPOSURE else OverCap
position.set(sym, held + lots)
return held + lots
}
}What soma check prints:
$ soma check wrong.cell
error: `held + lots <= Cents(5000000)` compares Lots with Cents — two nominal types never compare: if both sides count Lots, declare the Cents side as Lots (`Lots(…)`, `const … = Lots(…)`); if a conversion is meant, write it (`to_int(held + lots)`, `to_int(Cents(5000000))`)
--> wrong.cell:11:17
|
11 | require held + lots <= MAX_EXPOSURE else OverCap
| ^
= code: E0122
✗ 1 error(s), 0 warning(s).The fix field of soma check --json: two nominal types never compare: if both sides count Lots, declare the Cents side as Lots (`Lots(…)`, `const … = Lots(…)`); if a conversion is meant, write it (`to_int(held + lots)`, `to_int(Cents(5000000))`)
The fix
On line 5, const MAX_EXPOSURE = Cents(5000000) becomes const MAX_LOTS = Lots(50); on line 11, require held + lots <= MAX_EXPOSURE else OverCap becomes require held + lots <= MAX_LOTS else OverCap.
wrong.cell → right.cell
--- wrong.cell
+++ right.cell
@@ -3,5 +3,5 @@
cell Risk {
- const MAX_EXPOSURE = Cents(5000000)
+ const MAX_LOTS = Lots(50)
memory {
position: Map<String, Lots> [persistent]
@@ -9,5 +9,5 @@
on order(sym: String, lots: Lots) {
let held = position.get(sym) ?? 0
- require held + lots <= MAX_EXPOSURE else OverCap
+ require held + lots <= MAX_LOTS else OverCap
position.set(sym, held + lots)
return held + lotsWith the fix, soma check accepts the program:
$ soma check right.cell
✓ All checks passed.