Open
Description
This is a problem when implementing a bitfield macro in Rust.
pub trait Bits {
const BITS: usize; // How many bits this field has
type Underlying; // Minimum underlying uint (u8, u16, ...) to store this field
fn from_arbint(from: arbitrary_int::UInt<Self::Underlying, { Self::BITS }>) -> Self;
}
This code uses an arbitrary precision integer library: arbitrary-int. Trait Bits is used to describe:
- How many bits this field has.
- Minimum underlying uint type to store this field, like u8, u16, .. etc.
- How to convert an arbitrary_int::UInt<T, BITS> to this field.
For example, for a bool type:
impl Bits for bool {
const BITS: usize = 1;
type Underlying = u8;
fn from_arbint(from: arbitrary_int::UInt<Self::Underlying, { Self::BITS }>) -> Self {
from.value() == 1
}
}
For array type it becomes a bit more complicated:
// Used to calculate the minimun uint type to store bits
pub trait CalcUint {
type Uint;
}
impl CalcUint for [(); 1] {
type Uint = u8;
}
...
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!()
}
}
Then the compiler report error at { Self::BITS } in from_arbint:
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,
| |________________________________^
= note: see https://rustc-dev-guide.rust-lang.org/overview.html#queries and https://rustc-dev-guide.rust-lang.org/query.html for more information
Can someone help to explain why is this happening and how to fix it? Thanks!
PS: For complete code: https://play.rust-lang.org/?version=nightly&mode=debug&edition=2021&gist=a893e99e95aa2a964fa49546a9fbdaaa .
NOTE: The playground does not support random 3rd party library(?), so one need to copy code to local for test/debug.
Metadata
Metadata
Assignees
Labels
No labels