Now you’re mixing up compile time and runtime. This version of assert
is supposed to check the invariant at runtime (opposed to Generic compile time assertions).
Nevertheless, it also reduced types on compile time, as raise
does in the initial example.
Your last proposal doesn’t work for the initial example:
# doesn't compile
macro assert(invariant)
{% unless invariant %}
raise("runtime_assert")
{% end %}
end
# compiles
# macro assert(invariant)
# {% if invariant %}
# raise("runtime_assert") if !{{invariant}}
# {% else %}
# raise("runtime_assert")
# {% end %}
# end
def fn(arg : Bool|Int32)
assert(!arg.is_a?(Bool))
arg+42 # compile-time error in case of the first assert variant, assert doesn't reduce the type
end
a = [1,true]
p fn(a[0])
I’m not sure if the working version can be reduced.