惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

WordPress大学
WordPress大学
大猫的无限游戏
大猫的无限游戏
酷 壳 – CoolShell
酷 壳 – CoolShell
博客园 - 叶小钗
月光博客
月光博客
Last Week in AI
Last Week in AI
让小产品的独立变现更简单 - ezindie.com
让小产品的独立变现更简单 - ezindie.com
人人都是产品经理
人人都是产品经理
阮一峰的网络日志
阮一峰的网络日志
罗磊的独立博客
IT之家
IT之家
美团技术团队
OSCHINA 社区最新新闻
OSCHINA 社区最新新闻
Hugging Face - Blog
Hugging Face - Blog
博客园_首页
S
SegmentFault 最新的问题
宝玉的分享
宝玉的分享
博客园 - Franky
freeCodeCamp Programming Tutorials: Python, JavaScript, Git & More
Jina AI
Jina AI
奇客Solidot–传递最新科技情报
奇客Solidot–传递最新科技情报
The Cloudflare Blog
博客园 - 司徒正美
爱范儿
爱范儿

Rust Blog

Security Advisory for Cargo (CVE-2026-5223) | Rust Blog Security Advisory for Cargo (CVE-2026-5222) | Rust Blog Project goals update — April 2026 (end of 2025H2) | Rust Blog Rust is participating in Outreachy | Rust Blog Raising the baseline for the `nvptx64-nvidia-cuda` target | Rust Blog Announcing Google Summer of Code 2026 selected projects | Rust Blog Announcing Rust 1.95.0 | Rust Blog docs.rs: building fewer targets by default | Rust Blog Changes to WebAssembly targets and handling undefined symbols | Rust Blog Announcing Rust 1.94.1 | Rust Blog Security advisory for Cargo | Rust Blog What we heard about Rust's challenges | Rust Blog Call for Testing: Build Dir Layout v2 | Rust Blog Announcing rustup 1.29.0 | Rust Blog Announcing Rust 1.94.0 | Rust Blog 2025 State of Rust Survey Results | Rust Blog Rust debugging survey 2026 | Rust Blog Update on the October 15, 2018 incident on crates.io Announcing Rust 1.29.2 Announcing Rust 1.29 Announcing Rust 1.28 What is Rust 2018? Announcing Rust 1.27.2 Announcing Rust 1.27.1 Security Advisory for rustdoc Announcing Rust 1.27 Announcing Rust 1.26.2 Announcing Rust 1.26.1 Rust turns three Announcing Rust 1.26
Const generics MVP hits beta!
The const generics project group · 2021-02-26 · via Rust Blog

After more than 3 years since the original RFC for const generics was accepted, the first version of const generics is now available in the Rust beta channel! It will be available in the 1.51 release, which is expected to be released on March 25th, 2021. Const generics is one of the most highly anticipated features coming to Rust, and we're excited for people to start taking advantage of the increased power of the language following this addition.

Even if you don't know what const generics are (in which case, read on!), you've likely been benefitting from them: const generics are already employed in the Rust standard library to improve the ergonomics of arrays and diagnostics; more on that below.

With const generics hitting beta, let's take a quick look over what's actually being stabilized, what this means practically, and what's next.

What are const generics?

Const generics are generic arguments that range over constant values, rather than types or lifetimes. This allows, for instance, types to be parameterized by integers. In fact, there has been one example of const generic types since early on in Rust's development: the array types [T; N], for some type T and N: usize. However, there has previously been no way to abstract over arrays of an arbitrary size: if you wanted to implement a trait for arrays of any size, you would have to do so manually for each possible value. For a long time, even the standard library methods for arrays were limited to arrays of length at most 32 due to this problem. This restriction was finally lifted in Rust 1.47 - a change that was made possible by const generics.

Here's an example of a type and implementation making use of const generics: a type wrapping a pair of arrays of the same size.

struct ArrayPair<T, const N: usize> {
    left: [T; N],
    right: [T; N],
}

impl<T: Debug, const N: usize> Debug for ArrayPair<T, N> {
    // ...
}

Current restrictions

The first iteration of const generics has been deliberately constrained: in other words, this version is the MVP (minimal viable product) for const generics. This decision is motivated both by the additional complexity of general const generics (the implementation for general const generics is not yet complete, but we feel const generics in 1.51 are already very useful), as well as by the desire to introduce a large feature gradually, to gain experience with any potential shortcomings and difficulties. We intend to lift these in future versions of Rust: see what's next.

Only integral types are permitted for const generics

