Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Can't pass Content argument to next template #134

Closed
drehren opened this issue Aug 11, 2023 · 5 comments
Closed

Can't pass Content argument to next template #134

drehren opened this issue Aug 11, 2023 · 5 comments
Labels

Comments

@drehren
Copy link

drehren commented Aug 11, 2023

Hi, consider the following two templates

first_template.rs.html:

@use super::next_template_html;

@(content: Content)

@:next_template_html(content)

next_template.rs.html:

@(content: Content)

<div>
  <p>Here be content!</p>
@:content()
</div>

Compilation fails with the following:

error[E0277]: expected a `FnOnce<(&mut &mut W,)>` closure, found `impl FnOnce(&mut W) -> io::Result<()>`
  --> ructe_ex\target\debug\build\ructe_next-a19889e173553d57\out\templates\template_first_template_html.rs:12:42
   |
12 | next_template_html(_ructe_out_.by_ref(), content)?;
   | ------------------                       ^^^^^^^ expected an `FnOnce<(&mut &mut W,)>` closure, found `impl FnOnce(&mut W) -> io::Result<()>`
   | |
   | required by a bound introduced by this call
   |
   = note: expected a closure with arguments `(&mut W,)`
              found a closure with arguments `(&mut &mut W,)`
note: required by a bound in `next_template_html`
  --> ructe_ex\target\debug\build\ructe_next-a19889e173553d57\out\templates\template_next_template_html.rs:9:98
   |
9  |              pub fn next_template_html<W>(#[allow(unused_mut)] mut _ructe_out_: W, content: impl FnOnce(&mut W) -> io::Result<()>) -> io::Result<()>
   |                                                                                                  ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `next_template_html`

For more information about this error, try `rustc --explain E0277`.

Is it possible to pass Content from a template to the next ?

Thanks !

@kaj
Copy link
Owner

kaj commented Aug 14, 2023

Yes, I have also seen some problem related to this in the last release, after merging #125 .

@kornelski , could you take a look at this, could the type for content be written in a better way to solve this?

@kornelski
Copy link
Contributor

The problem here is that by_ref() is required, but it also increases level of indirection. Then every time you nest template calls, the by_ref() adds one more &mut, but the sub-templates should ideally all only require &mut W.

So when calling a template, there needs to be something anti-by-ref that decreases levels of indirection.

This hack works:

@use super::contentcallnext_html;

@(content: Content)

@:contentcallnext_html((|w|content(*w)))

Here's a minimal example:

use std::io::{self, Write};

pub fn contentcall_html<W>(#[allow(unused_mut)] mut _ructe_out_: W, content: impl FnOnce(&mut W) -> io::Result<()>) -> io::Result<()>
where W: Write {
    contentcallnext_html(_ructe_out_.by_ref(), |w| content(*w))?;
    Ok(())
}

pub fn contentcallnext_html<W>(#[allow(unused_mut)] mut _ructe_out_: W, content: impl FnOnce(&mut W) -> io::Result<()>) -> io::Result<()>
where W: Write {
    content(_ructe_out_.by_ref())?;
    Ok(())
}

@kaj Are you able to detect when argument to @:sub_template is a Content? If so, wrap arg as |w| arg(*w).

@kornelski
Copy link
Contributor

I wonder if ructe could define its own trait that calls things, so that dealing with W vs &mut W vs &dyn W distinction could be left to Rust's auto-deref method resolution magic.

@kaj kaj added the bug label Jun 9, 2024
@kaj
Copy link
Owner

kaj commented Jun 25, 2024

Another workaround is to change the first_template.rs.html like this:

@use super::next_template_html;

@(content: Content)

@:next_template_html({@:content()})

I'm considering wether I shold document this a required workaround or basically revert #125 , as I still havn't found any other solution.

@drehren
Copy link
Author

drehren commented Jun 26, 2024

I am happy with a the workaround.
I think that documenting it would be good as it seems to properly "blend" with how a ructe template should look.

kaj added a commit that referenced this issue Jun 30, 2024
Gave up on finding a real fix for #134, so documenting a workaround
instead.
kaj added a commit that referenced this issue Jun 30, 2024
kaj added a commit that referenced this issue Jun 30, 2024
@kaj kaj closed this as completed Jun 30, 2024
kaj added a commit that referenced this issue Jun 30, 2024
* The main branch in git is now `main` rather than `master`.
* Update clippy lint usage to get rid of warnings in all code using
  ructe (PR #137).  Thanks @vbradl!
* Identified a problem with `Content` parameters sent through
  intermediate templates, and documented a workaround for it (Issue
  #134, PR #141).  Thanks @drehren and @kornelski.
* The `axum` test is mentioned in [`README.md`] (PR #138).
  Thanks @abd0-omar!
* Update `base64` to 0.22.1 and `itertools` dependency to 0.13.0.
* MSRV is now 1.61.0.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

No branches or pull requests

3 participants