r/rust • • 20h ago

šŸ“” official blog Generic Const Args and You | Inside Rust Blog

https://blog.rust-lang.org/inside-rust/2026/10/02/generic-const-args-and-you/
210 Upvotes

43 comments sorted by

77

u/Recatek gecs 20h ago

The generic_const_exprs feature is probably the #1 most frequent unstable feature that the compiler points out to me as I'm writing code. I constantly bang my head against this limitation right now. Always very excited and eager to read about progress in this space.

12

u/cosmic-parsley 9h ago

Head banging is right, I can’t tell you how many times I’ve written `-> [u8; N * 2]` and almost flipped my laptop because it doesn’t work.

That seems much simpler than everything else in the article. Maybe it could be stable first?

72

u/kiujhytg2 19h ago

Thanks for all of your hard work, const generics is one of those "It can't be that hard, can it, can't you just ..." tasks that's more complex than it initially seems

41

u/yodal_ 17h ago

I remember when work was first starting on const generics. I was actually one of the first people to work on it, though lcnr quickly became the main driving force as I had to focus on my senior year of college. We got full const generics "working" pretty quickly all things considered. It was only a few months of work off and on. I remember finally getting a const generics program building and running around Christmas Eve of 2017. One of the first programs even used expressions! It felt like we were so close.

We then realized how many corner cases and hidden assumptions there were hiding all over the compiler. This resulted in at least three massive refactors to get even min_const_generics over the finish line. It is crazy to think that the "full" feature is still being worked on nearly a decade later, but just from the early work I can't say I'm too surprised.

18

u/noop_noob 16h ago

generic_const_exprs is one of the nightly features that is prone to crashing the compiler. List of known crashes: https://github.com/rust-lang/rust/issues?q=is%3Aissue+state%3Aopen+label%3AF-generic_const_exprs+label%3AI-ICE

28

u/Shnatsel 19h ago

min_generic_const_args and the full-blown generic_const_args would be very useful for SIMD, so I'm excited to hear there is progress!

22

u/CouteauBleu 14h ago

This article is really missing an explanation of what the gca! macro means and why it's necessary.

From the background I have, I'm guessing it's mostly about semver stability (e.g. if any function can be used in type signatures, then changing any function body becomes a breaking change) but I'd appreciate a full explanation spelling it out rather than just "this macro allows you to used this syntax but not that one".

6

u/kibwen 10h ago

See the prior discussion from this Zulip thread for more information on the difficulties that motivated the current design and its limitations: https://rust-lang.zulipchat.com/#narrow/channel/260443-project-const-generics/topic/nightly-2026-09-06.20generic.20const.20regression/near/622430401

8

u/matthieum [he/him] 14h ago

There are hints dropped in the What is Macroless section.

Apparently, it's just about being explicit about GCA being used, tying in with your remark on SemVer I guess.

But yeah... I kinda kept wondering if the topic of why there's a macro would be addressed later in the article, and was left hanging.

11

u/CouteauBleu 12h ago

There are hints dropped in the What is Macroless section.

That section doesn't actually what "GCA" is for. Like, it says that using the gca! syntax implicitly would make it unclear when the restrictions apply, but the article doesn't explain why gca! even has these restrictions in the first place.

4

u/kotakotik22 13h ago

I agree, that would have been nice.

I think it's also because GCA types push errors to post-mono: some definitely-erroneous functions would never produce a compiler error if they're never called. For example:

``` fn foo<const N : usize>() -> usize { N }

// note: the ABC type parameter is necessary so that the compiler doesn't automatically monomorphize this function. For the current rust compiler this doesn't make a difference but it would for a theoretical one where everything is GCA fn bar<const ABC : usize>() -> usize { foo::<{ 0usize - 1 }>() } ```

Currently, this will fail to compile even if bar is never used (monomorphized). If everything was GCA, this would only produce an error once bar is used by another function. (Similar to a panicking const-block)

I'm not really sure how much of an issue this really is: there are not many cases where a constant fails to initialize and it is known to always fail. But it does make some small difference for users and likely a huge difference for the compiler.

2

u/kotakotik22 13h ago

This could also have bigger consequences with potential future features. For example, if constants could have global side effects, it would suddenly begin to matter whether a constant was used at all: under GCA, global state would now depend on whether a function is called anywhere in the program.

Also, if we added where clauses which depend on constant arguments (e.g. where N > 16), we would now have a lot of functions that are more difficult to debug because N could be influenced by anything in the call chain.

And maybe more substantial cases I can't think of right now.

15

u/suggestiveinnuendo 19h ago

hopefully soon!

12

u/UARTman 17h ago

This seems a bit hacky as a solution, but I hope this works out, because having proper const generics is a good step to that perhaps unattainable holy grail that is dependently-typed imperative languages.

5

u/bascule 14h ago

Very excited for this feature as using an associated constant as the size of an array is the main reason RustCrypto has used typenum and hybrid-array/generic-array.

