From 3afe69fcdaca11c8bf38b0bebb85d7aedbc3fc42 Mon Sep 17 00:00:00 2001 From: David Mak Date: Sat, 5 Oct 2024 17:08:46 +0800 Subject: [PATCH] [core] typecheck: Disallow redeclaration of var shadowing global --- nac3core/src/typecheck/function_check.rs | 18 ++++++++++++++++-- 1 file changed, 16 insertions(+), 2 deletions(-) diff --git a/nac3core/src/typecheck/function_check.rs b/nac3core/src/typecheck/function_check.rs index c4626f2f..eccced75 100644 --- a/nac3core/src/typecheck/function_check.rs +++ b/nac3core/src/typecheck/function_check.rs @@ -34,6 +34,20 @@ impl<'a> Inferencer<'a> { Err(HashSet::from([format!("cannot assign to a `none` (at {})", pattern.location)])) } ExprKind::Name { id, .. } => { + // If `id` refers to a declared symbol, reject this assignment if it is used in the + // context of an (implicit) global variable + if let Some(id_info) = self.defined_identifiers.get(id) { + if matches!( + id_info.source, + DeclarationSource::Global { is_explicit: Some(false) } + ) { + return Err(HashSet::from([format!( + "cannot access local variable '{id}' before it is declared (at {})", + pattern.location + )])); + } + } + if !defined_identifiers.contains_key(id) { defined_identifiers.insert(*id, IdentifierInfo::default()); } @@ -104,7 +118,7 @@ impl<'a> Inferencer<'a> { *id, ) { Ok(_) => { - self.defined_identifiers.insert(*id, IdentifierInfo::default()); + defined_identifiers.insert(*id, IdentifierInfo::default()); } Err(e) => { return Err(HashSet::from([format!( @@ -370,7 +384,7 @@ impl<'a> Inferencer<'a> { if let Some(id_info) = defined_identifiers.get(id) { if id_info.source == DeclarationSource::Local { return Err(HashSet::from([format!( - "name '{id}' is assigned to before global declaration at {}", + "name '{id}' is used prior to global declaration at {}", stmt.location, )])); }