Я пытаюсь реализовать читатель, который мог бы извлечь значения из разных типов из файла. Существует структура File
, которая представляет файловый ресурс (и методы для доступа к его содержимому), и признак Reader
, который позволяет извлекать значения на основе результирующего типа. Реализация (фиктивная) выглядит следующим образом ( детская площадка ):
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
(например, удаляя Reader<bool>
), код скомпилируется без проблем ( plays ).
Почему компилятор не может узнать, что он должен использовать реализацию Reader<u32>
для инициализации count
? Что я должен изменить?
Я нашел обходной путь, но мне все еще интересно понять, почему компилятор не может понять это автоматически:
let count: u32 = (self as &mut Reader<u32>).read()?;
<Ч />
О проблеме сообщалось как rust-lang / rust # 54344 .