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 Ys. 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.
