# Discussion: Const requirements

**URL:** <https://internals.rust-lang.org/t/discussion-const-requirements/10942>\
**Category:** language design\
**Created:** [September 13, 2019, 5:33pm UTC](https://internals.rust-lang.org/t/discussion-const-requirements/10942 "2019-09-13T17:33:47Z")\
**Posts on this page:** 15\
**Page:** 1

<div class="post-metadata">

**Author:** ![Nokel81](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/nokel81/32/3966_2.png) [@Nokel81](https://internals.rust-lang.org/u/Nokel81)\
**Post date:** [September 13, 2019, 5:33pm UTC](https://internals.rust-lang.org/t/discussion-const-requirements/10942/1 "2019-09-13T17:33:47Z")

</div>

I was looking at the documentation for [AtomicU8::compare\_exchange](https://doc.rust-lang.org/std/sync/atomic/struct.AtomicU8.html#method.compare_exchange) and noticed that there was a very specific set of instructions on what is allowed in terms of the `Ordering` parameters.

I would imagine that the use of this would be made better if such things were checked at compile time. This is also not the only place that such compile checks would be nice to have.

Therefore I ask: is there any desire to have such checks be, at least in part, possible?

What I am imagining are some sort of annotations, sort of like `where` clauses that are attempted at compile time. To facilitate this, we could also make calling functions with these checks `unsafe` if the compiler cannot guarantee that it checks out.

Example: (Assuming `std::cmp::Ord` is implemented for `Ordering`)

```rust
pub fn compare_exchange(
    &self,
    current: u8,
    new: u8,
    success: Ordering,
    failure: Ordering
) -> Result<u8, u8> 
where 
    success >= failure,
    failure == Ordering::SeqCst
        || failure == Ordering::Acquire
        || failure == Ordering::Relaxed

```

---

<div class="post-metadata">

**Author:** ![mcy](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/mcy/32/6512_2.png) [@mcy](https://internals.rust-lang.org/u/mcy)\
**Post date:** [September 13, 2019, 5:48pm UTC](https://internals.rust-lang.org/t/discussion-const-requirements/10942/2 "2019-09-13T17:48:33Z")

</div>

While this is a very good idea (comparable to C++ contracts), I think atomics are the wrong use-case. Adding this sort of compile-time checking to atomics is dangerous because they are _still_ subtle to use and it will lull people into shooting their feet off.

---

<div class="post-metadata">

**Author:** ![Nokel81](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/nokel81/32/3966_2.png) [@Nokel81](https://internals.rust-lang.org/u/Nokel81)\
**Post date:** [September 13, 2019, 5:54pm UTC](https://internals.rust-lang.org/t/discussion-const-requirements/10942/3 "2019-09-13T17:54:40Z")

</div>

I have had this idea for some time, but it was when I was reading the atomic's documentation that I finally came up with a public example of what could be made better.

However, I don't quite see how this specific check would lull people into a dangerous situation anymore than the current panics do.

---

<div class="post-metadata">

**Author:** ![hanna-kruppe](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/hanna-kruppe/32/6540_2.png) [@hanna-kruppe](https://internals.rust-lang.org/u/hanna-kruppe)\
**Post date:** [September 13, 2019, 6:08pm UTC](https://internals.rust-lang.org/t/discussion-const-requirements/10942/4 "2019-09-13T18:08:17Z")

</div>

I also don't understand why these extra checks would give any particular false sense of security, but there's a more serious show-stopper for applying this kind of compile-time checking to existing APIs: it's backwards incompatible. Unless you make uses with runtime values only warn instead of error, but at that point it's not clear to me why we should add a new language feature instead of a lint.

---

<div class="post-metadata">

**Author:** ![Nokel81](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/nokel81/32/3966_2.png) [@Nokel81](https://internals.rust-lang.org/u/Nokel81)\
**Post date:** [September 13, 2019, 6:26pm UTC](https://internals.rust-lang.org/t/discussion-const-requirements/10942/5 "2019-09-13T18:26:02Z")

</div>

So C++ contracts basically panic if a pre-/post-condition fails (runtime checks) and they can be turned off completely (in rust it would probably be `debug_assert!(...)`.

I don't quite see how this is backwards incompatible in general (specific cases may vary). For the function call that I initially linked the values that I check are `panic!(...)` in the original, so no code would have those values anyway.

---

<div class="post-metadata">

**Author:** ![hanna-kruppe](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/hanna-kruppe/32/6540_2.png) [@hanna-kruppe](https://internals.rust-lang.org/u/hanna-kruppe)\
**Post date:** [September 13, 2019, 6:45pm UTC](https://internals.rust-lang.org/t/discussion-const-requirements/10942/6 "2019-09-13T18:45:39Z")

</div>

One kind of backwards incompatibility is if the function which is changed to require constant parameters (or else `unsafe`, as you proposed as escape hatch) was wrapped and the wrapper uses runtime parameters (because the const parameter equivalent didn't exist when it was written), for example:

```rust
fn my_cmpxchg(x: &AtomicU8, success: Ordering, failure: Ordering) -> Result<u8, u8> {
    x.compare_exchange(0, 1, success, failure)
}

```

---

<div class="post-metadata">

**Author:** ![Nokel81](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/nokel81/32/3966_2.png) [@Nokel81](https://internals.rust-lang.org/u/Nokel81)\
**Post date:** [September 13, 2019, 6:59pm UTC](https://internals.rust-lang.org/t/discussion-const-requirements/10942/7 "2019-09-13T18:59:03Z")

</div>

Ah makes sense. However, I think that how we roll such a feature out should be discussed later. I used this as an example of why it might be useful

---

<div class="post-metadata">

**Author:** ![scottmcm](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/scottmcm/32/2355_2.png) [@scottmcm](https://internals.rust-lang.org/u/scottmcm)\
**Post date:** [September 13, 2019, 9:05pm UTC](https://internals.rust-lang.org/t/discussion-const-requirements/10942/8 "2019-09-13T21:05:20Z")

</div>

I don't think there's a need for anything _compile-time_ here -- either making a more specific type or already-on-the-list constraints on const generics will be sufficient.

I think that this could be re-phrased into a _runtime_ thing that seems interesting to me, though. We have lots of methods that start by `assert!`ing something, and making that more visible to callers seems interesting.

For example, [`.step_by(0)` panics](https://doc.rust-lang.org/std/iter/trait.Iterator.html#method.step_by), and (iirc) there's a special-case clippy lint to help catch that. What if, instead of being hidden in the implementation, one could do `#[assert(step > 0)]` on the method? Then built-in lints could try to check those things, while still doing the check at runtime. That way it could be automatically-documented too.

(And for `compare_exchange`, maybe it'd be a `#[debug_assert]`, which lints could still use even if nothing happens at runtime.)

---

<div class="post-metadata">

**Author:** ![newpavlov](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/newpavlov/32/3290_2.png) [@newpavlov](https://internals.rust-lang.org/u/newpavlov)\
**Post date:** [September 13, 2019, 9:20pm UTC](https://internals.rust-lang.org/t/discussion-const-requirements/10942/9 "2019-09-13T21:20:49Z")

</div>

I think adding `debug_assert`s to those functions would be great, but right now we can't do it properly, see discussion in this [issue](https://github.com/rust-lang/rust/issues/51713).

And I would also love for Rust to move a bit closer to SPARK in terms of powerful compile-time contracts.

---

<div class="post-metadata">

**Author:** ![comex](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/comex/32/2587_2.png) [@comex](https://internals.rust-lang.org/u/comex)\
**Post date:** [September 13, 2019, 9:25pm UTC](https://internals.rust-lang.org/t/discussion-const-requirements/10942/10 "2019-09-13T21:25:57Z")

</div>

The ordering parameters really should be const generic parameters, like

```rust
pub fn compare_exchange<
    const SUCCESS: Ordering,
    const FAILURE: Ordering
>(
    &self,
    current: u8,
    new: u8
) -> Result<u8, u8> 

```

After all, the assembly code is different for each possible ordering. In fact, the implementations of these functions contain [a `match` over all possible orderings](https://github.com/rust-lang/rust/blob/master/src/libcore/sync/atomic.rs#L2169), which the optimizer will fold away if the ordering is constant, but which generates quite a lot of code if it isn't.

But const generics didn't exist when these APIs were created.

For const generic parameters, I agree that booleans in where clauses would be very useful. But doing it for runtime parameters would be a huge can of worms.

---

<div class="post-metadata">

**Author:** ![newpavlov](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/newpavlov/32/3290_2.png) [@newpavlov](https://internals.rust-lang.org/u/newpavlov)\
**Post date:** [September 13, 2019, 9:30pm UTC](https://internals.rust-lang.org/t/discussion-const-requirements/10942/11 "2019-09-13T21:30:12Z")

</div>

> [@comex](#):
>
> But const generics didn't exist when these APIs were created.

Small nitpick: [const arguments](https://internals.rust-lang.org/t/pre-rfc-const-function-arguments/6709) is a separate feature (which I would really like to see implemented one day) and is not entailed by const generics.

---

<div class="post-metadata">

**Author:** ![Nokel81](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/nokel81/32/3966_2.png) [@Nokel81](https://internals.rust-lang.org/u/Nokel81)\
**Post date:** [September 13, 2019, 9:40pm UTC](https://internals.rust-lang.org/t/discussion-const-requirements/10942/12 "2019-09-13T21:40:16Z")

</div>

Yes it would be nice that asserts and debug asserts placed in a specific way to be part of the documentation but I see that as a different concept and less useful since it isn't done at compile time.

One of the great benefits I see in Rust is compile time guarantees. And there are definite ergonomic arguments for not always making new types. Especially when there needs to some relation between two different parameters.

To negate some of the annoyance of unsafe functions we could treat debug and normal asserts as verifying the preconditions even if the runtime check doesn't happen in release mode.

---

<div class="post-metadata">

**Author:** ![scottmcm](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/scottmcm/32/2355_2.png) [@scottmcm](https://internals.rust-lang.org/u/scottmcm)\
**Post date:** [September 13, 2019, 10:21pm UTC](https://internals.rust-lang.org/t/discussion-const-requirements/10942/13 "2019-09-13T22:21:24Z")

</div>

> [@Nokel81](#):
>
> One of the great benefits I see in Rust is compile time guarantees

Sure. But those are best done on compile-time parameters, not runtime ones. And @hanna-kruppe already pointed out that there cannot be compile-time checks on the existing functions, so the new ones with the compile-time checks can just take compile-time parameters (as in @comex's post).

Then it's just value-constraints on const generics, which have been [on the wish-list for a while](https://github.com/rust-lang/rfcs/pull/1932), but are hard enough then even simple cases like `1+1=2` were [left out of RFC 2000](https://github.com/rust-lang/rfcs/blob/master/text/2000-const-generics.md#unresolved-questions).

---

<div class="post-metadata">

**Author:** ![comex](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/comex/32/2587_2.png) [@comex](https://internals.rust-lang.org/u/comex)\
**Post date:** [September 14, 2019, 2:12am UTC](https://internals.rust-lang.org/t/discussion-const-requirements/10942/14 "2019-09-14T02:12:28Z")

</div>

> [@newpavlov](#):
>
> Small nitpick: [const arguments](https://internals.rust-lang.org/t/pre-rfc-const-function-arguments/6709) is a separate feature (which I would really like to see implemented one day) and is not entailed by const generics.

Nitpick to your nitpick: Const generics as currently implemented would make possible the modified API from my last post, where the ordering parameters are moved within angle brackets. Const _arguments_ would make possible an API that keeps the parameters in their current position while requiring them to be constants.

---

<div class="post-metadata">

**Author:** ![system](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/system/32/14092_2.png) [@system](https://internals.rust-lang.org/u/system)\
**Post date:** [December 13, 2019, 2:24am UTC](https://internals.rust-lang.org/t/discussion-const-requirements/10942/15 "2019-12-13T02:24:06Z")

</div>

Closed on December 13, 2019, 2:24am UTC

This topic was automatically closed 90 days after the last reply. New replies are no longer allowed.