GCA should allow us to completely eliminate use of hybrid-array. We may need to keep using typenum for awhile until const generic expressions actually have full feature parity with it, but as soon as we can use typenum::Unsigned::USIZE as N in [T; N] the need for hybrid-array goes away.

3

u/Thomasedv 16h ago

I skimmed the article, so pardon if it's already stated. My head isn't able to parse all that complexity on a late Friday.Ā 

One of the tings I miss was when working on a function where most things were the same, but it branched on an enum with 3 values.Ā 

Much to my disappointment, this didn't work despite the enum being stateless so it's just pure integers at that point being used. Seeing the article, I didn't see if this special case was mentioned or not, only that you'd have to use the macro for an enum with fields that hold values. Ideally the stateless enums could easily be converted to pure integers behind the scenes and circumvent GCA complexity entirely?Ā 

Const generics with enums seems so much better for readability. Especially at the caller side where you'll either pass a number/bool, or some named constant to represent the value as a number. It makes so much more sense to have the enum directly and use it in the function. And the macro makes you pay an near equal amount of readability to use the function.Ā 

Also, for the macroless case, is it a compiler limit that we can leave the syntax inside the const block as some MaybeGca type, and resolve it based on the expected type? After all the function or struct already defines the expected type, so if you know that, you should know if you're getting something that potentially is GCA? I'm not particularly familiar with const generics, so I'm just guessing. My knowledge of this starts and stops with trying to use an enum variant as a const.

6

u/vdrnm 16h ago

Enums are supported with nightly feature min_adt_const_params.
Obviously not super convenient due to nightly and having to use ConstParamTy derive, but it works:

#![feature(min_adt_const_params)]

use core::marker::ConstParamTy;

#[derive(ConstParamTy, PartialEq,Eq)]
enum UEnum {
  One,Two,Three
}
fn generic_over_enum<const E: UEnum>() {
  match E {
    UEnum::One => println!("one"),
    UEnum::Two => println!("two"),
    UEnum::Three => println!("three"),
  }
}

2

u/Thomasedv 15h ago

Thanks for that. It would certainly be enough for my use.Ā 

Hopefully it makes it to stable in some form, as it's very convenient when needed. Sadly I don't want to use nightly for my own project.Ā 

5

u/Mrblahblah200 13h ago

Why is the gca macro here needed? Also, it’s a liiittle ugly, I hope it’s removed or renamed before release

2

u/noop_noob 13h ago

This is explained in the post under the heading "What is Macroless"

1

u/Mrblahblah200 8h ago

Ah cheers! I disagree with their reasoning honestly. It smacks to me of purity over utility

0

u/SirKastic23 8h ago

Did you read the post?

All GCA features require any newly supported expressions to be written inside of a gca! macro call. We are aware that this requirement poses significant ergonomic problems and are currently looking into ways to avoid this, though have not arrived at a good solution yet (more on this later).

3

u/ioneska 2h ago

Did you read the post?

All GCA features require any newly supported expressions to be written inside of a gca! macro call.

And yet this doesn't really answer to the parent question: Why is the gca macro here needed.

2

u/SirKastic23 1h ago

Probably because this is an experimental feature?

I guess I would have liked to see why they decided to require the macro for the feature, so it's a fair question by all means

But assuming that this is how the feature would land in stable doesn't make any sense

2

u/Mrblahblah200 8h ago

I couldn’t find the later?

1

u/SirKastic23 8h ago

I assumed "later" means a future post

2

u/InternationalFee3911 15h ago

Just at lunch I’d been niggling that the new release once again didn’t advance constexprs. Followed right on the heels by this article…

While it’s amazing and laudable the amount of dedication and resourcefulness that goes into fixing these surprisingly hard problems, at the same time it makes me cry. Basic arithmetic ([u8; N-1]) is one of the things I long for most. The macro sure feels alien, but if it gives a huge benefit, it’s not too bad as a workaround.

But the timeline – let’s hope GCA lands before GTA VII (rumored 2030!)

5

u/kibwen 12h ago

GTA VII (rumored 2030!)

If you mean 2,030 years from now, then that sounds believable, if a tad optimistic.

2

u/________-__-_______ 11h ago

Great to see this is actively progressing! Together with const fn in trait this is the feature I most often miss when doing compile time chicanery, really excited for it to be stabilized.

3

u/Lucretiel Datadog 10h ago

As excited as I am for const generic expressions (I’ve needed them surprisingly more often than I expected), I’m gonna be honest that I’m not a fan of the vibes on this. Is the macro expected to be temporary? I think I’m a bigger than most of new language features on average, but this definitely crosses a qualitative line in my head towards the ā€œlost the plotā€ the characterizes a lot of modern C++ features.Ā 

3

u/kibwen 10h ago

I believe the hope is to omit the macro. However, it's not clear to me whether it's possible to do so in all cases without changing the semantics of the language.

2

