Why this fires¶
Dimensional units declare a physical base, a positive exact scale from another unit, or a dimension formula. They require an exact integer, decimal, BigInt or BigDecimal scalar and their actual checked constructor.
@unit("m", base: true) newtype Meters(decimal)
@unit("km", of: Meters, scale: 1000d) newtype Kilometers(decimal)
let distance = 2km as MetersAddition, subtraction and comparison require equal physical dimensions. Multiplication and division combine or cancel dimensions; a bounded authored integer power raises the dimension. Declarations with the same spelling in different physical modules remain different bases. Authored operator methods keep their own return and effect contracts.
An exact conversion runs the destination constructor once, after representation and range checks. A known repeating value such as (1m / 3) as Meters cannot fit a decimal. Use as? when representation, range or a rejecting predicate should produce nil. Arithmetic faults, budget errors and constructor effects still propagate. Any, records, mutable marker fields and bitcasts cannot manufacture dimensional values.
Reserved duration suffixes become dimensional only with an expected temporal unit or an adjacent checked dimensional operand. Standalone 2h retains its legacy milliseconds. Temporal units must use the genuine seconds base and the builtin exact scale.
The initial wasm-aot and comptime implementations explicitly reject exact dimensional execution. JavaScript lowering rejects the checked dimensional surface; ordinary duration literals remain supported.
Contextual duration copies produced by a macro must not share one source span with different scalar values, constructor origins, or legacy/dimensional admission. These collisions are rejected with TE196 rather than reusing another copy's proof. Use explicit constructor calls such as Hours.new(1) and Hours.new(2) inside the macro when its expansion assigns one span to multiple duration tokens.