2

I've been trying many things from nested loops and sequential duplicated nested loops to this:

pub fn values_to_references<'a>(values_vector: Vec<String>) -> Vec<&'a gtk::ToValue> {
    values_vector
        .into_iter()
        .map(| item: String | &item.to_value() as &ToValue)
        .collect()
}

But whatever I try, the compiler always tells me that the lifetime of item is too short:

borrowed value must be valid for the lifetime 'a as defined on the body at 87:89...
borrowed value does not live long enough (does not live long enough)

I need to convert to those references in order to add Strings to a gtk::TreeModel (gtk::TreeStore), which will balk at anything other than that it seems. All examples I could find use references to static strings, which are known at compile time. That's not very useful. My strings come from a JSON file and cannot be known at compile time.

I want to be able to do the following with the gtk::TreeModel:

model.insert_with_values(
    None,
    None,
    &[0, 1, 2, 3],
    to_value_items.as_slice());

How can I achieve this?

Example Code

More code from my attempts to add stuff to a gtk::TreeStore or gtk::TreeModel:

pub fn add_to_tree_store(tree_store: &TreeStore, row: Vec<String>) {
    tree_store.insert_with_values(
        None,
        None,
        &[0, 1, 2, 3],
        VocTreeView::strings_to_ampersand_str(row)
            .iter()
            .map(|x| x as &ToValue)
            .collect());
}

pub fn strings_to_ampersand_str<'res_ref>(values_vector: Vec<String>) -> Vec<&'res_ref str> {
    let append_values: Vec<_> = values_vector.iter().map(|x| &x[..]).collect();
    append_values
}

This fails at collect():

a collection of type `&[&gtk::ToValue]` cannot be built from an iterator over elements of type `&gtk::ToValue` [E0277]

the trait bound `&[&gtk::ToValue]: std::iter::FromIterator<&gtk::ToValue>` is not satisfied (the trait `std::iter::FromIterator<&gtk::ToValue>` is not implemented for `&[&gtk::ToValue]`) [E0277]

Seems the same problem is again biting me.

Example Code 2

pub fn add_to_tree_store(tree_store: &TreeStore, row: Vec<String>) {
    tree_store.insert_with_values(
        None,
        None,
        &[0, 1, 2, 3],
        VocTreeView::values_to_references(&row)
            .iter()
            .map(|x| x as &gtk::ToValue)
            .collect());
}

pub fn values_to_references(values_vector: &[String]) -> Vec<&gtk::ToValue> {
    values_vector
        .into_iter()
        .map(|item| item as &gtk::ToValue)
        .collect()
}

This runs into an error at x inside map and collect as well:

At x:

required for the cast to the object type `gtk::ToValue` [E0277]

required because of the requirements on the impl of `gtk::ToValue` for `&gtk::ToValue` [E0277]

required because of the requirements on the impl of `glib::value::SetValue` for `&gtk::ToValue` [E0277]

the trait bound `gtk::ToValue: glib::value::SetValue` is not satisfied (the trait `glib::value::SetValue` is not implemented for `gtk::ToValue`) [E0277]

At collect:

a collection of type `&[&gtk::ToValue]` cannot be built from an iterator over elements of type `&gtk::ToValue` [E0277]

the trait bound `&[&gtk::ToValue]: std::iter::FromIterator<&gtk::ToValue>` is not satisfied (the trait `std::iter::FromIterator<&gtk::ToValue>` is not implemented for `&[&gtk::ToValue]`) [E0277]
Zelphir Kaltstahl
  • 5,722
  • 10
  • 57
  • 86
  • Don't have time to play with the compiler, but I think at the very least you need to assign lifetime 'a to parameter values_vector. Idea is to say the input and result have the same lifetime. It may also be required to assert the lifetime of the elements of values_vector, but I don't think so. I would also expect there to be lifetime issues when you go to use the result as if the TreeStore is holding references, you'll have to assert the lifetime on it as well, but I don't know what TreeStore is doing, etc. In general I'm surprised you would need to do this... – Zalman Stern Oct 08 '17 at 01:06
  • You will need to convert your `Vec` into a `Vec<&ToValue>`, something [like this](https://play.rust-lang.org/?gist=37d1b695aa30966391e1781e151361f3&version=stable). See [this question which was asked immediately before yours](https://stackoverflow.com/q/46624591/155423) and has the exact same problem, albeit for a different library. – Shepmaster Oct 08 '17 at 01:50
  • @ZalmanStern Yes, I am trying to do that, still struggling with "where to put that lifetime declaration?" – Zelphir Kaltstahl Oct 08 '17 at 09:50
  • @Shepmaster I do not understand how I can apply your answer to the other question to my case. I'll add more code to my question. – Zelphir Kaltstahl Oct 08 '17 at 11:16
  • 1
    @Zelphir I don't understand why you are trying to convert the items twice. [Just do it once](https://play.rust-lang.org/?gist=d322872a172344d8dc07f5b330711c1b&version=stable). – Shepmaster Oct 08 '17 at 13:17
  • @Shepmaster That's it, it works now. For some reason I build up the believe, that I could only translate `&str` to `&ToValue` and not `String`. That's why I tried it that way. Thanks for your help! If you make this an answer, I'll accept it. – Zelphir Kaltstahl Oct 08 '17 at 13:50
  • *If you make this an answer, I'll accept it* — it's not possible to answer duplicate questions because they've already been answered... by the duplicate. You can pop over to the duplicates and give the authors of those answers upvotes though. – Shepmaster Oct 08 '17 at 13:59

0 Answers0