我正在尝试实现一个能够从文件中提取不同类型的值的阅读器.有一个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();
}
Run Code Online (Sandbox Code Playgroud)
一切顺利,直到我添加了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`
Run Code Online (Sandbox Code Playgroud)
尽管我指定了File
同时实现了Reader<T>
和Reader<u32>
,它似乎被卡住Reader<T>
.
更奇怪的是,如果我只保留2个特征的实现Reader
(Reader<bool>
例如删除),代码编译没有任何问题(playground).
为什么编译器不能发现它应该使用Reader<u32>
实现进行count
初始化?我应该改变什么?
我找到了一个解决方法,但我仍然有兴趣理解为什么编译器无法自动解决它:
let count: u32 = (self as &mut Reader<u32>).read()?;
Run Code Online (Sandbox Code Playgroud)
据报道,问题是锈蚀/锈病#54344.
编译器没有充分的理由无法弄清楚它应该使用Reader<u32>
的实现let count: u32 = ...
。这是一个编译器错误,因为与该行的使用T
方式无关。self.read()
一个.read()
调用的返回类型似乎决定了另一个.read()
调用的返回类型,但事实并非如此!
Reader<T>
此外,如果这不是一个错误,那么除了Reader<u8>
和之外还有什么实现不会产生任何影响Reader<u32>
,但正如 @rodrigo 指出的那样,实现的存在Reader<bool>
会触发此错误。
请注意,?
(相当于match
下图所示)与该错误无关,因为Result<u32>
直接获取时仍然会出现错误:
let count_result: Result<u32> = self.read(); // error happens here
let count: u32 = match count_result {
std::result::Result::Ok(val) => val,
std::result::Result::Err(err) => {
return std::result::Result::Err(std::convert::From::from(err))
}
};
Run Code Online (Sandbox Code Playgroud)
归档时间: |
|
查看次数: |
245 次 |
最近记录: |