# My misunderstand of "const generic"

**URL:** <https://internals.rust-lang.org/t/my-misunderstand-of-const-generic/14203>\
**Category:** language design\
**Created:** [March 8, 2021, 3:51am UTC](https://internals.rust-lang.org/t/my-misunderstand-of-const-generic/14203 "2021-03-08T03:51:00Z")\
**Posts on this page:** 13\
**Page:** 1

<div class="post-metadata">

**Author:** ![earthengine](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/earthengine/32/2577_2.png) [@earthengine](https://internals.rust-lang.org/u/earthengine)\
**Post date:** [March 8, 2021, 3:51am UTC](https://internals.rust-lang.org/t/my-misunderstand-of-const-generic/14203/1 "2021-03-08T03:51:00Z")

</div>

When I heard about "const generic" I was thinking about something like

```rust
const<T> EMPTY_OPTION: Option<T> = None;
...
let ref_to_option:&'static _ = &EMPTY_OPTION::<u32>; 
//so we can freely return this to callers without worrying about lifetimes... 

```

Not

```rust
fn add_multiple_times<const N:u8>(v: u32, to_add: u8) -> u32 {...};
...
let result = add_multiple_times::<10>(8, 9);

```

I know it actually means the later and it is going to land soon; but what about the former? Are there any plans?

---

<div class="post-metadata">

**Author:** ![jhpratt](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/jhpratt/32/11640_2.png) [@jhpratt](https://internals.rust-lang.org/u/jhpratt)\
**Post date:** [March 8, 2021, 4:02am UTC](https://internals.rust-lang.org/t/my-misunderstand-of-const-generic/14203/2 "2021-03-08T04:02:53Z")

</div>

I'd personally call the former "generic constants". As far as I'm aware nobody has ever proposed this, let alone implemented it.

---

<div class="post-metadata">

**Author:** ![Soni](https://avatars.discourse-cdn.com/v4/letter/s/a3d4f5/32.png) [@Soni](https://internals.rust-lang.org/u/Soni)\
**Post date:** [March 8, 2021, 4:19am UTC](https://internals.rust-lang.org/t/my-misunderstand-of-const-generic/14203/3 "2021-03-08T04:19:20Z")

</div>

We've definitely _asked_ for generic ~~constants~~ statics before.

---

<div class="post-metadata">

**Author:** ![jhpratt](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/jhpratt/32/11640_2.png) [@jhpratt](https://internals.rust-lang.org/u/jhpratt)\
**Post date:** [March 8, 2021, 4:44am UTC](https://internals.rust-lang.org/t/my-misunderstand-of-const-generic/14203/4 "2021-03-08T04:44:29Z")

</div>

Well I've never seen it at least. I obviously can't speak for what I haven't seen.

---

<div class="post-metadata">

**Author:** ![earthengine](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/earthengine/32/2577_2.png) [@earthengine](https://internals.rust-lang.org/u/earthengine)\
**Post date:** [March 8, 2021, 5:27am UTC](https://internals.rust-lang.org/t/my-misunderstand-of-const-generic/14203/5 "2021-03-08T05:27:39Z")

</div>

I think no one will blame you for this; but we would like to see discussions about the feature and what would be the technical issues behind it.

This feature is commonly exists in other languages with generics, as far as I know the list includs C++ (as a class level static variable) and C# (commonly understood as "type dictionary").

---

<div class="post-metadata">

**Author:** ![matt1985](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/matt1985/32/4772_2.png) [@matt1985](https://internals.rust-lang.org/u/matt1985)\
**Post date:** [March 8, 2021, 6:08am UTC](https://internals.rust-lang.org/t/my-misunderstand-of-const-generic/14203/6 "2021-03-08T06:08:50Z")

</div>

I would love to get generic constants, but I'm getting by with associated constants.

Generic constants can be emulated with a generic struct (that is never instantiated), and an associated constant of that struct: [https://play.rust-lang.org/?version=stable&mode=debug&edition=2018&gist=1d7d7eee5c6472c3288671a97beb9d64](https://play.rust-lang.org/?version=stable&mode=debug&edition=2018&gist=1d7d7eee5c6472c3288671a97beb9d64)

```rust
use std::marker::PhantomData;

pub struct EMPTY_OPTION<T>(PhantomData<T>);

impl<T> EMPTY_OPTION<T> {
    pub const V: Option<T> = None;
}

fn main(){
    let ref_to_option:&'static _ = &EMPTY_OPTION::<u32>::V; 
}

```

While this is some boilerplate, I don't need generic constants often enough for it to be a problem.

---

<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:** [March 8, 2021, 6:56am UTC](https://internals.rust-lang.org/t/my-misunderstand-of-const-generic/14203/7 "2021-03-08T06:56:53Z")

</div>

> [@jhpratt](#):
>
> I'd personally call the former "generic constants". As far as I'm aware nobody has ever proposed this

🙋

> <https://github.com/rust-lang/rfcs/pull/1520#issuecomment-190783781>
>
> I'm against generic \`static\`s because it is not obvious how they are monomorphiz…ed: currently, monomorphized items always have internal linkage, and monomorphizing them from 2 different crates creates 2 different copies. Doing this in a \`static\` could cause some confusion.

---

<div class="post-metadata">

**Author:** ![matt1985](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/matt1985/32/4772_2.png) [@matt1985](https://internals.rust-lang.org/u/matt1985)\
**Post date:** [March 8, 2021, 7:50am UTC](https://internals.rust-lang.org/t/my-misunderstand-of-const-generic/14203/8 "2021-03-08T07:50:58Z")

</div>

Talking about the RFC: [https://github.com/comex/rfcs/blob/master/text/0000-generic-const-static.md](https://github.com/comex/rfcs/blob/master/text/0000-generic-const-static.md)

I'll mention that the motivation in here is partially covered by associated constants today:

> **The most important benefit is the ability to generate a separate static allocation in the binary for each used set of type parameters**. The use case for scalar-typed generic `const`s somewhat overlaps with `const fn`s, **but when a static address is needed, Rust currently provides no alternative or workaround**. (In particular, `const`s and `static`s inside generic `fn`s cannot refer to the outer `fn`'s type parameters, **nor can associated `const`s inside traits refer to trait generic parameters or to `Self`**. Actually, you can technically do it with `asm!`...)

since associated constants can now refer to the generic parameters of the `impl` block or `trait` (including `Self`), and can construct static references (so long as the type doesn't contain internal mutability) .

Also, the example that constructs `HashKeyData` can be written using associated constants: [https://play.rust-lang.org/?version=stable&mode=debug&edition=2018&gist=498925e5febae16e77c7c615c99582cf](https://play.rust-lang.org/?version=stable&mode=debug&edition=2018&gist=498925e5febae16e77c7c615c99582cf)

The `V` associated constant is a `&'static HashKeyData` to have the same effect as referencing a generic static, except that it doesn't guarantee a single address for all instances of `HKD::<Foo>::V`.  
As I understand it, `HKD::<Bar>::V` accross compilation units can produce different addresses.

Generic constants would have the advantage that they'd be nicer to use than associated constants for this purpose.

Generic statics would have the advantages that they guarantee all instances of `HKD::<u8>` (where `HKD` is a generic static) have the same address, and would allow taking static references to an internally mutable type.

---

<div class="post-metadata">

**Author:** ![earthengine](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/earthengine/32/2577_2.png) [@earthengine](https://internals.rust-lang.org/u/earthengine)\
**Post date:** [March 8, 2021, 9:59am UTC](https://internals.rust-lang.org/t/my-misunderstand-of-const-generic/14203/9 "2021-03-08T09:59:11Z")

</div>

Ok. I read that discussion thread and my impression is that the language team decided to think about it after the "const generic" being landed. So it would not be too long to re-open it. Thanks.

> [@Soni](#):
>
> We've definitely _asked_ for generic ~~constants~~ statics before.

I found your previous proposal.

> <https://github.com/rust-lang/rfcs/issues/2424>
>
> Not to be confused with const generics, but I'll use both to describe the idea.
> …
> 
> Let's say you have a const initializer and you want it to be different for every type:
> 
> \`\`\`rust
> const NONE\_T\_8ARRAY\<T\>: \[Option\<T\>; 8\] = \[None; 8\];
> \`\`\`
> 
> This is the basic generic const construct. Ofc, if you want length also specified:
> 
> \`\`\`rust
> const NONE\_T\_ARRAY\<T, const L: usize\>: \[Option\<T\>; L\] = \[None; L\];
> \`\`\`
> 
> This creates an array of size L containing only None.
> 
> Ofc, you also don't need to use types, consts are fine too:
> 
> \`\`\`rust
> const SQUARE\<const X: usize\>: usize = X \* X;
> \`\`\`
> 
> But perhaps you want it to be recursive:
> 
> \`\`\`rust
> const POW\<const X: usize, 0\>: usize = 1;
> const POW\<const X: usize, const Y: usize\>: usize = X \* POW\<X, Y-1\>;
> \`\`\`
> 
> And you want to calculate Pi with it \[\\\[1\\\]\]:
> 
> \`\`\`rust
> const POW\<const X: usize, 0\>: usize = 1;
> const POW\<const X: usize, const Y: usize\>: usize = X \* POW\<X, Y-1\>;
> const PI\<-1\>: f64 = 0;
> const PI\<const N: isize\>: f64 = (1.0/POW\<16, N as usize\> \* (4.0/(8\*N + 1.0) - 2.0/(8\*N + 4.0) - 1.0/(8\*N + 5.0) - 1.0/(8\*N + 6.0))) + PI\<N-1\>;
> \`\`\`
> 
> \[\\\[1\\\]\]: http://timmurphy.org/2013/06/27/template-metaprogramming-in-c/
> 
> And things of the sort.
> 
> Yeah... they'd be nice.
> 
> May we have them?

It is in "open" status, same as the actual "const generic" feature tracking issue.

> <https://github.com/rust-lang/rust/issues/44580>
>
> Tracking issue for rust-lang/rfcs#2000
> 
> Updates:
> \- 2 May 2019: https://github….com/rust-lang/rust/issues/44580#issuecomment-488819344
> \- 19 Oct 2019: https://github.com/rust-lang/rust/issues/44580#issuecomment-544155666
> \- 2 Jan 2020: https://github.com/rust-lang/rust/issues/44580#issuecomment-570191702
> \- 22 Jul 2020: https://github.com/rust-lang/rust/issues/44580#issuecomment-662543117
> \- 17 Nov 2020: https://github.com/rust-lang/rust/issues/44580#issuecomment-728913127
> \- 11 Dez 2021: https://github.com/rust-lang/rust/issues/44580#issuecomment-991782799
> 
> If you want to help out, take a look at the \[open const generics issues\](https://github.com/rust-lang/rust/labels/A-const-generics) and feel free to ping @varkor, @eddyb, @yodaldevoid, @oli-obk or @lcnr for help in getting started!
> 
> \---
> 
> Blocking stabilization:
> 
> \- \[\] Design:
> - \[x\] Resolving ordering of const and type parameters, with default parameters
> - \[\] Decide what the best UX / implementation cost balance is for unifying abstract const expressions.
> - \[\] How we determine well formedness of const expressions.
> \- \[x\] Implementation
> \- \[\] Documentation
> - \[\] rustc guide
> 
> \---
> 
> Remaining implementation issues:
> \- \[\] Resolve various \`FIXME(const\_generics)\` comments.
> \- \[\] Resolve concerns with canonicalisation / lazy normalisation.
> \- \[\] Investigate handling of const parameters in patterns.
> \- \[\] Add more tests.
> \- \[\] Implement defaults for const parameters (\`FIXME(const\_generics\_defaults)\`).
> \- \[\] Fix other \[A-const-generics issues\](https://github.com/rust-lang/rust/labels/A-const-generics).
> \- \[\] Audit uses of \`has\_infer\_types\`.
> \- \[x\] Forbid complex expressions for const arguments involving parameters (for now), e.g. \`{X \* 2}\`.
> \- \[\] Audit diagnostics (e.g. https://github.com/rust-lang/rust/pull/76401#discussion\_r484819320).

So yes, things are going forward. Thanks for the team!

---

<div class="post-metadata">

**Author:** ![bluss](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/bluss/32/2264_2.png) [@bluss](https://internals.rust-lang.org/u/bluss)\
**Post date:** [March 8, 2021, 12:47pm UTC](https://internals.rust-lang.org/t/my-misunderstand-of-const-generic/14203/10 "2021-03-08T12:47:04Z")

</div>

No new language feature needed for the example in your post, the following:

```rust
pub fn empty<'a, T: 'a>() -> &'a Option<T> { &None }

```

compiles today and allows `'static` if `T: 'static`.

---

<div class="post-metadata">

**Author:** ![matt1985](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/matt1985/32/4772_2.png) [@matt1985](https://internals.rust-lang.org/u/matt1985)\
**Post date:** [March 8, 2021, 6:15pm UTC](https://internals.rust-lang.org/t/my-misunderstand-of-const-generic/14203/11 "2021-03-08T18:15:26Z")

</div>

That's [static promotion](https://doc.rust-lang.org/reference/destructors.html#constant-promotion), and it doesn't work if the expression has function calls (to `const fn`), or contains interior mutability (any type that recursively contains an `UnsafeCell` field).

The calling `const fn` part will work with [inline const](https://doc.rust-lang.org/nightly/unstable-book/language-features/inline-const.html) once it's stabilized, but interior mutability requires generic statics.

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

```rust
error[E0515]: cannot return reference to temporary value
 --> src/lib.rs:7:41
  |
7 | pub fn empty() -> &'static Mutex<u32> { &M }
  | ^-
  | ||
  | |temporary value created here
  | returns a reference to data owned by the current function

error[E0515]: cannot return reference to temporary value
 --> src/lib.rs:9:40
  |
9 | pub fn returns_two() -> &'static u32 { &two() }
  | ^-----
  | ||
  | |temporary value created here
  | returns a reference to data owned by the current function

```

# Generic statics

Generic statics would allow you to get static references to types with interior mutability, so this would work:

```rust
static INSTANCES<T>: AtomicU64 = AtomicU64::new(0);

```

this static would allow counting the amount of instances of any type, without manually creating different statics for each.

---

<div class="post-metadata">

**Author:** ![SlightlyOutOfPhase](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/slightlyoutofphase/32/5440_2.png) [@SlightlyOutOfPhase](https://internals.rust-lang.org/u/SlightlyOutOfPhase)\
**Post date:** [March 11, 2021, 8:07pm UTC](https://internals.rust-lang.org/t/my-misunderstand-of-const-generic/14203/12 "2021-03-11T20:07:07Z")

</div>

It's already possible to achieve exactly what your first example does TBH. The following is perfectly valid, for example:

```rust
use std::marker::PhantomData;

struct Consts<'a, T> {
    phantom: PhantomData<&'a T>,
}

impl<T> Consts<'_, T> {
    const EMPTY_OPTION: Option<T> = None;
}

fn main() {
    let ref_to_option: &'static _ = &Consts::<u32>::EMPTY_OPTION;
}

```

I do agree that being able to write generic constants more "directly" would be nice in some cases though.

**Edit:** I just realized that someone else had already provided an extremely similar example... gets the point across even more for OP now I guess, haha.

---

<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:** [June 9, 2021, 8:07pm UTC](https://internals.rust-lang.org/t/my-misunderstand-of-const-generic/14203/13 "2021-06-09T20:07:26Z")

</div>

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