Rust中泛型常量表达式为何需添加空where约束?
Rust中const泛型结构体的奇怪where约束含义解析
问题重现
尝试定义带const泛型的结构体时,编译器报错:
#![feature(generic_const_exprs)] struct ArInt<const W: usize, const S: bool> { iarr: [i32; { (W + 31 + (!S) as usize) / 32 }], }
报错信息:
error: unconstrained generic constant --> src/lib.rs:4:11 | 4 | iarr: [i32; { (W + 31 + (!S) as usize) / 32 }], | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | = help: try adding a `where` bound using this expression: `where [(); { (W + 31 + (!S) as usize) / 32 }]:`
按照提示添加空where约束后编译通过:
#![feature(generic_const_exprs)] struct ArInt<const W: usize, const S: bool> where [(); { (W + 31 + (!S) as usize) / 32 }]: { iarr: [i32; { (W + 31 + (!S) as usize) / 32 }], }
约束含义解析
这个看似奇怪的where [(); { ... }]:约束,核心作用是强制编译器验证const表达式的结果是合法的数组长度,具体拆解如下:
[(); N]是Rust中的单元类型数组,其中()是不占内存的单元类型,N是数组长度。Rust要求数组长度必须是编译期可确定的非负usize值。- 这里的
{ (W + 31 + (!S) as usize) / 32 }是动态计算的const表达式,由于generic_const_exprs是不稳定特性,编译器目前无法自动推导该表达式的结果是否符合数组长度要求。 - 这个空约束省略了要实现的trait,本质是要求
[(); N]这个类型是良构的(well-formed)——而数组类型良构的前提就是N是有效的、非负的编译期usize常量。
简单来说,这个约束就是给编译器明确信号:"我确认这个const表达式计算出的长度合法,请允许用它定义数组",以此绕过编译器对未约束泛型常量的检查。
内容的提问来源于stack exchange,提问作者Yan Zhu
相关产品推荐
相关产品推荐

