I’m writing a fixed-size bit sequence type in Rust with the nightly features generic_const_exprs
and int_roundings
, and I’m able to impl
BitAndAssign
as such (I’ve not included the body because it isn’t necessary to verify that the first example builds and the second one doesn’t):
trait Bits {
const BITS: u32;
}
impl Bits for u32 {
const BITS: u32 = Self::BITS;
}
const fn bslen(x: u32, b: u32) -> usize {
x.div_ceil(b) as usize
}
struct BitSet<const X: u32, T: Bits = u32>
where
[(); bslen(X, T::BITS)]:
{
data: [T; bslen(X, T::BITS)]
}
use std::ops::BitAndAssign;
impl<const X: u32, const Y: u32, T: Bits>
BitAndAssign<&BitSet<Y, T>>
for BitSet<X, T>
where
[(); bslen(X, T::BITS)]:,
[(); bslen(Y, T::BITS)]:
{
fn bitand_assign(&mut self, other: &BitSet<Y, T>) {}
}
But when I try to change it to use Borrow<BitSet<Y, T>>
instead of &BitSet<Y, T>
, like so:
use std::ops::BitAndAssign;
use std::borrow::Borrow;
impl<const X: u32, const Y: u32, T: Bits, BSY: Borrow<BitSet<Y, T>>>
BitAndAssign<BSY>
for BitSet<X, T>
where
[(); bslen(X, T::BITS)]:,
[(); bslen(Y, T::BITS)]:
{
fn bitand_assign(&mut self, other: BSY) {}
}
I get an error:
error[E0207]: the const parameter `Y` is not constrained by the impl trait, self type, or predicates
--> src/minrep.rs:22:26
|
22 | impl<const X: u32, const Y: u32, T: Bits, BSY: Borrow<BitSet<Y, T>>>
| ^ unconstrained const parameter
|
I’m not sure what this means, since Y
is constrained, or why it only happens in the second case. generic_const_exprs
is unstable, so this could just be a compiler bug, but I figured I should ask just in case there’s something obvious, or not so obvious, that I’m missing.
CodePudding user response:
One BSY
type could implement Borrow<BitSet<Y, T>>
for multiple Y
s. In this case, knowing that BitSet<X, T>
implements BitAndAssign<BSY>
is simply not enough for the compiler to infer the value of Y
as there are multiple options.
This is why the compiler complains that Y
is unconstrained -- given the type BitSet<X, T>
and its implementation of the BitAndAssign<BSY>
trait (for a particular type BSY
), the compiler cannot necessarily determine the value of Y
. On the other hand, given the type BitSet<X, T>
and its implementation of the BitAndAssign<&BitSet<Y, T>>
trait, the compiler knows exactly what value of Y
to use as it is present in the trait definition.