From 0926af9b28b2da68a81c30a8fb1639191f96a565 Mon Sep 17 00:00:00 2001 From: "K. Isom" Date: Sun, 18 Oct 2026 14:57:02 -0700 Subject: [PATCH] fix(ros2): resolve borrow conflict in publish_one --- tines-ros2/src/node.rs | 40 +++++++++++++++++++++++++--------------- 1 file changed, 25 insertions(+), 15 deletions(-) diff --git a/tines-ros2/src/node.rs b/tines-ros2/src/node.rs index c98dcd7c..c41624c0 100644 --- a/tines-ros2/src/node.rs +++ b/tines-ros2/src/node.rs @@ -254,12 +254,19 @@ impl TinesNode { self.ensure(&tines_topic)?; } - // Publish the latest observation for every managed topic. - let managed: Vec = self.managed.keys().cloned().collect(); - for name in managed { - if let Some(topic) = self.managed.get_mut(&name) { - self.publish_one(&topic.tines_topic, name, now)?; - } + // Publish the latest observation for every managed topic. We only need + // each topic's `tines_topic` bytes to look up its latest observation, + // so clone them (and the name) into owned locals *before* calling + // `publish_one`. That drops the borrow of `self.managed` up front — + // holding `&mut self.managed` across the `&mut self` call is the + // sibling of the E0502 the reviewer flagged. + let managed: Vec<(String, Vec)> = self + .managed + .iter() + .map(|(name, t)| (name.clone(), t.tines_topic.clone())) + .collect(); + for (name, tines_topic) in managed { + self.publish_one(&tines_topic, name, now)?; } Ok(()) } @@ -272,20 +279,23 @@ impl TinesNode { name: String, now: Tick, ) -> Result<(), TinesNodeError> { - let topic = self - .managed - .get_mut(&name) - .expect("managed topic still present"); - if let (Some(publisher), Some(obs)) = - (topic.publisher.as_mut(), self.latest_obs(tines_topic, now)) - { + // `latest_obs` takes `&self`, but `topic` below would hold a live + // `&mut self.managed` — the E0502 the reviewer flagged. Collect the + // latest observation on an immutable borrow that ends here, then take + // `&mut self.managed` for only the publish + bookkeeping that follows. + let Some(obs) = self.latest_obs(tines_topic, now) else { + return Ok(()); + }; + if let Some(topic) = self.managed.get_mut(&name) { if topic.last_pub == Some(obs.id()) { return Ok(()); } let payload = String::from_utf8_lossy(&obs.payload).into_owned(); let msg = StrMsg { data: payload }; - let _ = publisher.publish(&msg); - topic.last_pub = Some(obs.id()); + if let Some(publisher) = topic.publisher.as_mut() { + let _ = publisher.publish(&msg); + topic.last_pub = Some(obs.id()); + } } Ok(()) }