[英]Why does the Rust compiler not use the expected trait implementation once I add an implementation for Vec<T>?
我正在嘗試實現一個能夠從文件中提取不同類型的值的閱讀器。 有一個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
特性的實現(例如刪除Reader<bool>
),代碼編譯沒有任何問題( playground )。
為什么編譯器不能發現它應該使用Reader<u32>
實現進行count
初始化? 我應該改變什么?
我找到了一個解決方法,但我仍然有興趣理解為什么編譯器無法自動解決它:
let count: u32 = (self as &mut Reader<u32>).read()?;
據報道,問題是銹蝕/銹病#54344 。
編譯器無法弄清楚它應該使用Reader<u32>
實現來let count: u32 = ...
這是一個編譯器錯誤,因為T
與self.read()
在該行上的使用方式沒有關系。 一個.read()
調用的返回類型似乎是在不應該確定另一個.read()
調用的返回類型時!
另外,如果它不是一個bug,那么除了Reader<u8>
和Reader<u32>
u32 Reader<u32>
, Reader<T>
實現沒有什么區別,但正如@rodrigo指出的那樣, Reader<bool>
的存在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))
}
};
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.