为什么AsRef不能用作参数类型注释,但可以与泛型声明一起使用?

时间:2019-01-28 08:13:09

标签: rust

playground

use std::path::Path;

// fn f1(p: AsRef<Path>) {
//     println!("{}", p.as_ref().display());
// }

fn f2<P: AsRef<Path>>(p: P) {
    println!("{}", p.as_ref().display());
}

fn main() {
    f2("/tmp/test.jpg");
}

编译器会抱怨f1未知Path的大小

1 个答案:

答案 0 :(得分:4)

AsRef是一个特征,而不是一个类型。您对f1()的定义代替了类型。此旧式语法是dyn AsRef<Path>的缩写,表示实现特征AsRef<Path>的任意类型,并在运行时进行动态分配。实现特征的任意类型的大小在编译时显然是未知的,因此您只能在指针后面使用特征对象,例如&dyn AsRef<Path>Box<dyn AsRef<Path>>。编译器不会抱怨Path的大小未知,而是会抱怨trait对象的大小未知。

另一方面,泛型类型的特质界限要求特征,而不是类型。 P还是实现AsRef<Path>的任意类型,但是此任意类型需要在编译时就知道,并且编译器会为实际使用的每种类型发出f2()的新编译版本。这样,在编译时就可以知道每种类型的大小。