From a199defeca2dfc6aa3e972acca82c96db07f99e9 Mon Sep 17 00:00:00 2001 From: Christian Vallentin Date: Tue, 1 Dec 2020 17:01:05 +0100 Subject: Improved if statement generation to avoid issues with implicit borrows (#392) * Changed to automatically coerce to bool * Added new test case * Updated test case to include else if --- askama_shared/src/generator.rs | 7 ++++++ testing/templates/if-coerce.html | 51 ++++++++++++++++++++++++++++++++++++++++ testing/tests/coerce.rs | 14 +++++++++++ 3 files changed, 72 insertions(+) create mode 100644 testing/templates/if-coerce.html create mode 100644 testing/tests/coerce.rs diff --git a/askama_shared/src/generator.rs b/askama_shared/src/generator.rs index 3a91e3c..ad086a3 100644 --- a/askama_shared/src/generator.rs +++ b/askama_shared/src/generator.rs @@ -518,8 +518,15 @@ impl<'a, S: std::hash::BuildHasher> Generator<'a, S> { buf.dedent()?; buf.write("} else if "); } + // The following syntax `*(&(...) as &bool)` is used to + // trigger Rust's automatic dereferencing, to coerce + // e.g. `&&&&&bool` to `bool`. First `&(...) as &bool` + // coerces e.g. `&&&bool` to `&bool`. Then `*(&bool)` + // finally dereferences it to `bool`. + buf.write("*(&("); let expr_code = self.visit_expr_root(expr)?; buf.write(&expr_code); + buf.write(") as &bool)"); } None => { buf.dedent()?; diff --git a/testing/templates/if-coerce.html b/testing/templates/if-coerce.html new file mode 100644 index 0000000..e32c2fe --- /dev/null +++ b/testing/templates/if-coerce.html @@ -0,0 +1,51 @@ +{% macro foo(b) -%} + {% if b %}t{% else %}f{% endif -%} +{% endmacro -%} + +{% macro bar(b) -%} + {%- call foo(b) -%} +{% endmacro -%} + +{% macro baz(b) -%} + {%- call bar(b) -%} +{% endmacro -%} + +{% macro qux(b) -%} + {%- call baz(b) -%} +{% endmacro -%} + +{%- call foo(false) -%} +{%- call bar(true) -%} +{%- call baz(false) -%} +{%- call qux(true) -%} + +{%- call qux(true && false) -%} +{%- call qux(false || true) -%} + +{%- call qux(self.t) -%} +{%- call qux(self.f) -%} +{%- call qux(self.f || self.t) -%} + +{%- if false -%} +if +{%- else if false || true -%} +elseif +{%- else -%} +else +{%- endif -%} + +{%- if true && false -%} +if +{%- else if false -%} +elseif +{%- else -%} +else +{%- endif -%} + +{%- if false || true -%} +if +{%- else if (true && false) -%} +elseif +{%- else -%} +else +{%- endif -%} diff --git a/testing/tests/coerce.rs b/testing/tests/coerce.rs new file mode 100644 index 0000000..1a44781 --- /dev/null +++ b/testing/tests/coerce.rs @@ -0,0 +1,14 @@ +use askama::Template; + +#[derive(Template)] +#[template(path = "if-coerce.html")] +struct IfCoerceTemplate { + t: bool, + f: bool, +} + +#[test] +fn test_coerce() { + let t = IfCoerceTemplate { t: true, f: false }; + assert_eq!(t.render().unwrap(), "ftftfttftelseifelseif"); +} -- cgit