From 117418fd10b806c989a5fee3053fc8b097387e2c Mon Sep 17 00:00:00 2001 From: Neven Villani Date: Mon, 1 May 2023 14:54:56 +0200 Subject: [PATCH] Payoff: much simpler event selection Error messages unchanged --- .../tree_borrows/diagnostics.rs | 57 +++++-------------- 1 file changed, 15 insertions(+), 42 deletions(-) diff --git a/src/borrow_tracker/tree_borrows/diagnostics.rs b/src/borrow_tracker/tree_borrows/diagnostics.rs index 72b23884bb..0aba9aeedf 100644 --- a/src/borrow_tracker/tree_borrows/diagnostics.rs +++ b/src/borrow_tracker/tree_borrows/diagnostics.rs @@ -196,44 +196,19 @@ impl History { History { events: Vec::new(), created: self.created, tag: self.tag } } - /// Reconstruct the history relevant to `error_offset` knowing that - /// its permission followed `complete_transition`. - /// - /// Here's how we do this: - /// - we know `full := complete_transition` the transition of the permission from - /// its initialization to the state just before the error was caused, - /// we want to find a chain of events that produces `full` - /// - we decompose `full` into `pre o post` where - /// `pre` is the best applicable transition from recorded events - /// - we select the event that caused `pre` and iterate - /// to find the chain of events that produces `full := post` - /// - /// To find the "best applicable transition" for full: - /// - eliminate events that cannot be applied because their offset is too big - /// - eliminate events that cannot be applied because their starting point is wrong - /// - select the one that happened closest to the range of interest - fn extract_relevant(&self, complete_transition: PermTransition, error_offset: Size) -> Self { - let mut selected_events: Vec = Vec::new(); - let mut full = complete_transition; - while !full.is_noop() { - let (pre, post) = self + /// Reconstruct the history relevant to `error_offset` by filtering + /// only events whose range contains the offset we are interested in. + fn extract_relevant(&self, error_offset: u64) -> Self { + History { + events: self .events .iter() - .filter(|e| e.offset <= error_offset) - .filter_map(|pre_canditate| { - full.apply_start(pre_canditate.transition) - .map(|post_canditate| (pre_canditate, post_canditate)) - }) - .max_by_key(|(pre_canditate, _post_candidate)| pre_canditate.offset) - .unwrap(); - // If this occurs we will loop infinitely ! - // Make sure to only put non-noop transitions in `History`. - assert!(!pre.transition.is_noop()); - full = post; - selected_events.push(pre.clone()); + .filter(|e| e.offset.start <= error_offset && error_offset < e.offset.end) + .cloned() + .collect::>(), + created: self.created, + tag: self.tag, } - - History { events: selected_events, created: self.created, tag: self.tag } } } @@ -260,12 +235,11 @@ impl TbError<'_> { /// Produce a UB error. pub fn build<'tcx>(self) -> InterpError<'tcx> { use TransitionError::*; - let started_as = self.conflicting_info.history.created.1; let kind = self.access_kind; let accessed = self.accessed_info; let conflicting = self.conflicting_info; let accessed_is_conflicting = accessed.tag == conflicting.tag; - let (pre_error, title, details, conflicting_tag_name) = match self.error_kind { + let (title, details, conflicting_tag_name) = match self.error_kind { ChildAccessForbidden(perm) => { let conflicting_tag_name = if accessed_is_conflicting { "accessed" } else { "conflicting" }; @@ -279,7 +253,7 @@ impl TbError<'_> { details.push(format!( "the {conflicting_tag_name} tag {conflicting} has state {perm} which forbids child {kind}es" )); - (perm, title, details, conflicting_tag_name) + (title, details, conflicting_tag_name) } ProtectedTransition(transition) => { let conflicting_tag_name = "protected"; @@ -296,7 +270,7 @@ impl TbError<'_> { loss = transition.summary(), ), ]; - (transition.started(), title, details, conflicting_tag_name) + (title, details, conflicting_tag_name) } ProtectedDealloc => { let conflicting_tag_name = "strongly protected"; @@ -307,16 +281,15 @@ impl TbError<'_> { ), format!("the {conflicting_tag_name} tag {conflicting} disallows deallocations"), ]; - (started_as, title, details, conflicting_tag_name) + (title, details, conflicting_tag_name) } }; - let pre_transition = PermTransition::from(started_as, pre_error).unwrap(); let mut history = HistoryData::default(); if !accessed_is_conflicting { history.extend(self.accessed_info.history.forget(), "accessed", false); } history.extend( - self.conflicting_info.history.extract_relevant(pre_transition, self.error_offset), + self.conflicting_info.history.extract_relevant(self.error_offset), conflicting_tag_name, true, );