From 58b22c41799d8c863b6695f2987c97f01c7d31fd Mon Sep 17 00:00:00 2001 From: Shunsuke Shibayama Date: Thu, 19 Sep 2024 03:51:20 +0900 Subject: [PATCH] fix: add debug assertions to PackageBuilder --- crates/els/server.rs | 8 ++++++-- crates/erg_compiler/build_package.rs | 22 +++++++++++++++++++--- crates/erg_compiler/module/promise.rs | 9 +++++++-- 3 files changed, 32 insertions(+), 7 deletions(-) diff --git a/crates/els/server.rs b/crates/els/server.rs index 0ac06fe43..37518521e 100644 --- a/crates/els/server.rs +++ b/crates/els/server.rs @@ -8,7 +8,7 @@ use std::sync::atomic::{AtomicBool, Ordering}; use std::sync::{mpsc, Arc}; use std::time::Duration; -use erg_common::config::ErgConfig; +use erg_common::config::{ErgConfig, ErgMode}; use erg_common::consts::PYTHON_MODE; use erg_common::dict::Dict; use erg_common::env::erg_path; @@ -213,7 +213,11 @@ impl Server { #[allow(unused)] pub fn bind_fake_client() -> FakeClient { let (sender, receiver) = std::sync::mpsc::channel(); - FakeClient::new(Server::new(ErgConfig::default(), Some(sender)), receiver) + let cfg = ErgConfig { + mode: ErgMode::LanguageServer, + ..Default::default() + }; + FakeClient::new(Server::new(cfg, Some(sender)), receiver) } } diff --git a/crates/erg_compiler/build_package.rs b/crates/erg_compiler/build_package.rs index 32d292d66..3483ea0f2 100644 --- a/crates/erg_compiler/build_package.rs +++ b/crates/erg_compiler/build_package.rs @@ -819,11 +819,19 @@ impl /// Launch the analysis processes in order according to the dependency graph. fn execute(&mut self, ast: AST, mode: &str) -> Result { log!(info "Start to spawn dependencies processes"); - let path = NormalizedPathBuf::from(self.cfg.input.path()); + let root = NormalizedPathBuf::from(self.cfg.input.path()); let mut graph = self.shared.graph.clone_inner(); - let deps = self.build_deps_and_module(&path, &mut graph); + let deps = self.build_deps_and_module(&root, &mut graph); log!(info "All dependencies have started to analyze"); debug_power_assert!(self.asts.len(), ==, 0); + if self.cfg.mode != ErgMode::LanguageServer { + for path in self.shared.graph.ancestors(&root) { + assert!( + self.shared.promises.is_registered(&path), + "{path} is not registered" + ); + } + } self.finalize(); match self.main_builder.build_from_ast(ast, mode) { Ok(artifact) => Ok(CompleteArtifact::new( @@ -895,6 +903,7 @@ impl self.shared.promises.wait_until_finished(path); } else if let Some(inliner) = self.inlines.get(path).cloned() { self.build_deps_and_module(&inliner, graph); + self.shared.promises.mark_as_joined(path.clone()); } else { unreachable!("{path} is not found in self.inlines and self.asts"); } @@ -998,10 +1007,17 @@ impl } Err(artifact) => { let ctx = builder.pop_context().unwrap(); - py_mod_cache.register(path, raw_ast, artifact.object, ctx, CheckStatus::Failed); + py_mod_cache.register( + path.clone(), + raw_ast, + artifact.object, + ctx, + CheckStatus::Failed, + ); self.shared.warns.extend(artifact.warns); self.shared.errors.extend(artifact.errors); } } + self.shared.promises.mark_as_joined(path); } } diff --git a/crates/erg_compiler/module/promise.rs b/crates/erg_compiler/module/promise.rs index e57b5ea68..991aa0d11 100644 --- a/crates/erg_compiler/module/promise.rs +++ b/crates/erg_compiler/module/promise.rs @@ -54,6 +54,10 @@ impl Promise { matches!(self, Self::Joined) } + pub const fn is_joining(&self) -> bool { + matches!(self, Self::Joining) + } + pub fn thread_id(&self) -> Option { match self { Self::Joined | Self::Joining => None, @@ -172,8 +176,8 @@ impl SharedPromises { if !self.graph.entries().contains(path) { return Err(Box::new(format!("not registered: {path}"))); } - if self.graph.ancestors(path).contains(&self.root) { - // cycle detected, `self.path` must not in the dependencies + if self.graph.ancestors(path).contains(&self.root) || path == &self.root { + // cycle detected, `self.root` must not in the dependencies // Erg analysis processes never join ancestor threads (although joining ancestors itself is allowed in Rust) // self.wait_until_finished(path); return Ok(()); @@ -206,6 +210,7 @@ impl SharedPromises { return Ok(()); }; if handle.thread().id() == current().id() { + *self.promises.borrow_mut().get_mut(path).unwrap() = Promise::Joined; return Ok(()); } let res = handle.join();