From fa467172dde1f593dfcfebc6877f7d908545c0de Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Tue, 2 Jul 2024 22:39:28 +0200 Subject: [PATCH 1/2] Prevent jinja `let` to move variables --- rinja_derive/src/generator.rs | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/rinja_derive/src/generator.rs b/rinja_derive/src/generator.rs index 33f616af..201d4151 100644 --- a/rinja_derive/src/generator.rs +++ b/rinja_derive/src/generator.rs @@ -921,7 +921,12 @@ impl<'a> Generator<'a> { } self.visit_target(buf, true, true, &l.var); - buf.writeln(format_args!(" = {};", &expr_buf.buf)); + let (before, after) = if !is_copyable(val) { + ("&(", ")") + } else { + ("", "") + }; + buf.writeln(format_args!(" = {before}{}{after};", &expr_buf.buf)); Ok(()) } @@ -2121,7 +2126,7 @@ fn is_copyable_within_op(expr: &Expr<'_>, within_op: bool) -> bool { // The result of a call likely doesn't need to be borrowed, // as in that case the call is more likely to return a // reference in the first place then. - Expr::Call(..) | Expr::Path(..) => true, + Expr::Call(..) | Expr::Path(..) | Expr::Filter(..) => true, // If the `expr` is within a `Unary` or `BinOp` then // an assumption can be made that the operand is copy. // If not, then the value is moved and adding `.clone()` From e7f2979b732846ca8b5d278b99eeb0d16bcbf3f9 Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Tue, 2 Jul 2024 22:40:09 +0200 Subject: [PATCH 2/2] Add regression test for moving variables in let statement --- testing/tests/ref_deref.rs | 2 +- testing/tests/vars.rs | 20 ++++++++++++++++++++ 2 files changed, 21 insertions(+), 1 deletion(-) diff --git a/testing/tests/ref_deref.rs b/testing/tests/ref_deref.rs index ce17bc65..4e685e4b 100644 --- a/testing/tests/ref_deref.rs +++ b/testing/tests/ref_deref.rs @@ -39,7 +39,7 @@ fn test_ref_deref() { #[derive(Template)] #[template( source = r#" -{%- let x = *title -%} +{%- let x = **title -%} {%- if x == "another" -%} another2 {%- else -%} diff --git a/testing/tests/vars.rs b/testing/tests/vars.rs index 6a471f8e..84710946 100644 --- a/testing/tests/vars.rs +++ b/testing/tests/vars.rs @@ -131,3 +131,23 @@ fn test_decl_assign_range() { let t = DeclAssignRange; assert_eq!(t.render().unwrap(), "1"); } + +#[derive(Template)] +#[template( + source = " +{%- set t = title -%} +{{t}}/{{title -}} +", + ext = "txt" +)] +struct DoNotMoveFields { + title: String, +} + +#[test] +fn test_not_moving_fields_in_var() { + let x = DoNotMoveFields { + title: "a".to_string(), + }; + assert_eq!(x.render().unwrap(), "a/a"); +}