-1

I'm trying to model a dataframe-like structure. I know how use enums here, but I'm exploring how do it similar to C#/Python/etc.

I tried to follow Rust Trait object conversion but things are not working:

use std::any::{Any};
use std::fmt::Debug;

pub trait Value: Any + Sized {
    fn as_any(&self) -> &Any {
        self
    }

    fn as_any_mut(&mut self) -> &mut Any {
        self
    }
}

impl Value for i32 {}

#[derive(Debug)]
struct Frame {
    data: Vec<Box<Any>>,
}

fn make_int(of: Vec<i32>) -> Frame {
    let data = of.into_iter().map(|x| Box::new(x.as_any())).collect();
    Frame {
        data: data,
    }
}

The compiler complains:

error[E0277]: the trait bound `std::vec::Vec<std::boxed::Box<std::any::Any>>: std::iter::FromIterator<std::boxed::Box<&std::any::Any>>` is not satisfied
  --> src/main.rs:40:61
   |
40 |     let data = of.into_iter().map(|x| Box::new(x.as_any())).collect();
   |                                                             ^^^^^^^ a collection of type `std::vec::Vec<std::boxed::Box<std::any::Any>>` cannot be built from an iterator over elements of type `std::boxed::Box<&std::any::Any>`
   |
   = help: the trait `std::iter::FromIterator<std::boxed::Box<&std::any::Any>>` is not implemented for `std::vec::Vec<std::boxed::Box<std::any::Any>>`
mcarton
  • 27,633
  • 5
  • 85
  • 95
mamcx
  • 15,916
  • 26
  • 101
  • 189
  • An *array* is not the same as a *`Vec`*. – Shepmaster Jul 30 '18 at 22:37
  • 1
    Can you explain what you don't understand about the error message? It seems pretty clear to me: `Box` != `Box<&Any>`. – Shepmaster Jul 30 '18 at 22:38
  • Please review how to create a [MCVE] and then [edit] your question to include it. There are numerous types present that have nothing to do with your question, thus it is not **Minimal**. – Shepmaster Jul 30 '18 at 22:40
  • @Shepmaster I understand the errror but not how solve it. If I put Box::new(x.as_any()) why is not matching Vec>? – mamcx Jul 30 '18 at 22:42
  • Yes, you need to provide enough code to reproduce the problem (*Complete*), but that's all you should provide (*Minimal*). If you read the help page for [mcve] all of this is explained. – Shepmaster Jul 30 '18 at 22:44
  • For example, you don't need `Layout` or `DataType` to produce the problem — they aren't relevant whatsoever. – Shepmaster Jul 30 '18 at 22:45
  • @Shepmaster I put there because I have found is common to complain why I'm doing that (ie: not using a static array). Without the context I need to explain that. – mamcx Jul 30 '18 at 22:48

1 Answers1

2

The main problem is with this function:

fn as_any(&self) -> &Any {
    self
}

This means that you can borrow a Value as a &Any, (it converts a &Value into a &Any).

But then, you want to create a Box<Any> from that &Any. That will never work, because &Any is a borrowed value, while Box<Any> is owned.

The easiest solution would be to change the trait to return the boxed value (an owned trait object):

pub trait Value: Any + Sized {
    fn as_boxed_any(&self) -> Box<Any> {
        Box::new(self)
    }
    //The mut variation is not needed
}

Now the make_int function is trivial:

fn make_int(of: Vec<i32>) -> Frame {
    let data = of.into_iter().map(|x| x.as_boxed_any()).collect();
    Frame {
        data: data,
    }
}

UPDATE: Tinkering a bit, I've found that you can create the Vec<Box<Any>> by writing:

fn make_int(of: Vec<i32>) -> Frame {
    let data = of.into_iter().map(|x| Box::new(x) as Box<Any>).collect();
    Frame {
        data: data,
    }
}

If you are writing the trait only for this conversion, you don't actually need it.

rodrigo
  • 94,151
  • 12
  • 143
  • 190
  • This solve the task, but is weird why Box::new(x.as_any()) not get the same effect. – mamcx Jul 30 '18 at 23:51
  • @mamcx: As I commented, that is because `as_any()` borrows the value, and then you want to take ownership of the borrowed result. If you just want to box the any, you can simply write `fn box_any(t: T) -> Box { Box::new(t) }`, and then to build the vector: `of.into_iter().map(box_any).collect()`. – rodrigo Jul 31 '18 at 00:00