Why doesn't the commented-out bar
code below compile, even though foo
and baz
do?
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);
}
Trying to compile bar
yields the following compiler error:
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>());
| ^^^^^^^^^^^^
I already spelled out the constraint that value
must implement Any
so why do I have to do an explicit cast?
That's because downcast_ref
is not part of the trait itself. If we look at the trait's definition in the documentation:
pub trait Any: 'static {
fn get_type_id(&self) -> TypeId;
}
we can see that downcast_ref
is not there. Only methods defined as members of a trait are made available on types that implements that trait.
Rather, downcast_ref
is in an impl Any + 'static
block1. Since the method takes &self
, it means the method is only available on values of type &(Any + 'static)
(&Any
with no lifetime specified is equivalent to &(Any + 'static)
). &Any
and &T
(where T
is a type parameter) are not the same type; &Any
is a trait object (which is a fat pointer), while &T
is just a normal reference (which is a thin pointer).
1 It's also defined in an impl Any + 'static + Send
block, so the method is also available on values of type &(Any + 'static + Send)
.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With