diff --git a/askama_shared/src/generator.rs b/askama_shared/src/generator.rs index 320e55eab..837f16512 100644 --- a/askama_shared/src/generator.rs +++ b/askama_shared/src/generator.rs @@ -667,8 +667,26 @@ impl<'a, S: std::hash::BuildHasher> Generator<'a, S> { ", _loop_item) in ::askama::helpers::TemplateLoop::new({}) {{", expr_code )), + Expr::Array(..) => buf.writeln(&format!( + ", _loop_item) in ::askama::helpers::TemplateLoop::new({}.iter()) {{", + expr_code + )), + // If `iter` is a call then we assume it's something that returns + // an iterator. If not then the user can explicitly add the needed + // call without issues. + Expr::MethodCall(..) | Expr::PathCall(..) | Expr::Index(..) => buf.writeln(&format!( + ", _loop_item) in ::askama::helpers::TemplateLoop::new(({}).into_iter()) {{", + expr_code + )), + // If accessing `self` then it most likely needs to be + // borrowed, to prevent an attempt of moving. + _ if expr_code.starts_with("self.") => buf.writeln(&format!( + ", _loop_item) in ::askama::helpers::TemplateLoop::new(((&{}).into_iter())) {{", + expr_code + )), + // Otherwise, we borrow `iter` assuming that it implements `IntoIterator`. _ => buf.writeln(&format!( - ", _loop_item) in ::askama::helpers::TemplateLoop::new((&{}).into_iter()) {{", + ", _loop_item) in ::askama::helpers::TemplateLoop::new(({}).into_iter()) {{", expr_code )), }?; diff --git a/testing/tests/loops.rs b/testing/tests/loops.rs index 3ce61859c..4345b4f72 100644 --- a/testing/tests/loops.rs +++ b/testing/tests/loops.rs @@ -67,3 +67,39 @@ fn test_for_range() { "foo (first)\nfoo (last)\nbar\nbar\nfoo\nbar\nbar\n" ); } + +#[derive(Template)] +#[template(source = "{% for i in [1, 2, 3] %}{{ i }}{% endfor %}", ext = "txt")] +struct ForArrayTemplate {} + +#[test] +fn test_for_array() { + let t = ForArrayTemplate {}; + assert_eq!(t.render().unwrap(), "123"); +} + +#[derive(Template)] +#[template( + source = "{% for i in [1, 2, 3].iter() %}{{ i }}{% endfor %}", + ext = "txt" +)] +struct ForMethodCallTemplate {} + +#[test] +fn test_for_method_call() { + let t = ForMethodCallTemplate {}; + assert_eq!(t.render().unwrap(), "123"); +} + +#[derive(Template)] +#[template( + source = "{% for i in [1, 2, 3, 4, 5][3..] %}{{ i }}{% endfor %}", + ext = "txt" +)] +struct ForIndexTemplate {} + +#[test] +fn test_for_index() { + let t = ForIndexTemplate {}; + assert_eq!(t.render().unwrap(), "45"); +}