Stream: t-lang

Topic: static assertions?


Josh Triplett (Apr 20 2020 at 18:33, on Zulip):

Now that we have good const evaluation, what would it take to reintroduce a static assertion mechanism?

Josh Triplett (Apr 20 2020 at 18:33, on Zulip):

We have things like compile_error!, but as far as I can tell that's unconditional.

Josh Triplett (Apr 20 2020 at 18:34, on Zulip):

I'd like to be able to write this:

static_assert!(size_of::<usize>() == size_of::<u64>());
simulacrum (Apr 20 2020 at 18:51, on Zulip):

There's already a library providing this: https://docs.rs/static_assertions/1.1.0/static_assertions/ fwiw

simulacrum (Apr 20 2020 at 18:56, on Zulip):

but I'd also love to see it in std

Josh Triplett (Apr 20 2020 at 19:05, on Zulip):

Right. That would, among other things, provide much better error messages.

Josh Triplett (Apr 20 2020 at 19:06, on Zulip):

That crate uses the "constant array with negative size" trick.

Sebastian Malton (Apr 20 2020 at 19:12, on Zulip):

Which feels like a C style of solution, would it be possible to provide a minimal subset of assertions and then leave higher order items to crates?

simulacrum (Apr 20 2020 at 19:16, on Zulip):

I think any initial solution would likely be just the single static_assert macro (and maybe _eq, I guess).

ecstatic-morse (Apr 20 2020 at 19:26, on Zulip):

Stabilizing #49146 and #51999 is the path forward here. If you also guarantee that const items outside of an impl block will be evaluated, even if they are unused, static_assert is just a macro that expands to const _: () = assert!($expr);. static_assertions already depends on that last part.

Josh Triplett (Apr 20 2020 at 21:05, on Zulip):

I'm not looking for a way to clean up the const _: () trick. I'd like to have a conditional version of compile_error!, as a top-level construct.

ecstatic-morse (Apr 20 2020 at 23:01, on Zulip):

What would the difference be between the following and what you're looking for?

macro_rules! static_assert {
    ($expr:expr, $msg:lit) => { const _: () = assert!($expr, $msg); }
}

If #51999 were stabilized, we would no longer have to rely on an index out-of-bounds error, and you would get the same message at compile-time as if the assert had triggered at runtime.

ecstatic-morse (Apr 20 2020 at 23:12, on Zulip):

At that point, the output of static_assert and compile_error should be the same, except that errors from compile_error show up during macro expansion, while those from static_assert won't be shown until const-eval happens.

Josh Triplett (Apr 20 2020 at 23:14, on Zulip):

The primary difference would be that I'd like to not have the availability and timeline of static assertions depend on a mechanism to ensure that such constants get computed and not optimized out.

Josh Triplett (Apr 20 2020 at 23:15, on Zulip):

compile_error exists today. The equivalent of compile_error_if seems extremely straightforward to implement.

Josh Triplett (Apr 20 2020 at 23:16, on Zulip):

And in the future, if we implement and stabilize the multiple issues needed to make const _: () = assert!(...); work, we can always change the definition of static_assert.

Josh Triplett (Apr 20 2020 at 23:16, on Zulip):

It's not like doing so locks us in; we could move it from the language to the library easily enough if we want to do so.

ecstatic-morse (Apr 20 2020 at 23:21, on Zulip):

Josh Triplett said:

compile_error exists today. The equivalent of compile_error_if seems extremely straightforward to implement.

I'm not convinced that this part is true, which is why I'm more bullish on a #![const_panic] based approach I think. Have you looked at implementing compile_error_if? If it is easy to do, then I would be quite happy to have it ASAP, since like you say we can change the implementation later.

Josh Triplett (Apr 20 2020 at 23:22, on Zulip):

For the record, I would like panic/assert in const to work too, once that's ready. :)

Josh Triplett (Apr 20 2020 at 23:23, on Zulip):

And to answer your question: superficially, yes.

nikomatsakis (Apr 21 2020 at 16:48, on Zulip):

Something I would very much like is clear error messages --

nikomatsakis (Apr 21 2020 at 16:48, on Zulip):

you won't get this through the static-assert library

nikomatsakis (Apr 21 2020 at 16:48, on Zulip):

but maybe an assert! based solution would be able to do so

nikomatsakis (Apr 21 2020 at 16:49, on Zulip):

in any case I think we should totally aim for seamless integration

nikomatsakis (Apr 21 2020 at 16:49, on Zulip):

it's worth pointing out that the static assert library lets you guarantee all manner of things, only some of which would be suitable for a static_assert!

nikomatsakis (Apr 21 2020 at 16:49, on Zulip):

it's got some pretty clever hacks in there

simulacrum (Apr 21 2020 at 16:59, on Zulip):

I personally wonder if, since assert! is already pretty embedded in the compiler, we could make it just work in item context, instead of needing a separate macro. But that might be confusing too if it's not a real macro afterwards

Josh Triplett (Apr 21 2020 at 17:04, on Zulip):

I think we need very little in the language itself, just the ability to do a compile-time static assert on a condition and provide a message. The rest can go in some combination of the standard library and other crates.

Josh Triplett (Apr 21 2020 at 17:05, on Zulip):

@simulacrum I think I'd rather not have assert! do too much DWIM based on context.

simulacrum (Apr 21 2020 at 17:16, on Zulip):

Yeah -- though I wonder if a more general "const expressions are items" could be an interesting idea. But probably not much benefit, I agree.

nikomatsakis (Apr 21 2020 at 17:39, on Zulip):

well

nikomatsakis (Apr 21 2020 at 17:39, on Zulip):

keep in mind that

fn foo() {
    fn bar() { }
}

works

nikomatsakis (Apr 21 2020 at 17:39, on Zulip):

I think that's one of those design decisions I would reverse if we could

nikomatsakis (Apr 21 2020 at 17:40, on Zulip):

but regardless, it makes fn foo() { assert!(...); } kind of "ambiguous"

Josh Triplett (Apr 21 2020 at 17:40, on Zulip):

I do use items-in-functions occasionally, and would want that to still work.

simulacrum (Apr 21 2020 at 17:41, on Zulip):

That's a good point. I don't mind so much having a separate macro

Josh Triplett (Apr 21 2020 at 17:41, on Zulip):

That said, I did put something in the 2021 ideas list that talked about improving the handling of const inside a block.

Josh Triplett (Apr 21 2020 at 17:42, on Zulip):

I'd like to have order actually matter. I don't think it should work to forward-reference a constant declared later in a code block.

nikomatsakis (Apr 21 2020 at 17:42, on Zulip):

well so

nikomatsakis (Apr 21 2020 at 17:43, on Zulip):

ok, let's not discuss nested items for the time being

nikomatsakis (Apr 21 2020 at 17:43, on Zulip):

but it might make sense to deprecate some subset because "IDE friendly"

simulacrum (Apr 21 2020 at 17:44, on Zulip):

my understanding (though only through talking/hearing @matklad) is that IDEs care far more about our "macros produce arbitrary items" problem :)

simulacrum (Apr 21 2020 at 17:45, on Zulip):

but yeah

nikomatsakis (Apr 21 2020 at 18:15, on Zulip):

well, both are bad

nikomatsakis (Apr 21 2020 at 18:16, on Zulip):

but one is easy to fix :P

Nikolai Vazquez (May 04 2020 at 20:59, on Zulip):

Author of static_assertions crate here. I'm planning to turn const_assert! into const _: () = assert!(condition, message); when that becomes stable.

Last update: Jun 05 2020 at 22:55UTC