The title is not that great so I'll explain more in details here.
I am working on the v1 of Tera, a template engine.
One of the feature is Function: in short a Rust function we can call from a template. It can be something simple like getting the current date to something operating on some context like: Overview | Zola
In v1, Function
is becoming the following trait:
pub trait Function: Sync + Send {
fn call(&self, args: &HashMap<String, Value>) -> Result<Value>;
}
The main perf bottleneck of Zola are those get_page
/get_section
that need access to the full context and which needed to be serialized. Ok when you have 200 pages, less when you have 100k.
I was hoping to use the fact that these are now traits to use references instead of cloning. I made an example of how it would ideally look like: https://github.com/Keats/tera/blob/lifetime-issue/examples/borrowed_trait_context/main.rs
This gets a lifetime error on https://github.com/Keats/tera/blob/lifetime-issue/examples/borrowed_trait_context/main.rs#L53 which is solved by making the reference 'site
which in turns errors with:
error[E0597]: `site` does not live long enough
--> examples/borrowed_trait_context/main.rs:66:5
|
66 | site.register_tera_fns();
| ^^^^ borrowed value does not live long enough
...
69 | }
| -
| |
| `site` dropped here while still borrowed
| borrow might be used here, when `site` is dropped and runs the destructor for type `Site<'_>`
error[E0499]: cannot borrow `site` as mutable more than once at a time
--> examples/borrowed_trait_context/main.rs:67:13
|
66 | site.register_tera_fns();
| ---- first mutable borrow occurs here
67 | rebuild(&mut site);
| ^^^^^^^^^
| |
| second mutable borrow occurs here
| first borrow later used here
All of those make sense but now I'm stuck. I do not want to borrow self.pages
mutably but I have to to register the function on the Tera instance so I do need the mut
.
It might be a case of XY problem and me trying to pigeonhole my original idea onto it.
Does anyone have solutions/alternative ideas to make it work while keeping references? Writing this made me think of maybe looking into crates for self-references from the user side?
In the case of Zola in particular, references will always be valid as Tera functions are re-registered on change and I am guessing for most other usecases other than Zola, cloning will be just fine perf wise since it will happen once.