0

I'm solving a fairly classic "matchmaking" problem, commonly solved as an assignment-type problem in Operations Research. I have the following structs represent a Person and a Compatibility between two people.

struct Person {
    name: String,
}

struct Compatibility<'a> {
    lhs: &'a Person,
    rhs: &'a Person,
    compatibility_score: f64,
}

This is fine. Compatibilities don't own the persons they represent in their fields and as such just store references to them, but they must live at least as long as them, hence the lifetime param. I can easily create some objects of both types like this:

fn create_model() {
    let persons = vec![
        Person{name: "Katie".to_string()},
        Person{name: "Helen".to_string()},
    ];
    let compatibilities = vec![
        Compatibility{lhs: &persons[0], rhs: &persons[1], compatibility_score: 50.0},
    ];
}

I'm trying to introduce a third struct, Model, which will own a vector of Person as well as a vector of Compatibility, and as such represent the data model which the problem will be run on.

pub struct Model {
    persons: Vec<Person>,
    compatibilities: Vec<Compatibility>,
}

Now this won't compile because Compatibility speficies a lifetime parameter, and so it seems that even though Model will own a vector of Compatibility, it still needs to specify a lifetime parameter, or otherwise we'll end up with error[E0106]: missing lifetime specifier. This makes some kind of sense to me - I mean, if an instance of Compatibility needs to live for at least as long as the Person instances it references, then the compiler needs to ensure that anything which owns a compatibility also lives as long. So I add that in like so:

pub struct Model<'a> {
    persons: Vec<Person>,
    compatibilities: Vec<Compatibility<'a>>,
}

This is now building. But now how do I actually create a Model? Continuing from the earlier snippet, if I try to do this:

Model {
    persons,
    compatibilities
}

Then the compiler complains that I am moving persons, but it is still being borrowed by compatibilities. The thing is, I know it's still being borrowed by compatibilities, and I'm trying to move both of them into the Model instance. I need to somehow connect the two vectors so the compiler understands they live together.

Code is on playground if you'd like to edit it yourself.

Progman
  • 16,827
  • 6
  • 33
  • 48
Coxy
  • 665
  • 5
  • 13
  • @SCappella thanks for the link - that question is from someone having exactly the same problem as me, yes. I also understand the accepted/most-upvoted answer which explains *why* it can't be done, and the recommendation to "not attempt to put these items in the same structure together". However, I'm still left in a position where I would like this "data model" to be stored somewhere so that the model can be passed around as a single unit encompassing the entire model. It's possible I'll need to research the Rc type, but I'd be interested to hear suggestions towards simpler solutions. – Coxy Apr 13 '20 at 10:16
  • https://play.rust-lang.org/?version=stable&mode=debug&edition=2018&gist=8a20534afbbe80ca5057eddf5d32eea5 – Stargateur Apr 13 '20 at 10:24
  • @Stargateur thanks for giving it a crack. I'll have to decide if going that way, with the model not owning the persons, is going to be the best for my use case or not. Cheers. – Coxy Apr 13 '20 at 11:21

0 Answers0