Hello! I have a function in my wit which takes a list of struct as a parameter.
interface michel-api {
...
new-documents-for-index: func(index: string, documents: list<document>)
}
The problem is: my document list is computed, I cannot inline it. And I have lifetime issues..
let docs: Vec<DocumentParam<'a>> = files
.iter()
.map(|it| DocumentParam {
identifier: &it.id.to_string(),
fields: &[
FieldParam {
name: "filename",
value: Text(&it.filename.to_string()),
},
FieldParam {
name: "path",
value: Text(&it.path.to_string_lossy()),
},
],
})
.collect();
I have this error : cannot return value referencing temporary value [E0515] returns a value referencing data owned by the current function
The files
is a Vec<FileDocument> where FileDocument is an owned object of mine
It just doesn't seem possible to give this list
Well, after searching even further, I don’t think this is possible. I know this is more a Rust problem, but I can’t find any solution to this. I can only wait for the issue speaking about disabling borrowed types
And I guess that the fact that I don't get any answers means it's not possible :sob:
Something like this, perhaps?
let files = files.iter().map(|it| {
(it.id.to_string(), it.filename.to_string(), it.path.to_string_lossy())
}).collect::<Vec<_>>();
let docs: Vec<DocumentParam<'_>> = files
.iter()
.map(|(id, filename, path)| DocumentParam {
identifier: id.as_str(),
fields: &[
FieldParam {
name: "filename",
value: Text(filename.as_str()),
},
FieldParam {
name: "path",
value: Text(path.as_str()),
},
],
})
.collect();
err, actually:
let files = files
.iter()
.map(|it| {
(
it.id.to_string(),
it.filename.to_string(),
it.path.to_string_lossy(),
)
})
.collect::<Vec<_>>();
let files = files
.iter()
.map(|(id, filename, path)| {
(
id,
[
FieldParam {
name: "filename",
value: Text(filename.as_str()),
},
FieldParam {
name: "path",
value: Text(path.as_str()),
},
],
)
})
.collect::<Vec<_>>();
let docs: Vec<DocumentParam<'_>> = files
.iter()
.map(|(id, fields)| DocumentParam {
identifier: id.as_str(),
fields,
})
.collect();
Wow, it seems like it is working... i totally did not understand how splitting this in three variables would help with the ownership in the function, but I really thank you for your time, it really means a lot
Storing the stings and arrays in named variables in the outer scope instead of temporaries in the inner scopes of the closures ensures that the references don't outlive their referents, which is what is needed to make the compiler happy. The first Vec
stores the strings, the second Vec
stores the arrays which refer to the strings in the first Vec
, and the third Vec
stores the references to the arrays in the second Vec
, plus the id
strings stored in the first Vec
.
You could technically do this more concisely if you venture into the world of self-referential structs using e.g. ouroboros
but I wouldn't recommend that for simple situations like this.
Last updated: Dec 23 2024 at 13:07 UTC