# Constifying the std/core library

**URL:** <https://internals.rust-lang.org/t/constifying-the-std-core-library/12962>\
**Category:** Uncategorized\
**Created:** [August 26, 2020, 7:31pm UTC](https://internals.rust-lang.org/t/constifying-the-std-core-library/12962 "2020-08-26T19:31:13Z")\
**Posts on this page:** 18\
**Page:** 1

<div class="post-metadata">

**Author:** ![bugadani](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/bugadani/32/7133_2.png) [@bugadani](https://internals.rust-lang.org/u/bugadani)\
**Post date:** [August 26, 2020, 7:31pm UTC](https://internals.rust-lang.org/t/constifying-the-std-core-library/12962/1 "2020-08-26T19:31:13Z")

</div>

Hi!

Now that conditions and loops are allowed in constant functions, would it make sense to mark as much of the standard library as possible as const? What drawbacks would that have?

---

<div class="post-metadata">

**Author:** ![gbutler](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/gbutler/32/3670_2.png) [@gbutler](https://internals.rust-lang.org/u/gbutler)\
**Post date:** [August 26, 2020, 8:19pm UTC](https://internals.rust-lang.org/t/constifying-the-std-core-library/12962/2 "2020-08-26T20:19:53Z")

</div>

> [@bugadani](#):
>
> What drawbacks would that have?

A commitment to always have those API's be constant compatible which may limit implementation flexibility. So caution is probably warranted, but, with thorough evaluation and consideration, things should move to `const` as the need for such is determined (via light-weight proposals/PR's, MFC, and/or RFC's).

---

<div class="post-metadata">

**Author:** ![bugadani](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/bugadani/32/7133_2.png) [@bugadani](https://internals.rust-lang.org/u/bugadani)\
**Post date:** [August 26, 2020, 9:10pm UTC](https://internals.rust-lang.org/t/constifying-the-std-core-library/12962/3 "2020-08-26T21:10:16Z")

</div>

> [@gbutler](#):
>
> > [@bugadani](#):
> >
> > What drawbacks would that have?
> 
> A commitment to always have those API's be constant compatible

Thanks! I was thinking more about technical drawbacks, like significantly increased compile times or something, but I guess that's a valid point as well.

---

<div class="post-metadata">

**Author:** ![ratmice](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/ratmice/32/4917_2.png) [@ratmice](https://internals.rust-lang.org/u/ratmice)\
**Post date:** [August 26, 2020, 9:14pm UTC](https://internals.rust-lang.org/t/constifying-the-std-core-library/12962/4 "2020-08-26T21:14:44Z")

</div>

> [@bugadani](#):
>
> What drawbacks would that have?

One thing i've noticed with const constructors (where there are already some in stable), is that ptr equality can lead to some awkward behaviors, such as the following assertions. This won't impact existing comparisons, I.e. using static or local bindings these compare as you would expect, but we're potentially introducing new weird const pointer comparisons.

```rust
use std::mem::MaybeUninit;

const C1: MaybeUninit<bool> = MaybeUninit::<bool>::uninit();
const C2: MaybeUninit<bool> = MaybeUninit::<bool>::uninit();

const CT: MaybeUninit<bool> = MaybeUninit::new(true);
const CT2: MaybeUninit<bool> = MaybeUninit::new(true);
const CF: MaybeUninit<bool> = MaybeUninit::new(false);

fn main() {
    assert!(std::ptr::eq(C1.as_ptr(), C2.as_ptr()));
    assert!(std::ptr::eq(CT.as_ptr(), CT2.as_ptr()));
    // This one is especially peculiar.
    assert!(std::ptr::eq(C1.as_ptr(), CF.as_ptr()));
}

```

---

<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:** [August 26, 2020, 10:17pm UTC](https://internals.rust-lang.org/t/constifying-the-std-core-library/12962/5 "2020-08-26T22:17:41Z")

</div>

> [@ratmice](#):
>
> ```rust
> // This one is especially peculiar.
> assert!(std::ptr::eq(C1.as_ptr(), CF.as_ptr()));
> 
> ```

Not really, because `undef` (in LLVM) is "could be anything", so one possible thing it could be is false, so given that it's a `Freeze` thing it's no weirder than any other const promotion thing getting merged with something else (like `&0` and `&0` having the same address).

---

<div class="post-metadata">

**Author:** ![ratmice](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/ratmice/32/4917_2.png) [@ratmice](https://internals.rust-lang.org/u/ratmice)\
**Post date:** [August 27, 2020, 5:21am UTC](https://internals.rust-lang.org/t/constifying-the-std-core-library/12962/6 "2020-08-27T05:21:39Z")

</div>

Well, I don't really know what to say except why then not assert! true, or true and false, it's the "in LLVM" part that bothers me mostly, as this is entirely safe code, but I haven't really found an explanation other than "In LLVM" which explains this observable equivalence.

So, I get worried when "because `undef`" starts being an explanation for the observable behavior of safe code. Anyhow it's definitely a corner case which i'm certain i'm in the minority of being concerned about so i'll leave it at that.

---

<div class="post-metadata">

**Author:** ![tspiteri](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/tspiteri/32/7283_2.png) [@tspiteri](https://internals.rust-lang.org/u/tspiteri)\
**Post date:** [August 27, 2020, 6:16am UTC](https://internals.rust-lang.org/t/constifying-the-std-core-library/12962/7 "2020-08-27T06:16:36Z")

</div>

> [@bugadani](#):
>
> I was thinking more about technical drawbacks, like significantly increased compile times

Compile times wouldn't increase because marking a function as const will not affect the way it is compiled in already working code. It only makes the function usable in new places such as when defining a new constant, but it does not affect how it is compiled otherwise.

For example

```rust
const fn foo(a: i32) -> i32 { /* ... */ }
// ...
const C: i32 = foo(1);
let x = foo(5);

```

Here `foo` can be used to define `C` because it is const. But the const does not affect `x` in any way. That is, if without const the function was evaluated at compile time as an optimization, then it will still be evaluated at compile time with const. But if without const the function was not evaluated at compile time, then it will still not be evaluated at compile time with const. To force compile time evaluation you would need something like

```rust
const X: i32 = foo(5);
let x = X;

```

[RFC 2920](https://github.com/rust-lang/rfcs/pull/2920) is there to provide a way to force compile time evaluation, but that would have to be explicitly forced and is not automatic.

---

<div class="post-metadata">

**Author:** ![bugadani](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/bugadani/32/7133_2.png) [@bugadani](https://internals.rust-lang.org/u/bugadani)\
**Post date:** [August 27, 2020, 7:46am UTC](https://internals.rust-lang.org/t/constifying-the-std-core-library/12962/8 "2020-08-27T07:46:04Z")

</div>

Oh my, so I had a totally wrong assumption here about compile-time evaluation. Thanks a lot!

---

<div class="post-metadata">

**Author:** ![Nemo157](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/nemo157/32/11585_2.png) [@Nemo157](https://internals.rust-lang.org/u/Nemo157)\
**Post date:** [August 27, 2020, 8:34am UTC](https://internals.rust-lang.org/t/constifying-the-std-core-library/12962/9 "2020-08-27T08:34:45Z")

</div>

A blocker for some constification right now is optimized implementations. I had a quick look at constifying `str::from_utf8`, and it looks like all features to get it working exist now _except_ the validation uses some pointer tricks to perform faster which are not supported in const-context yet (the first blocker I noticed was for aligning, which [may be "supported" in the future since it's just a hint](https://github.com/rust-lang/rust/issues/62420), but there may be other blockers hiding behind that error).

Being able to write the "naive" implementation to run in `const`-context and `unsafe`ly assert that this optimized implementation is equivalent and should be used at runtime would be very useful.

(There is some prior discussion of this in rust-lang/rust _somewhere_, but with a quick search I couldn't find it, iirc @oli-obk was suggesting a macro-like `unsafe { if_const!(const_impl, runtime_impl) }`)

---

<div class="post-metadata">

**Author:** ![Ixrec](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/ixrec/32/6754_2.png) [@Ixrec](https://internals.rust-lang.org/u/Ixrec)\
**Post date:** [August 27, 2020, 9:44am UTC](https://internals.rust-lang.org/t/constifying-the-std-core-library/12962/10 "2020-08-27T09:44:50Z")

</div>

> [@Nemo157](#):
>
> Being able to write the "naive" implementation to run in `const` -context and `unsafe` ly assert that this optimized implementation is equivalent and should be used at runtime would be very useful.
> 
> (There is some prior discussion of this in rust-lang/rust _somewhere_ , but with a quick search I couldn't find it, iirc @oli-obk was suggesting a macro-like `unsafe { if_const!(const_impl, runtime_impl) }` )

The closest thing I'm aware of is discussion of "unconst" operations: [What do we do with "unconst" operations? · Issue #14 · rust-lang/const-eval · GitHub](https://github.com/rust-lang/const-eval/issues/14). I feel like I've also seen a const-if or if-const thing somewhere, but I can't find that now either.

---

<div class="post-metadata">

**Author:** ![gbutler](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/gbutler/32/3670_2.png) [@gbutler](https://internals.rust-lang.org/u/gbutler)\
**Post date:** [August 27, 2020, 1:58pm UTC](https://internals.rust-lang.org/t/constifying-the-std-core-library/12962/11 "2020-08-27T13:58:24Z")

</div>

> [@tspiteri](#):
>
> But the const does not affect `x` in any way

Is this entirely the case? Isn't it the case, at least in theory, that a `const` function could/would be optimized to a greater degree (more easily possibly) then a non-const function due to the fact that a `const` function is guaranteed to not have side-effects or rely upon extraneous state?

---

<div class="post-metadata">

**Author:** ![tesuji](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/tesuji/32/12790_2.png) [@tesuji](https://internals.rust-lang.org/u/tesuji)\
**Post date:** [August 27, 2020, 2:41pm UTC](https://internals.rust-lang.org/t/constifying-the-std-core-library/12962/12 "2020-08-27T14:41:10Z")

</div>

Currently compiler doesn't exploit that at all. You could join [https://rust-lang.zulipchat.com/#narrow/stream/122651-general/topic/Common.20misconception.3A.20.60const.20fn.60.20and.20its.20effect.20on.20codegen](https://rust-lang.zulipchat.com/#narrow/stream/122651-general/topic/Common.20misconception.3A.20.60const.20fn.60.20and.20its.20effect.20on.20codegen) for related discussion.

---

<div class="post-metadata">

**Author:** ![gbutler](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/gbutler/32/3670_2.png) [@gbutler](https://internals.rust-lang.org/u/gbutler)\
**Post date:** [August 27, 2020, 3:13pm UTC](https://internals.rust-lang.org/t/constifying-the-std-core-library/12962/13 "2020-08-27T15:13:31Z")

</div>

Thanks for the link. I'll definitely read on it.

> [@tesuji](#):
>
> Currently compiler doesn't exploit that at all

That is why I said, "at least in theory," meaning that even if the compiler currently didn't take advantage of it, there was the possibility of making the compiler exploit it for optimization purposes.

---

<div class="post-metadata">

**Author:** ![RalfJung](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/ralfjung/32/2415_2.png) [@RalfJung](https://internals.rust-lang.org/u/RalfJung)\
**Post date:** [August 29, 2020, 11:35am UTC](https://internals.rust-lang.org/t/constifying-the-std-core-library/12962/14 "2020-08-29T11:35:15Z")

</div>

Almost everything is possible. 😉 But the fact remains that it currently doesn't happen, neither in Rust nor in C++. Any discussion about its consequences is entirely hypothetical and should be treated as such. It is entirely unclear if it would be a good idea -- `const` functions can still fail to evaluate (panic, loop forever), so it's not like we can just make the optimizer run them all blindly. If we have an analysis that determines which of them can be run, then we might as well use that analysis on _all_ functions.

* * *

@ratmice that is an interesting case. Pointer equality is indeed a very tricky subject, and I am afraid the ship long has sailed where saying anything about it is "simple". There's a whole series of open questions related to it; [I collected them in this issue](https://github.com/rust-lang/unsafe-code-guidelines/issues/239).

The explanation for the behavior you noticed is that consts do not have a stable address, so the compiler is allowed to merge multiple constants into one as it sees fit. We don't need to mention LLVM for this explanation. I was not aware that it would even merge `undef` with 0; I think this is an artifact of how we compile `undef` to LLVM (AFAIK we will it with 0s), but it is certainly consistent with the general principle of consts not having a stable address.

---

<div class="post-metadata">

**Author:** ![ratmice](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/ratmice/32/4917_2.png) [@ratmice](https://internals.rust-lang.org/u/ratmice)\
**Post date:** [August 30, 2020, 12:42am UTC](https://internals.rust-lang.org/t/constifying-the-std-core-library/12962/15 "2020-08-30T00:42:48Z")

</div>

Thanks, this at least sets me at some ease that the behavior is how rustc compiles `undef` to LLVM, and that the compiler is in control of the matter, not just some LLVM behavior which could change whimsically without considering the invariants of the trait `Eq`.

The rest of my concerns should be covered by _note to self_: don't store secrets in consts.

---

<div class="post-metadata">

**Author:** ![notriddle](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/notriddle/32/14082_2.png) [@notriddle](https://internals.rust-lang.org/u/notriddle)\
**Post date:** [September 1, 2020, 11:10pm UTC](https://internals.rust-lang.org/t/constifying-the-std-core-library/12962/16 "2020-09-01T23:10:47Z")

</div>

> [@scottmcm](#):
>
> Not really, because `undef` (in LLVM) is "could be anything", so one possible thing it could be is false, so given that it's a `Freeze` thing it's no weirder than any other const promotion thing getting merged with something else (like `&0` and `&0` having the same address).

You can already see similar situations using `Cell::new()` in a const position.

```rust
use std::cell::Cell;

const C: Cell<bool> = Cell::new(false);

fn main() {
  C.set(true);
  assert_eq!(false, C.get());
}

```

[Playground link](https://play.rust-lang.org/?version=stable&mode=debug&edition=2018&gist=f87b06456af20dbfc406f7ea61f74cb0)

A `const` item will actually produce a new object every time you mention it. In the Cell's case, that means mutation gets silently thrown away. In pointers' case, that means `C1.as_ptr()` produces a dangling raw pointer.

---

<div class="post-metadata">

**Author:** ![elichai2](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/elichai2/32/5205_2.png) [@elichai2](https://internals.rust-lang.org/u/elichai2)\
**Post date:** [September 24, 2020, 1:27pm UTC](https://internals.rust-lang.org/t/constifying-the-std-core-library/12962/17 "2020-09-24T13:27:58Z")

</div>

That's a more general problem of const vs static that should be solved via good documentation and compiler warnings, I don't think it's really related to const fn

---

<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 23, 2020, 1:28pm UTC](https://internals.rust-lang.org/t/constifying-the-std-core-library/12962/18 "2020-12-23T13:28:23Z")

</div>

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