Generic compile time assertions

Hello,

I was wondering if one could define a generic macro that can be used as a shorthand for doing some compile time checks. However, the following doesn’t seem to work:

alias T = Int32#|Bool

macro static_assert(invariant)
    {% raise("static_assert") if !invariant %}
end

static_assert(T.union_types.includes?(Bool)) # doesn't work

{% raise("static_assert") if !T.union_types.includes?(Bool) %} # works, i.e. raises compile time error (if Bool isn't part of T)

Is there a better way for static_assert?

Thanks!

1 Like

Yes! Like this:

alias T = Int32 # |Bool

macro static_assert(invariant)
  \{% raise("static_assert") unless {{invariant}} %}
end

static_assert(T.union_types.includes?(Bool)) # doesn't work

The idea:

  • Use \{% which will actually not enter into a macro expression. Instead, the output of the macro will be {% ... %} which is itself a macro
  • Given that we aren’t in a macro expression, we can interpolate the invariant with {{invariant}}

You can also put {% debug %} at the very end of the macro, and you’ll see this is the output:

{% raise("static_assert") unless T.union_types.includes?(Bool) %}

That’s what the macro is generating.

7 Likes

I think this is something that would be nice to have in stdlib, even being so simple to implement.