Rust generic_const_exprs特性循环检测错误排查与修复求助
Rust位字段宏实现中的循环检测错误
问题背景
在实现位字段相关的Bits trait时,针对数组类型的impl触发了编译器的循环检测错误,核心代码及错误信息如下:
定义的Bits trait
pub trait Bits { const BITS: usize; // 该字段的位数 type Underlying; // 存储该字段所需的最小底层无符号整数类型(u8、u16等) fn from_arbint(from: arbitrary_int::UInt<Self::Underlying, { Self::BITS }>) -> Self; }
数组类型的Bits实现
// 用于计算存储指定位数所需的最小无符号整数类型 pub trait CalcUint { type Uint; } impl CalcUint for [(); 1] { type Uint = u8; } // ... 省略其他位数对应的impl impl CalcUint for [(); 9] { type Uint = u16; } // ... impl<T, const N: usize> Bits for [T; N] where T: Bits + Default + Copy, [(); T::BITS * N]: CalcUint, { const BITS: usize = T::BITS * N; type Underlying = <[(); T::BITS * N] as CalcUint>::Uint; fn from_arbint(from: arbitrary_int::UInt<Self::Underlying, { Self::BITS }>) -> Self { todo!() } }
编译器错误信息
error[E0391]: cycle detected when building an abstract representation for `<impl at src/lib.rs:53:1: 56:33>::from_arbint::{constant#0}` --> src/lib.rs:62:64 | 62 | fn from_arbint(from: arbitrary_int::UInt<Self::Underlying, { Self::BITS }>) -> Self { | ^^^^^^^^^^^^^^ | note: ...which requires building THIR for `<impl at src/lib.rs:53:1: 56:33>::from_arbint::{constant#0}`... --> src/lib.rs:62:64 | 62 | fn from_arbint(from: arbitrary_int::UInt<Self::Underlying, { Self::BITS }>) -> Self { | ^^^^^^^^^^^^^^ note: ...which requires type-checking `<impl at src/lib.rs:53:1: 56:33>::from_arbint::{constant#0}`... --> src/lib.rs:62:72 | 62 | fn from_arbint(from: arbitrary_int::UInt<Self::Underlying, { Self::BITS }>) -> Self { | ^^^^ = note: ...which requires evaluating trait selection obligation `[T; N]: Bits`... = note: ...which again requires building an abstract representation for `<impl at src/lib.rs:53:1: 56:33>::from_arbint::{constant#0}`, completing the cycle note: cycle used when checking that `<impl at src/lib.rs:53:1: 56:33>` is well-formed --> src/lib.rs:53:1 | 53 | / impl<T, const N: usize> Bits for [T; N] 54 | | where 55 | | T: Bits + Default + Copy, 56 | | [(); T::BITS * N]: CalcUint, | |________________________________^
错误原因分析
编译器验证[T; N]的Bits实现合法性时陷入循环依赖:
- 为确定
from_arbint方法的参数类型,需要计算Self::BITS的值; Self::BITS定义为T::BITS * N,但编译器需要确认[T; N]满足Bits约束,这又回到检查该impl的合法性,包括from_arbint的参数类型;- 上述步骤形成闭环,触发循环检测错误。
修复方案
直接在from_arbint的参数类型中使用T::BITS * N替代Self::BITS,因为Self::BITS本质就是该计算值,可避免编译器递归查询Self::BITS,打破循环。
修改后的数组Bits实现
impl<T, const N: usize> Bits for [T; N] where T: Bits + Default + Copy, [(); T::BITS * N]: CalcUint, { const BITS: usize = T::BITS * N; type Underlying = <[(); T::BITS * N] as CalcUint>::Uint; // 用T::BITS * N替换Self::BITS fn from_arbint(from: arbitrary_int::UInt<Self::Underlying, { T::BITS * N }>) -> Self { todo!() } }
说明
修改后,编译器可直接通过T的BITS常量和N计算出所需位数,无需递归查询[T; N]的BITS常量,解决循环依赖问题。
内容的提问来源于stack exchange,提问作者fubupc
相关产品推荐
相关产品推荐

