结构方法类型推断

Struct method type inference

鉴于以下情况:

use std::old_io::{BufferedReader, File};

struct Journal<T> where T: Buffer {
    file: T,
}

impl<T: Buffer> Iterator for Journal<T> {
    type Item = String;

    fn next(&mut self) -> Option<String> {
        match self.file.read_line() {
            Ok(line) => Some(line.to_string()),
            Err(_) => None,
        }
    }
}

fn main() {
    let path = Path::new("/tmp/allocator-journal.txt");
    let mut file = BufferedReader::new(File::open(&path));

    let journal = Journal {file: file};
    for line in journal {
        print!("{}", line);
    }
}

我想将文件打开逻辑移动到 Journal 上的 new 方法中。由于 unable to infer enough type information about '_'; type annotations required [E0282],以下编译失败:

use std::old_io::{BufferedReader, File, IoResult};

struct Journal<T> where T: Buffer {
    file: T,
}

impl<T: Buffer> Journal<T> {
    fn new() -> Journal<BufferedReader<IoResult<File>>> {
        let path = Path::new("/tmp/allocator-journal.txt");
        let mut file = BufferedReader::new(File::open(&path));
        Journal {file: file}
    }
}

impl<T: Buffer> Iterator for Journal<T> {
    type Item = String;

    fn next(&mut self) -> Option<String> {
        match self.file.read_line() {
            Ok(line) => Some(line.to_string()),
            Err(_) => None,
        }
    }
}

fn main() {
    let journal = Journal::new();
    for line in journal {
        print!("{}", line);
    }
}

向变量绑定或方法调用 (Journal::new::<Journal<BufferedReader<etc..>>>) 添加类型提示都无法解决问题。

为什么无法推断类型? Journal::new 的签名是显式的,对吧?

顺便说一句,为什么 Journal::new() 的 return 类型不能是 Journal<T> where T = Buffer?

您正在混合泛型和非泛型(具体?)的世界。这是解决方法:

impl Journal<BufferedReader<IoResult<File>>> {
    fn new() -> Journal<BufferedReader<IoResult<File>>> {
        let path = Path::new("/tmp/allocator-journal.txt");
        let mut file = BufferedReader::new(File::open(&path));
        Journal {file: file}
    }
}

注意此处缺少 T。重点是您决定 T 必须是什么类型 (BufferedReader<IoResult<File>>),因此不需要类型变量。

通过 具有 类型变量,编译器试图找出 T 应该是什么。但是,您不会在任何地方使用 T,因此它没有任何意义,并且您会收到一条错误消息。

这提出了一个问题:为什么要有泛型?您实际上并没有将它们用于任何事情,因此您不妨将 T 替换为BufferedReader<IoResult<File>>无处不在。