Downcast: no method named `downcast_ref` found for type

Hello,

regarding my last thread I decided to stop and refactor my code. My approach now is to downcast the trait object. Never did this before.
This time there is no gist because downcast is not available on playground.

toml

[package]
name = "k"
version = "0.1.0"
authors = ["xxx"]
edition = "2018"

[dependencies]
downcast = "*"

error:

error[E0599]: no method named `downcast_ref` found for type `std::boxed::Box<(dyn Component + std::marker::Send + 'static)>` in the current scope
  --> src/main.rs:30:16
   |
30 |         (*component).downcast_ref::<XComponent>().unwrap().machine.as_ref().unwrap()
   |                      ^^^^^^^^^^^^ method not found in `std::boxed::Box<(dyn Component + std::marker::Send + 'static)>`
   |
   = help: items from traits can only be used if the trait is implemented and in scope
   = note: the following trait defines an item `downcast_ref`, perhaps you need to implement it:
           candidate #1: `downcast::Downcast`

What is the problem here? Is it the "Send + 'static"?

code:

#[macro_use]
extern crate downcast;
use downcast::Any;

fn main()
{
}

pub trait Component: Any {
	fn get_name(&self) -> String;
}

downcast!(dyn Component);

struct X;

pub struct XComponent {
	machine: Option<X>,
}

impl Component for XComponent {
	fn get_name(&self) -> String {
		"X".into()
	}
}

fn get_state<'a>(component: &Box<dyn Component + Send + 'static>) -> &'a X
{
	(*component).downcast_ref::<XComponent>().unwrap().machine.as_ref().unwrap()
}

The note in the error message tells you what you need to do:

   = help: items from traits can only be used if the trait is implemented and in scope
   = note: the following trait defines an item `downcast_ref`, perhaps you need to implement it:
           candidate #1: `downcast::Downcast`

You can't use methods from the Downcast trait unless that trait is in scope. Add use downcast::Downcast to your file.

2 Likes

Thanks. Is it really so easy? I added the use downcast::Downcast; to the top of my file. But it does not work. It now says

warning: unused import: `downcast::Downcast`
 --> src/main.rs:5:5
  |
5 | use downcast::Downcast;
  |     ^^^^^^^^^^^^^^^^^^
  |
  = note: `#[warn(unused_imports)]` on by default

and the other error remains. I feel stupid :frowning:

Ah, you might have been correct that your + Send + 'static bounds are the issue, then. I'm not familiar enough with downcast to suggest how to fix that part :frowning:

1 Like

This example shows that downcast! macro receives the trait itself and not the trait object. What if you replace downcast!(dyn Component) with downcast!(Component)?

1 Like

Hi cerberuser,

thanks. With your suggestion I get the same warning twice, but there is no difference, E0599 remains.

warning: trait objects without an explicit `dyn` are deprecated
  --> src/main.rs:11:11
   |
11 | downcast!(Component);
   |           ^^^^^^^^^ help: use `dyn`: `dyn Component`
   |
   = note: `#[warn(bare_trait_objects)]` on by default

warning: trait objects without an explicit `dyn` are deprecated
  --> src/main.rs:11:11
   |
11 | downcast!(Component);
   |           ^^^^^^^^^ help: use `dyn`: `dyn Component`

This is indeed caused by Send, 'static is alright. I'll ask the author of the crate about the issue.

Thanks

Could anyone help me getting this downcast to work? I switched to downcast_rs but get another problem.

#[macro_use]
extern crate downcast_rs;
use std::any::Any;
use downcast_rs::DowncastSync;

pub trait Component: DowncastSync {
	fn get_name(&self) -> String;
}

impl_downcast!(sync Component);

#[derive(Clone)]
struct X;

#[derive(Clone)]
pub struct XComponent {
	machine: Option<X>,
}

impl Component for XComponent {
	fn get_name(&self) -> String {
		"X".into()
	}
}

fn main()
{
    let x = Box::new(XComponent{machine: Some(X{})});
    let state0 = get_state(&x);
}

fn get_state<'a>(component: &Box<dyn Component + Send + 'static>) -> X
{
    let x = component.clone();
	let x: Result<Box<XComponent>, _> = (*x).downcast();
	x.ok().unwrap().machine.unwrap()
}

2 errors

error[E0308]: mismatched types
  --> src/main.rs:29:28
   |
29 |     let state0 = get_state(&x);
   |                            ^^ expected trait Component, found struct `XComponent`
   |
   = note: expected type `&std::boxed::Box<(dyn Component + std::marker::Send + 'static)>`
              found type `&std::boxed::Box<XComponent>`

error[E0599]: no method named `downcast` found for type `std::boxed::Box<dyn Component + std::marker::Send>` in the current scope
  --> src/main.rs:35:43
   |
35 |     let x: Result<Box<XComponent>, _> = (*x).downcast();
   |                                              ^^^^^^^^ method not found in `std::boxed::Box<dyn Component + std::marker::Send>`