如何让递归下降泛型常量的Rust代码成功编译?
解决方法
要让这段代码编译,得加约束保证N始终大于0,同时让递归的ConsPeaks<{N-1}>类型合法。具体来说,要在结构体的where子句里明确限制N > 0,避免N-1出现usize下溢,还要确保递归类型满足自身的约束。
修改后的代码
#![feature(generic_const_exprs)] struct ConsPeaks<const N: usize> where [(); N]: Sized, // 限制 N 必须大于0,防止 N-1 下溢 const { N > 0 }: bool, // 保证递归的 ConsPeaks<{N-1}> 符合自身的约束要求 ConsPeaks<{ N - 1 }>: Sized, { data: [u8; N], next: Option<Box<ConsPeaks<{ N - 1 }>>>, } // 给 N=0 的情况写终止实现,不然 N=1 时 next 的类型会找不到合法定义 impl ConsPeaks<0> { fn new() -> Self { Self { data: [], next: None, } } } impl<const N: usize> ConsPeaks<N> where [(); N]: Sized, const { N > 0 }: bool, ConsPeaks<{ N - 1 }>: Sized, { fn new(data: [u8; N], next: Option<Box<ConsPeaks<{ N - 1 }>>>) -> Self { Self { data, next } } }
为什么之前的Assert方法没用?
你之前试的Assert<{N>0}>: IsTrue约束没生效,是因为没给Assert<true>实现IsTrue trait。补上这个实现,再加上递归类型的约束,代码就能编译:
#![feature(generic_const_exprs)] struct Arr<const N: usize> where Assert<{N > 0}>: IsTrue, // 确保递归的 Arr<{N-1}> 满足约束 Arr<{N-1}>: Sized, { data: [u8; N], next: Option<Box<Arr<{N-1}>>>, } enum Assert<const COND: bool> {} trait IsTrue {} // 只给 Assert<true> 实现 IsTrue,这样当 N>0 时约束才成立 impl IsTrue for Assert<true> {} // 终止条件:N=0 的情况 impl Arr<0> { fn new() -> Self { Self { data: [], next: None, } } } impl<const N: usize> Arr<N> where Assert<{N > 0}>: IsTrue, Arr<{N-1}>: Sized, { fn new(data: [u8; N], next: Option<Box<Arr<{N-1}>>>) -> Self { Self { data, next } } }
核心逻辑
Rust的generic_const_exprs特性要求所有泛型const表达式在编译期必须合法,哪怕你不会去实例化非法的N值。加N > 0的约束,就能排除N=0的情况(此时N-1会下溢成usize的最大值,导致数组大小非法);加ConsPeaks<{N-1}>: Sized约束,是为了确保递归的类型也满足自身的所有where条件。最后给N=0写终止结构体,让递归链有合法的终点。
内容的提问来源于stack exchange,提问作者user18236575
相关产品推荐
相关产品推荐

