From cd744f0aa705882f0e4fd0466e24cdbccf9fc28f Mon Sep 17 00:00:00 2001 From: René Kijewski Date: Mon, 31 Jan 2022 08:38:44 +0100 Subject: Make is_shadowing_variable() failable --- askama_shared/src/generator.rs | 36 ++++++++++++++++++++++++------------ 1 file changed, 24 insertions(+), 12 deletions(-) (limited to 'askama_shared') diff --git a/askama_shared/src/generator.rs b/askama_shared/src/generator.rs index 7080b87..acd716b 100644 --- a/askama_shared/src/generator.rs +++ b/askama_shared/src/generator.rs @@ -804,26 +804,38 @@ impl<'a, S: std::hash::BuildHasher> Generator<'a, S> { buf.writeln(";") } - fn is_shadowing_variable(&self, var: &Target<'a>) -> bool { + fn is_shadowing_variable(&self, var: &Target<'a>) -> Result { match var { Target::Name(name) => { let name = normalize_identifier(name); match self.locals.get(&name) { // declares a new variable - None => false, + None => Ok(false), // an initialized variable gets shadowed - Some(meta) if meta.initialized => true, + Some(meta) if meta.initialized => Ok(true), // initializes a variable that was introduced in a LetDecl before - _ => false, + _ => Ok(false), } } - Target::Tuple(_, targets) => targets - .iter() - .any(|target| self.is_shadowing_variable(target)), - Target::Struct(_, named_targets) => named_targets - .iter() - .any(|(_, target)| self.is_shadowing_variable(target)), - _ => panic!("Cannot have literals on the left-hand-side of an assignment."), + Target::Tuple(_, targets) => { + for target in targets { + match self.is_shadowing_variable(target) { + Ok(false) => continue, + outcome => return outcome, + } + } + Ok(false) + } + Target::Struct(_, named_targets) => { + for (_, target) in named_targets { + match self.is_shadowing_variable(target) { + Ok(false) => continue, + outcome => return outcome, + } + } + Ok(false) + } + _ => Err("literals are not allowed on the left-hand side of an assignment".into()), } } @@ -838,7 +850,7 @@ impl<'a, S: std::hash::BuildHasher> Generator<'a, S> { let mut expr_buf = Buffer::new(0); self.visit_expr(&mut expr_buf, val)?; - let shadowed = self.is_shadowing_variable(var); + let shadowed = self.is_shadowing_variable(var)?; if shadowed { // Need to flush the buffer if the variable is being shadowed, // to ensure the old variable is used. -- cgit