我正在研究一些位操作代码,该代码将原始整数转换为称为struct Bits(Vec<bool>)
的新类型,其中vec中的每个bool表示单个位。我实现了From特性,从比特转换回使用,它工作得很完美。我改变了From的相同实现,将从Bits转换回u8,它抱怨u8不满足我对BitAnd之类的东西的特征界限,尽管u8确实有BitAnd的实现。实际上,u8和usize通过对Rust库中的宏的完全相同的调用来实现BitAnd。所讨论的特性边界来自我的BitMan特性的一揽子实现。是什么让usize工作得很好,但u8甚至不能编译?
我得到的完整错误和注释是:
error[E0599]: the method `set_bit` exists for type `u8`, but its trait bounds were not satisfied
--> srclib.rs:131:24
|
131 | new_u8.set_bit(index, Bit(current_bit)).unwrap();
| ^^^^^^^ method cannot be called on `u8` due to unsatisfied trait bounds
note: trait bound `&mut u8: BitAnd` was not satisfied
--> srclib.rs:168:8
|
166 | impl<T> BitMan for T
| ------ -
167 | where
168 | T: BitAnd<Output = Self>
| ^^^^^^^^^^^^^^^^^^^^^ unsatisfied trait bound introduced here
note: the following trait bounds were not satisfied:
`<&mut u8 as BitAnd>::Output = &mut u8`
`<&u8 as BitAnd>::Output = &u8`
--> srclib.rs:168:15
|
166 | impl<T> BitMan for T
| ------ -
167 | where
168 | T: BitAnd<Output = Self>
| ^^^^^^^^^^^^^ unsatisfied trait bound introduced here
note: trait bound `&mut u8: BitOr` was not satisfied
--> srclib.rs:169:11
|
166 | impl<T> BitMan for T
| ------ -
...
169 | + BitOr<Output = Self>
| ^^^^^^^^^^^^^^^^^^^^ unsatisfied trait bound introduced here
note: the following trait bounds were not satisfied:
`<&mut u8 as BitOr>::Output = &mut u8`
`<&u8 as BitOr>::Output = &u8`
--> srclib.rs:169:17
|
166 | impl<T> BitMan for T
| ------ -
...
169 | + BitOr<Output = Self>
| ^^^^^^^^^^^^^ unsatisfied trait bound introduced here
note: trait bound `&mut u8: Not` was not satisfied
--> srclib.rs:170:11
|
166 | impl<T> BitMan for T
| ------ -
...
170 | + Not<Output = Self>
| ^^^^^^^^^^^^^^^^^^ unsatisfied trait bound introduced here
note: the following trait bounds were not satisfied:
`<&mut u8 as Not>::Output = &mut u8`
`<&u8 as Not>::Output = &u8`
--> srclib.rs:170:15
|
166 | impl<T> BitMan for T
| ------ -
...
170 | + Not<Output = Self>
| ^^^^^^^^^^^^^ unsatisfied trait bound introduced here
note: trait bound `&mut u8: Shl` was not satisfied
--> srclib.rs:171:11
|
166 | impl<T> BitMan for T
| ------ -
...
171 | + Shl<Output = Self>
| ^^^^^^^^^^^^^^^^^^ unsatisfied trait bound introduced here
note: the following trait bounds were not satisfied:
`<&mut u8 as Shl>::Output = &mut u8`
`<&u8 as Shl>::Output = &u8`
--> srclib.rs:171:15
|
166 | impl<T> BitMan for T
| ------ -
...
171 | + Shl<Output = Self>
| ^^^^^^^^^^^^^ unsatisfied trait bound introduced here
note: the following trait bounds were not satisfied:
`&mut u8: num::Zero`
`&u8: num::Zero`
--> srclib.rs:173:11
|
166 | impl<T> BitMan for T
| ------ -
...
173 | + Zero
| ^^^^ unsatisfied trait bound introduced here
note: the following trait bounds were not satisfied:
`&mut u8: One`
`&u8: One`
--> srclib.rs:174:11
|
166 | impl<T> BitMan for T
| ------ -
...
174 | + One
| ^^^ unsatisfied trait bound introduced here
note: the following trait bounds were not satisfied:
`&mut u8: From<usize>`
`&u8: From<usize>`
`u8: From<usize>`
--> srclib.rs:175:11
|
166 | impl<T> BitMan for T
| ------ -
...
175 | + From<usize>
| ^^^^^^^^^^^ unsatisfied trait bound introduced here
note: trait bound `&mut u8: Clone` was not satisfied
--> srclib.rs:176:11
|
166 | impl<T> BitMan for T
| ------ -
...
176 | + Clone
| ^^^^^ unsatisfied trait bound introduced here
_
pub struct Bits(Vec<bool>);
impl<T> BitMan for T
where
T: BitAnd<Output = Self>
+ BitOr<Output = Self>
+ Not<Output = Self>
+ Shl<Output = Self>
+ Sized
+ Zero
+ One
+ From<usize>
+ Clone
+ PartialEq,
{
fn set_bit(mut self, index: usize, bit: Bit) -> Result<Bit, BitManError> {
if index > size_of::<Self>() {
return Err(BitManError::OutOfBounds(format!(
"Index {:?} is larger than total size {:?}.",
index,
size_of::<Self>()
)));
}
if bit.0 {
let mask: Self = Self::one();
let mask: Self = mask << (size_of::<Self>() - index).into();
self = self & !mask.clone();
return Ok(Bit(self & mask != Self::zero()));
} else {
let mask: Self = Self::one();
let mask: Self = mask << (size_of::<Self>() - index).into();
self = self | mask.clone();
return Ok(Bit(self & mask != Self::zero()));
}
}
}
impl From<Bits> for usize {
fn from(bits_to_convert: Bits) -> Self {
if bits_to_convert.0.len() > size_of::<usize>() {
let shortened_bits: Bits = Bits(
bits_to_convert.0
[(bits_to_convert.0.len() - size_of::<usize>())..bits_to_convert.0.len()]
.to_vec(),
);
usize::from(shortened_bits)
} else {
let mut new_usize: usize = Default::default();
for (index, current_bit) in bits_to_convert.0.clone().into_iter().enumerate() {
new_usize.set_bit(index, Bit(current_bit)).unwrap();
}
if bits_to_convert.0.len() < size_of::<usize>() {
new_usize = new_usize >> size_of::<usize>() - bits_to_convert.0.len();
}
new_usize
}
}
}
impl From<Bits> for u8 {
fn from(bits_to_convert: Bits) -> Self {
if bits_to_convert.0.len() > size_of::<u8>() {
let shortened_bits: Bits = Bits(
bits_to_convert.0
[(bits_to_convert.0.len() - size_of::<u8>())..bits_to_convert.0.len()]
.to_vec(),
);
u8::from(shortened_bits)
} else {
let mut new_u8: u8 = Default::default();
for (index, current_bit) in bits_to_convert.0.clone().into_iter().enumerate() {
new_u8.set_bit(index, Bit(current_bit)).unwrap();
}
if bits_to_convert.0.len() < size_of::<u8>() {
new_u8 = new_u8 >> size_of::<u8>() - bits_to_convert.0.len();
}
new_u8
}
}
}
这个错误相当大,但是我会挑出一个有问题的部分并突出显示:
note: the following trait bounds were not satisfied:
`&mut u8: From<usize>`
`&u8: From<usize>`
`u8: From<usize>`
--> srclib.rs:175:11
|
166 | impl<T> BitMan for T
| ------ -
...
175 | + From<usize>
| ^^^^^^^^^^^ unsatisfied trait bound introduced here
当编译器看到new_u8.set_bit(...)
时,它将尝试u8
,&u8
和&mut u8
来匹配trait实现。但是正如您在上面看到的,这些类型中的没有一个实现From<usize>
。如果您为期望的实现显式调用trait方法,使用完全限定语法,您可以更好地看到这一点:
<u8 as BitMan>::set_bit(new_u8, ...)
error[E0277]: the trait bound `u8: From<usize>` is not satisfied
--> src/lib.rs:87:17
|
87 | <u8 as BitMan>::set_bit(new_u8, index, Bit(current_bit)).unwrap();
| ^^^^^^^^^^^^^^^^^^^^^^^ the trait `From<usize>` is not implemented for `u8`
|
= help: the following implementations were found:
<u8 as From<Bits>>
<u8 as From<NonZeroU8>>
<u8 as From<bool>>
<f32 as From<i16>>
and 73 others
根据你的措辞,我猜你假设它会为u8
实现,但是usize
可以表示比u8
适合的更多的值,这样的转换将是有损的。TryFrom
特性用于可能失败的转换。无论如何,您可能应该使用T: Shl<usize, Output = Self>
,并删除.into()
s和From
约束。这个编译。
你可能也应该改变它改变self
可变引用。因为你是按值传递self
,现在它只是复制usize
/u8
,在函数内修改,然后不做任何事情;它不会修改原始值。