From f1af14b1cc503ac20f56a79a96c7780d02bdfe75 Mon Sep 17 00:00:00 2001 From: nsfisis Date: Wed, 24 Jun 2026 03:56:26 +0900 Subject: fix(console): make Command/BaseCommand methods take &self The Command trait and Composer's BaseCommand took &mut self, so dispatch held a borrow_mut on the command's RefCell for the whole call. A command re-entering itself (e.g. the help command describing itself) then panicked with "RefCell already borrowed". All Command/BaseCommand methods now take &self and the command state is interior-mutable (Cell/RefCell). Shared borrows coexist, so re-entrant describe paths no longer conflict. Getters that returned references now return Ref guards; the descriptor describe_* methods take &dyn Command; mixin accessors return Ref/RefMut. Co-Authored-By: Claude Opus 4.8 (1M context) --- crates/shirabe/src/command/package_discovery_trait.rs | 18 ++++++++++-------- 1 file changed, 10 insertions(+), 8 deletions(-) (limited to 'crates/shirabe/src/command/package_discovery_trait.rs') diff --git a/crates/shirabe/src/command/package_discovery_trait.rs b/crates/shirabe/src/command/package_discovery_trait.rs index 9be30f5..943eeaf 100644 --- a/crates/shirabe/src/command/package_discovery_trait.rs +++ b/crates/shirabe/src/command/package_discovery_trait.rs @@ -37,12 +37,14 @@ use crate::util::Filesystem; pub trait PackageDiscoveryTrait: BaseCommand { // PHP: private $repos; private $repositorySets; // TODO(phase-b): trait fields require an associated state struct in Rust; expose via accessors - fn get_repos_mut(&mut self) -> &mut Option; + fn get_repos_mut( + &self, + ) -> std::cell::RefMut<'_, Option>; fn get_repository_sets_mut( - &mut self, - ) -> &mut IndexMap>>; + &self, + ) -> std::cell::RefMut<'_, IndexMap>>>; - fn get_repos(&mut self) -> crate::repository::RepositoryInterfaceHandle { + fn get_repos(&self) -> crate::repository::RepositoryInterfaceHandle { if self.get_repos_mut().is_none() { // PHP: array_merge([new PlatformRepository], RepositoryFactory::defaultReposWithDefaultManager($this->getIO())) let mut repos: Vec = @@ -67,7 +69,7 @@ pub trait PackageDiscoveryTrait: BaseCommand { /// @param key-of|null $minimumStability fn get_repository_set( - &mut self, + &self, input: std::rc::Rc>, minimum_stability: Option<&str>, ) -> std::rc::Rc> { @@ -134,7 +136,7 @@ pub trait PackageDiscoveryTrait: BaseCommand { #[allow(clippy::too_many_arguments, reason = "to keep PHP signature")] fn determine_requirements( - &mut self, + &self, input: std::rc::Rc>, _output: std::rc::Rc>, mut requires: Vec, @@ -463,7 +465,7 @@ pub trait PackageDiscoveryTrait: BaseCommand { /// @throws \InvalidArgumentException /// @return array{string, string} name version fn find_best_version_and_name_for_package( - &mut self, + &self, io: std::rc::Rc>, input: std::rc::Rc>, name: &str, @@ -759,7 +761,7 @@ pub trait PackageDiscoveryTrait: BaseCommand { } /// @return array - fn find_similar(&mut self, package: &str) -> Result> { + fn find_similar(&self, package: &str) -> Result> { let results: Vec = match (|| -> Result> { if self.get_repos_mut().is_none() { return Err(LogicException { -- cgit v1.3.1