u/SirKastic23 8h ago edited 8h ago

I’m gonna be honest that I’m not a fan of the vibes on this. Is the macro expected to be temporary?

Is the only vibe you have an issue with the macro?

The post makes it clear it is meant to be temporary

All GCA features require any newly supported expressions to be written inside of a gca! macro call. We are aware that this requirement poses significant ergonomic problems and are currently looking into ways to avoid this, though have not arrived at a good solution yet (more on this later).

2

u/yuriks 7h ago edited 7h ago

Yeah honestly, I've occasionally wanted the ability to use arithmetic expressions in const generic parameters, and was also excited for the reduction of restrictions on the feature just from the principle of "things that feel like they should work should work" which seems to underpin a lot of the recent work on the language. But after reading this post I was just left with the feeling that "maybe I can do without this one, actually". :|

I'm definitely missing some of the context on the implementation difficulties since it's been a while since I've read into this deeply, but the article I feel also didn't do a great job convincing me why I would want to deal with this. The allowed kinds of expressions seem very limited (e.g. from what I understand arithmetic is still actually impossible? Or at least none of the examples clearly showed it being possible.) and there aren't motivational examples showing how they could improve existing code. The justification for the gca! syntax also seemed circular. It talks about how it's needed to distinguish what parameters can use the new flexibility or not, but from my point of view all of those restrictions seem to stem more from compiler limitations rather than a semantic difference that I should be paying attention to as a programmer.

I'll have to give it a re-read later to see if I just need some more coffee, but I'm glad to see I'm at least not alone in being confused(?) by the post.

EDIT: To clarify, I'm not criticizing the work that went into the feature at all. I understand how challenging it is to design and implement these things. I guess my point is that, as a call to action/testing, I don't feel like the article really inspired me to experiment or be excited about what's coming from it.

0

u/sasik520 15h ago

I sometimes wonder if it didn't go too far.

The article mentions rust wants to support stuff like struct Bar<const N: Foo>; or fn accepts_arrays<const N: [usize; 2]>() {}. I just wonder, if this really brings that much benefit?

So far, all use cases I've seen involve ints and the most demanded thing is being able to add and/or substract consts, e.g.

``` struct Bar<const N: usize> {}

impl<const N: usize> Bar<N> { fn baz() -> Baz { Baz::<N + 2> {} } } ```

Maybe plain simple enums could be supported too, but honestly since nothing stop an enum to add a parametrized variant at any time, I'm unsure if it's that good idea.

Are there really any real-life use cases for more complex const generics and especially ones that justify all of this extreme complexity?

(btw. I have an exact same thought on specialization)

9

u/CouteauBleu 14h ago

One very immediate use-case is being able to use NonZeroU32 and the likes in const generics, without special-casing them.

7

u/Lasuman 15h ago

Yes there are certainly use cases for complex const-generics, a good example is my crate which uses them to encode possible-value-sets.

-4

u/sasik520 15h ago

I mean... don't be offended please, but this is an example of a crate with 67 downloads.

Does it justify years of work of multiple people and probably hundreds of thousands of line of code in the compiler and the tooling?

7

u/Lasuman 15h ago

Crates that make use of many very unstable features naturally have a very limited potential user base.
Since const-generics are very limited on stable, what you generally see in the wild will only make use of the currently available feature set.

Also hundreds of thousands LOC is an overestimation by an order of magnitude.

6

u/Recatek gecs 13h ago

Every addition to the language that satisfies my use case is vital.

Every addition to the language unrelated to my use case is bloat.

1

u/sasik520 13h ago

There are for sure people thinking this way but that's definitely not my point of view and I have never started anything like that.

2

u/Tastaturtaste 14h ago

Of course there won't be much code in the wild showing use-cases as long as it's not possible to write the code on stable.Ā 

If you are interested in use-cases that will be possible with this, you can take a look at C++'s Non-Type-Template-Parameters (NTTPs), which since C++ 20 also support structural types.Ā 

One use-case could be support for a custom "on-drop" function on my::Box without increasing it's size: If the "on-drop" function is stateless and its type can be made part of the Box instantiation, the instance wouldn't have to store the function or even a pointer to the function.Ā Ā 

Ā  Ā  struct Box<T, const F: FnOnce(T)>{}Ā Ā  Ā  Ā  let box = Box::new::<i32, typeof!(|n| println!("{n}"))>(5);Ā Ā  Ā  Ā  assert_eq!(std::mem::size_of_val(&box), 8);Ā  Ā  Ā  Ā  drop(box); // prints 5

As you probably notice, other stuff is still missing to make this possible: typeof is one of the missing pieces. But generic_const_exprs should get us one step closer.

3

u/SmartAsFart 10h ago

You don't need const generics for a custom drop function. You just create a Dropper trait with a method which you call with the contents of your custom box. This is a ZST, with no requirement for const generics.

1

u/Tastaturtaste 9h ago

You are right, that is much more straightforward. My bad!