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

时间:2018-09-03 16:56:58

标签: rust traits

我正在尝试实现一个读取器,该读取器能够从文件中提取不同类型的值。有一个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()?;

问题已报告为rust-lang/rust#54344

1 个答案:

答案 0 :(得分:2)

没有充分的理由使编译器无法弄清楚应该为df<-as.data.frame(m) 使用from pyspark.sql.functions import split, col df = spark.createDataFrame([ ("file1.A.txt",), ("file2.A.txt",), ("file3.B.txt",), ("file4.A.txt",), ("file5.B.txt",) ], ["filenames"] ) df.withColumn('a_or_b', split(col("filenames"), "\.")[1]).show() +-----------+------+ | filenames|a_or_b| +-----------+------+ |file1.A.txt| A| |file2.A.txt| A| |file3.B.txt| B| |file4.A.txt| A| |file5.B.txt| B| +-----------+------+ 实现。这是一个编译器错误,因为Reader<u32>与该行上let count: u32 = ...的使用方式无关。一个T调用的返回类型似乎正在确定另一个self.read()调用的返回类型!

此外,如果不是bug,那么.read().read()之外的Reader<T>的实现也不会有什么区别,但正如@rodrigo指出的那样,则Reader<u8>实现的存在会触发此错误。

请注意,Reader<u32>(与下面显示的Reader<bool>等效)与错误无关,因为直接获得?时仍然会收到错误:

match