For now, the only types that may be used as the type of a const generic argument are the types of integers (i.e. signed and unsigned integers, including isize and usize) as well as char and bool. This covers a primary use case of const, namely abstracting over arrays. In the future, this restriction will be lifted to allow more complex types, such as &str and user-defined types.

No complex generic expressions in const arguments

Currently, const parameters may only be instantiated by const arguments of the following forms:

  • A standalone const parameter.
  • A literal (i.e. an integer, bool, or character).
  • A concrete constant expression (enclosed by {}), involving no generic parameters.

For example:

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

fn bar<T, const M: usize>() {
    foo::<M>(); // ok: `M` is a const parameter
    foo::<2021>(); // ok: `2021` is a literal
    foo::<{20 * 100 + 20 * 10 + 1}>(); // ok: const expression contains no generic parameters
    
    foo::<{ M + 1 }>(); // error: const expression contains the generic parameter `M`
    foo::<{ std::mem::size_of::<T>() }>(); // error: const expression contains the generic parameter `T`
    
    let _: [u8; M]; // ok: `M` is a const parameter
    let _: [u8; std::mem::size_of::<T>()]; // error: const expression contains the generic parameter `T`
}

By-value array iterator

In addition to the language changes described above, we've also started adding methods to the standard library taking advantage of const generics. While most are not yet ready for stabilization in this version, there is one method that has been stabilized. array::IntoIter allows arrays to be iterated by value, rather than by reference, addressing a significant shortcoming. There is ongoing discussion about the possibility of implementing IntoIterator directly for arrays, though there are backwards-compatibility concerns that still have to be addressed. IntoIter::new acts as an interim solution that makes working with arrays significantly simpler.

use std::array;
fn needs_vec(v: Vec<i32>) {
    // ...
}

let arr = [vec![0, 1], vec![1, 2, 3], vec![3]];
for elem in array::IntoIter::new(arr) {
    needs_vec(elem);
}

What's next?

Const generics and default arguments

Generic parameters must currently come in a specific order: lifetimes, types, consts. However, this causes difficulties when one attempts to use default arguments alongside const parameters. For the compiler to know which generic argument is which, any default arguments need to be placed last. These two constraints - "types come before consts", and "defaults come last" - conflict with each other for definitions that have default type arguments and const parameters.

The solution to this is to relax the ordering constraint so that const parameters may precede type arguments. However, there turn out to be subtleties involved in implementing this change, because the Rust compiler currently makes assumptions about parameter ordering that require some delicacy to remove.

In light of similar design questions around defaults for const arguments, these are also currently not supported in version 1.51. However, fixing the parameter ordering issues above will also unblock const defaults.

Const generics for custom types

For a type to be valid, in theory, as the type of a const parameter, we must be able to compare values of that type at compile-time. Furthermore, equality of values should be well-behaved (namely, it should be deterministic, reflexive, symmetric, and transitive). To guarantee these properties, the concept of structural equality was introduced in the const generics RFC: essentially this includes any type with #[derive(PartialEq, Eq)] whose members also satisfy structural equality.

There are still some questions concerning precisely how structural equality should behave, and prerequisites for implementation. Primitive types are significantly simpler, which has allowed us to stabilize const generics for these types before more general types.

Const generics with complex expressions

There are several complexities involved in supporting complex expressions. A feature flag, feature(const_evaluatable_checked), is available in the Nightly channel, which enables a version of complex expression support for const generics.

One difficulty lies in the necessity of having some way to compare unevaluated constants, as the compiler does not automatically know that two syntactically identical expressions are actually equal. This involves a kind of symbolic reasoning about expressions, which is a complex problem in general.

// The two expressions `N + 1` and `N + 1` are distinct
// entities in the compiler, so we need a way to check
// if they should be considered equal.
fn foo<const N: usize>() -> [u8; N + 1] {
    [0; N + 1]
}

We also want a way to deal with potential errors when evaluating generic operations.

fn split_first<T, const N: usize>(arr: [T; N]) -> (T, [T; N - 1]) {
    // ...
}

fn generic_function<const M: usize>(arr: [i32; M]) {
    // ...
    let (head, tail) = split_first(arr);
    // ...
}

Without a way to restrict the possible values of M here, calling generic_function::<0>() would cause an error when evaluating 0 - 1 that is not caught at declaration time and so may unexpectedly fail for downstream users.

There are design questions about how exactly to express these kinds of bounds, which need to be addressed before stabilising complex const arguments.

Summary

With such a major new feature, there are likely to be a few rough edges. If you encounter any problems, even if it's as minor as a confusing error message, please open an issue! We want the user experience to be the best it can possibly be - and any issues now are likely to be even more important for the next iterations of const generics.