是否可以在 Rust 中使用 const 泛型实例化新类型?

Wee*_*ezy 1 generics rust const-generics

我不是 const 泛型方面的专家,但在尝试涉及对 const 泛型进行操作的新类型实例化时,我尝试了几种不同的方法,但都存在问题,例如:当尝试将此 const 泛型结构中的基数从 增加到KK+1

// Given a Base<K> return a Base<K+1>
pub struct Base<const K:u32> {}
pub const fn base_bump<const K: u32, const L: u32>(b: Base<K>,) -> Base<L> {
    const L : u32 = K + 1;
    Base::<L> {}
}
Run Code Online (Sandbox Code Playgroud)

错误 :

error[E0401]: can't use generic parameters from outer function
 --> src/main.rs:5:20
  |
2 | pub const fn base_bump<const K: u32, const L: u32>(
  |                              - const parameter from outer function
...
5 |     const l: u32 = K + 1;
  |                    ^ use of generic parameter from outer function

For more information about this error, try `rustc --explain E0401`.
error: could not compile `playground` due to previous error
Run Code Online (Sandbox Code Playgroud)

我的理解是 const 泛型的当前状态拒绝const generic从其他const genericss 实例化 new ,因为const generics 在成为值之前是类型。爱荷华州,K

error[E0401]: can't use generic parameters from outer function
 --> src/main.rs:5:20
  |
2 | pub const fn base_bump<const K: u32, const L: u32>(
  |                              - const parameter from outer function
...
5 |     const l: u32 = K + 1;
  |                    ^ use of generic parameter from outer function

For more information about this error, try `rustc --explain E0401`.
error: could not compile `playground` due to previous error
Run Code Online (Sandbox Code Playgroud)

是一种类型,而不是由 定义的通常的 const 值,const K : u32 = 1;尽管我在这里强烈提到,错误消息并未指出其背后的原因。

当我们尝试这样做时会出现另一个问题:

fn foo<const K: u32> () {}
Run Code Online (Sandbox Code Playgroud)

错误:

error[E0207]: the const parameter `L` is not constrained by the impl trait, self type, or predicates
 --> src/lib.rs:3:27
  |
3 | impl<const K : u32, const L: u32> Base<K> {
  |                           ^ unconstrained const parameter
  |
  = note: expressions using a const parameter must map each value to a distinct output value
  = note: proving the result of expressions other than the parameter are unique is not supported
Run Code Online (Sandbox Code Playgroud)

有什么方法可以实现我在这里尝试做的事情,或者我应该放弃 const 泛型并使用常规字段来定义此处的基数?

Cha*_*man 5

我的理解是 const 泛型的当前状态拒绝从其他 const 泛型实例化新的 const 泛型,因为 const 泛型在成为值之前是类型

这不是真的,但您的代码存在多个问题。

首先,正如编译器指出的那样,const L 函数内部不能引用函数的泛型参数K。这是因为consts 是单独编译的,即使在函数内部也是如此(唯一的区别是函数外部的代码无法访问,即作用域)。

您应该嵌入计算:

pub const fn base_bump<const K: u32, const L: u32>(b: Base<K>) -> Base<L> {
    Base::<{ K + 1 }> {}
}
Run Code Online (Sandbox Code Playgroud)

但这仍然存在多个问题。首先,您声明您要返回调用者选择的值,但实际上您返回的是常量Base而不是。您需要像这样声明该函数:LK + 1L

pub const fn base_bump<const K: u32>(b: Base<K>) -> Base<{ K + 1 }> {
    Base::<{ K + 1 }> {}
}
Run Code Online (Sandbox Code Playgroud)

但这会出错:

error: generic parameters may not be used in const operations
 --> src/lib.rs:2:74
  |
2 | pub const fn base_bump<const K: u32, const L: u32>(b: Base<K>) -> Base<{ K + 1 }> {
  |                                                                          ^ cannot perform const operation using `K`
  |
  = help: const parameters may only be used as standalone arguments, i.e. `K`

error: generic parameters may not be used in const operations
 --> src/lib.rs:3:14
  |
3 |     Base::<{ K + 1 }> {}
  |              ^ cannot perform const operation using `K`
  |
  = help: const parameters may only be used as standalone arguments, i.e. `K`
Run Code Online (Sandbox Code Playgroud)

因为这东西需要#![feature(generic_const_exprs)]有了它,它可以工作,但会发出警告:

warning: the feature `generic_const_exprs` is incomplete and may not be safe to use and/or cause compiler crashes
 --> src/lib.rs:1:12
  |
1 | #![feature(generic_const_exprs)]
  |            ^^^^^^^^^^^^^^^^^^^
  |
  = note: `#[warn(incomplete_features)]` on by default
  = note: see issue #76560 <https://github.com/rust-lang/rust/issues/76560> for more information
Run Code Online (Sandbox Code Playgroud)

请参阅我的这个答案,了解为什么此功能特别困难。