Skip to content

Recursive templates fail to render when the {{ child }} is escaped #393

@Kijewski

Description

@Kijewski

In this ↓ example we have a tree-like structure where Person contains children: &[Person]:

#[derive(Template)]
#[template(
    ext = "html",
    source = "{{name}}<{% for child in children %}{{ child }},{% endfor %}>"
)]
struct Person<'a> {
    name: &'a str,
    children: &'a [Person<'a>],
}

This example will fail to compile, because in here child is rendered with escaping. Because of that the Writer template argument be will become unrestrictedly large: EscapeWriter<EscapeWriter<EscapeWriter< … >>>. With each recursion the Writer gets one more nesting level. The recursion depth is unlimited, so no such writer can be constructed.

The problem can be resolved by adding |safe, so the no escaper is used. Using the Text escaper (ext = "txt") does not work, because even though it does not transform the input, it still winds up as template argument. I don't think that we can catch the problem to give the user a better error message.

The Writer is std::fmt::Writer, which is dyn-compatible. It might be possible break the recursion by adding an alternative escape filter that does not accept a generic impl fmt::Writer, but a dyn fmt::Writer.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions