为什么本地类型的IntoIdeator的实现与核心机箱中的实现发生冲突



我可以为自定义类型实现IntoIterator,但当IntoIterator绑定到自定义特征时,我无法实现该特征。

下面的代码显示了问题。当为自定义类型(FakeReader(实现IntoIterator时,一切都很好。然而,当我尝试为该类型实现BmpReader时,编译器似乎会获取IntoIterator的内部impl,并要求我的自定义类型为Iterator

use core::iter::Iterator;
/// The trait that I'm designing
pub trait BmpReader : IntoIterator {
const INTERNAL_BUFFER_SIZE: usize;
}
// Uncomment to see error
//impl BmpReader for FakeReader {
//     const INTERNAL_BUFFER_SIZE: usize = 20;
//}
impl<'a> IntoIterator for &'a FakeReader {
type Item = &'a [u8];
type IntoIter = FakeReaderIterator<'a>;
fn into_iter(self) -> Self::IntoIter {
Self::IntoIter{
reader: &self,
index: 0,
}
}
}
struct FakeReader {
buffer: [u8; 20],
}
pub struct FakeReaderIterator<'a> {
reader: &'a FakeReader,
index: usize
}
impl<'a> Iterator for FakeReaderIterator<'a> {
type Item = &'a [u8];
fn next(&mut self) -> Option<Self::Item> {
if self.index == self.reader.buffer.len() {
return None;
}
let result = &self.reader.buffer[self.index..self.index+1];
self.index += 1;
Some(result)
}
}
fn main() {
let mut reader = FakeReader {
buffer: [0u8; 20]
};
let _= reader.buffer.iter_mut().enumerate().map(|(i,v)| *v = i as u8).count();
for i in &reader {
println!("{:?}", i)
}
}

取消对有问题的impl块的注释会导致以下错误:

error[E0277]: `FakeReader` is not an iterator
--> src/main.rs:9:6
|
9 | impl BmpReader for FakeReader {
|      ^^^^^^^^^ `FakeReader` is not an iterator
|
= help: the trait `Iterator` is not implemented for `FakeReader`
= help: the trait `IntoIterator` is implemented for `&'a FakeReader`
= note: required because of the requirements on the impl of `IntoIterator` for `FakeReader`
note: required by a bound in `BmpReader`
--> src/main.rs:4:23
|
4 | pub trait BmpReader : IntoIterator {
|                       ^^^^^^^^^^^^ required by this bound in `BmpReader`

游乐场连接

当创建具有特征绑定的特征时,您绑定了Self来实现该特征,但在本例中,&FakeReader实现了IntoIterator,因此您不能为FakeReader实现BmpReader,但可以为&FakeReader实现。你可以写

impl<'a> BmpReader for &'a FakeReader {
const INTERNAL_BUFFER_SIZE: usize = 20;
}

访问常量意味着写入

let size = <&FakeReader>::INTERNAL_BUFFER_SIZE;

并在BmpReader:上创建一个通用函数

fn foo<T: BmpReader>(a: T) {
let _size = T::INTERNAL_BUFFER_SIZE;
let _iter = a.into_iter();
}
fn main() {
let reader = FakeReader {
buffer: [0u8; 20]
};
test(&reader);
}

另一种解决方案是绑定&Self以实现特性的IntoIterator

pub trait BmpReader
where for <'a> &'a Self: IntoIterator
{
const INTERNAL_BUFFER_SIZE: usize;
}
impl BmpReader for FakeReader {
const INTERNAL_BUFFER_SIZE: usize = 20;
}

(for<'a> &'a Self: IntoIterator是@Chayim Friedman的建议(

您现在可以直接在FakeReader:上访问常量

let size = FakeReader::INTERNAL_BUFFER_SIZE;

但是在BmpReader上创建泛型函数需要指定绑定:

fn foo<T: BmpReader>(a: &T)
where for <'a> &'a T: IntoIterator
{
let _size = T::INTERNAL_BUFFER_SIZE;
let _iter = a.into_iter();
}
fn main() {
let reader = FakeReader {
buffer: [0u8; 20]
};
foo(&reader);
}

Bot解决方案是有效的,请选择最适合您需求的解决方案,并使代码最具可读性/可维护性。

最新更新