From 359bb6eebe24158c3a472432a5df4e9a3eeeaaf5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jakub=20=C5=BD=C3=A1dn=C3=ADk?= Date: Mon, 21 Feb 2022 23:05:20 +0200 Subject: [PATCH] Look up predecl only in the working set (#4592) Previously, the parser tried to look up the predecl also in the permanent state and if a definition with that name already existed, it would try to update it, which is illegal. --- crates/nu-parser/src/parse_keywords.rs | 4 ++-- crates/nu-protocol/src/engine/engine_state.rs | 10 ++++++++++ 2 files changed, 12 insertions(+), 2 deletions(-) diff --git a/crates/nu-parser/src/parse_keywords.rs b/crates/nu-parser/src/parse_keywords.rs index ebb69b8ed5..d2025f8485 100644 --- a/crates/nu-parser/src/parse_keywords.rs +++ b/crates/nu-parser/src/parse_keywords.rs @@ -331,7 +331,7 @@ pub fn parse_def( if let (Some(name), Some(mut signature), Some(block_id)) = (&name_expr.as_string(), sig.as_signature(), block.as_block()) { - if let Some(decl_id) = working_set.find_decl(name.as_bytes()) { + if let Some(decl_id) = working_set.find_predecl(name.as_bytes()) { let declaration = working_set.get_decl_mut(decl_id); signature.name = name.clone(); @@ -430,7 +430,7 @@ pub fn parse_extern( if let (Some(name_expr), Some(sig)) = (name_expr, sig) { if let (Some(name), Some(mut signature)) = (&name_expr.as_string(), sig.as_signature()) { - if let Some(decl_id) = working_set.find_decl(name.as_bytes()) { + if let Some(decl_id) = working_set.find_predecl(name.as_bytes()) { let declaration = working_set.get_decl_mut(decl_id); signature.name = name.clone(); diff --git a/crates/nu-protocol/src/engine/engine_state.rs b/crates/nu-protocol/src/engine/engine_state.rs index da5a0948b3..ed66f3ee6c 100644 --- a/crates/nu-protocol/src/engine/engine_state.rs +++ b/crates/nu-protocol/src/engine/engine_state.rs @@ -999,6 +999,16 @@ impl<'a> StateWorkingSet<'a> { self.delta.exit_scope(); } + pub fn find_predecl(&self, name: &[u8]) -> Option { + for scope in self.delta.scope.iter().rev() { + if let Some(decl_id) = scope.predecls.get(name) { + return Some(*decl_id); + } + } + + None + } + pub fn find_decl(&self, name: &[u8]) -> Option { let mut visibility: Visibility = Visibility::new();