简体   繁体   English

为Vec添加实现后,为什么Rust编译器不使用预期的trait实现 <T> ?

[英]Why does the Rust compiler not use the expected trait implementation once I add an implementation for Vec<T>?

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. 有一个File结构表示文件资源(以及访问其内容的方法),还有一个Reader特性,可以根据结果类型提取值。 The (dummy) implementation looks like this ( playground ): (虚拟)实现看起来像这样( 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. 在我添加Reader<Vec<T>>实现之前,一切正常。 Vectors are stored in the file as a u32 indicating the number of elements followed by the element's representation. 向量作为u32存储在文件中,表示元素表示后面的元素数。 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> . 即使我指定File实现Reader<T>Reader<u32> ,它似乎仍然停留在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 ). 更奇怪的是,如果我只保留2个Reader特性的实现(例如删除Reader<bool> ),代码编译没有任何问题( playground )。

Why can't the compiler find out it should use the Reader<u32> implementation for count initialization? 为什么编译器不能发现它应该使用Reader<u32>实现进行count初始化? 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 . 据报道,问题是锈蚀/锈病#54344

There's no good reason why the compiler can't figure out that it should use the Reader<u32> implementation for let count: u32 = ... . 编译器无法弄清楚它应该使用Reader<u32>实现来let count: u32 = ... It's a compiler bug because T has no connection to how self.read() is being used on that line. 这是一个编译器错误,因为Tself.read()在该行上的使用方式没有关系。 The return type of one .read() call seems to be determining the return type of another .read() call when it shouldn't be! 一个.read()调用的返回类型似乎是在不应该确定另一个.read()调用的返回类型时!

Additionally, if it were not a bug, then it wouldn't make a difference what implementations of Reader<T> there are other than Reader<u8> and Reader<u32> , but as @rodrigo pointed out, the presence of a Reader<bool> implementation triggers this error. 另外,如果它不是一个bug,那么除了Reader<u8>Reader<u32> u32 Reader<u32>Reader<T>实现没有什么区别,但正如@rodrigo指出的那样, Reader<bool>的存在Reader<bool>实现会触发此错误。

Note that the ? 请注意? (which is equivalent to the match shown below) has nothing to do with the bug, since you still get the error when the Result<u32> is gotten directly: (这相当于下面显示的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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM