I'm trying to implement a reader which could be able to extract values from different types from a file. There is a File struct which represents the file resource (and methods to access its content), and a Reader trait which makes it possible to extract values based on the resulting type. The (dummy) implementation looks like this (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();
}
Everything worked until I added the Reader<Vec<T>> implementation. Vectors are stored in the file as a u32 indicating the number of elements followed by the element's representation. The compiler gives the following error:
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`
Even though I specified that File implements both Reader<T> and Reader<u32>, it seems to be stuck on Reader<T>.
What's even more strange is that if I only keep 2 implementations of the Reader trait (removing Reader<bool> for instance), the code compiles without any issue (playground).
Why can't the compiler find out it should use the Reader<u32> implementation for count initialization? What should I change?
I've found a workaround, but I'm still interested in understanding why the compiler can't figure it out automatically:
let count: u32 = (self as &mut Reader<u32>).read()?;
Issue has been reported as rust-lang/rust#54344.