为什么我必须明确地转换为约束类型?

时间:2017-09-05 00:04:44

标签: rust

为什么下面的注释掉的bar代码没有编译,即使foobaz也这样做了?

use std::any::Any;
use std::fmt::Display;

// `value` implements `Clone`, so I can call `.clone()`.
fn foo<T: Display + Clone>(value: &T) {
    println!("{}", value.clone());
}

// `value` implements `Any`, so I should be able to call `.downcast_ref`...
// But this doesn't compile!
//
// fn bar<T: Display + Any>(value: &T) {
//     println!("{}", value.downcast_ref::<i32>());
// }

// For some reason I have to do an explicit cast to `&Any`...
fn baz<T: Display + Any>(value: &T) {
    let value = value as &Any;
    println!("{}", value.downcast_ref::<i32>().unwrap());
}

fn main() {
    foo(&7);
    // bar(&8);
    baz(&9);
}

尝试编译bar会产生以下编译器错误:

error[E0599]: no method named `downcast_ref` found for type `&T` in the current scope
  --> src/main.rs:13:30
   |
13 |         println!("{}", value.downcast_ref::<i32>());
   |                              ^^^^^^^^^^^^

我已经详细说明了value必须实施Any的约束,那为什么我必须做一个明确的演员?

1 个答案:

答案 0 :(得分:9)

那是因为downcast_ref不是特质本身的一部分。如果我们查看特征的定义in the documentation

pub trait Any: 'static {
    fn get_type_id(&self) -> TypeId;
}

我们可以看到downcast_ref不存在。只有定义为特征成员的方法才能在实现该特征的类型上使用。

相反,downcast_ref位于impl Any + 'static 1 中。由于该方法采用&self,因此该方法仅适用于&(Any + 'static)类型的值(&Any,未指定生命周期等同于&(Any + 'static))。 &Any&T(其中T是类型参数)不是同一类型; &Any是一个特征对象(它是一个胖指针),而&T只是一个普通的引用(它是一个瘦指针)。

1 它也在impl Any + 'static + Send块中定义,因此该方法也适用于&(Any + 'static + Send)类型的值。