我正在尝试实现一个读取器,它可以从文件中提取不同类型的值。有一个表示文件资源(和访问其内容的方法)的File
结构体,以及一个Reader
特质,它使得根据结果类型提取值成为可能。这个(虚拟的)实现看起来像这样(playground):
use std::io::Result;
mod file {
use std::io::Result;
pub struct File {/* ... */}
pub trait Reader<T> {
fn read(&mut self) -> Result<T>;
}
impl Reader<u32> for File {
fn read(&mut self) -> Result<u32> {
// Dummy implementation
Ok(10)
}
}
impl Reader<u8> for File {
fn read(&mut self) -> Result<u8> {
// Dummy implementation
Ok(0)
}
}
impl Reader<bool> for File {
fn read(&mut self) -> Result<bool> {
// Dummy implementation
Ok(false)
}
}
}
use file::{File, Reader};
impl<T: Default> Reader<Vec<T>> for File
where
File: Reader<T> + Reader<u32>,
{
fn read(&mut self) -> Result<Vec<T>> {
let count: u32 = self.read()?;
let mut array: Vec<T> = Vec::with_capacity(count as usize);
for _ in 0..count {
let mut item: T = self.read()?;
array.push(item);
}
Ok(array)
}
}
fn main() {
let mut file = File {};
let _v: Vec<u8> = file.read().unwrap();
}
在我添加Reader<Vec<T>>
实现之前,一切都正常。向量以u32
的形式存储在文件中,表示元素数量,后跟元素的表示。编译器给出以下错误:
error[E0308]: try expression alternatives have incompatible types
--> src/main.rs:41:26
|
41 | let count: u32 = self.read()?;
| ^^^^^^^^^^^^
| |
| expected u32, found type parameter
| help: try wrapping with a success variant: `Ok(self.read()?)`
|
= note: expected type `u32`
found type `T`
尽管我已经指定了
File
实现了Reader<T>
和Reader<u32>
,但它似乎仅使用Reader<T>
。更奇怪的是,如果我只保留2个Reader
trait的实现(例如删除Reader<bool>
),则代码可以编译而无需任何问题(playground)。为什么编译器不能找到应该使用Reader<u32>
实现进行count
初始化?我应该做出什么改变?我已经找到了一种解决方法,但我仍然对为什么编译器无法自动解决此问题感兴趣:let count: u32 = (self as &mut Reader<u32>).read()?;
问题已被报告为 rust-lang/rust#54344。
T
与类型参数中的T
是相同的,不可能有不同的实现具有相同的返回类型。 - Peter Hallread()
返回Result
,处理错误会使代码变得不太易读。 - Tey'