Skip to content

Commit 0830b84

Browse files
authored
Merge pull request #4740 from royAmmerschuber/feature/refactor-diagnostics-struct
TreeBorrows: Put accesses diagnostic parameters into a single struct
2 parents 8014987 + 85e3acc commit 0830b84

File tree

2 files changed

+94
-102
lines changed

2 files changed

+94
-102
lines changed

src/tools/miri/src/borrow_tracker/tree_borrows/diagnostics.rs

Lines changed: 44 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -77,6 +77,32 @@ pub struct Event {
7777
pub span: Span,
7878
}
7979

80+
/// Diagnostics data about the current access and the location we are accessing.
81+
/// Used to create history events and errors.
82+
#[derive(Clone, Debug)]
83+
pub struct DiagnosticInfo {
84+
pub alloc_id: AllocId,
85+
pub span: Span,
86+
/// The range the diagnostic actually applies to.
87+
/// This is always a subset of `access_range`.
88+
pub transition_range: Range<u64>,
89+
/// The range the access is happening to. Is `None` if this is the protector release access
90+
pub access_range: Option<AllocRange>,
91+
pub access_cause: AccessCause,
92+
}
93+
impl DiagnosticInfo {
94+
/// Creates a history event.
95+
pub fn create_event(&self, transition: PermTransition, is_foreign: bool) -> Event {
96+
Event {
97+
transition,
98+
is_foreign,
99+
access_cause: self.access_cause,
100+
access_range: self.access_range,
101+
transition_range: self.transition_range.clone(),
102+
span: self.span,
103+
}
104+
}
105+
}
80106
/// List of all events that affected a tag.
81107
/// NOTE: not all of these events are relevant for a particular location,
82108
/// the events should be filtered before the generation of diagnostics.
@@ -280,32 +306,29 @@ impl History {
280306
pub(super) struct TbError<'node> {
281307
/// What failure occurred.
282308
pub error_kind: TransitionError,
283-
/// The allocation in which the error is happening.
284-
pub alloc_id: AllocId,
285-
/// The offset (into the allocation) at which the conflict occurred.
286-
pub error_offset: u64,
309+
/// Diagnostic data about the access that caused the error.
310+
pub access_info: &'node DiagnosticInfo,
287311
/// The tag on which the error was triggered.
288312
/// On protector violations, this is the tag that was protected.
289313
/// On accesses rejected due to insufficient permissions, this is the
290314
/// tag that lacked those permissions.
291-
pub conflicting_info: &'node NodeDebugInfo,
292-
// What kind of access caused this error (read, write, reborrow, deallocation)
293-
pub access_cause: AccessCause,
315+
pub conflicting_node_info: &'node NodeDebugInfo,
294316
/// Which tag, if any, the access that caused this error was made through, i.e.
295317
/// which tag was used to read/write/deallocate.
296318
/// Not set on wildcard accesses.
297-
pub accessed_info: Option<&'node NodeDebugInfo>,
319+
pub accessed_node_info: Option<&'node NodeDebugInfo>,
298320
}
299321

300322
impl TbError<'_> {
301323
/// Produce a UB error.
302324
pub fn build<'tcx>(self) -> InterpErrorKind<'tcx> {
303325
use TransitionError::*;
304-
let cause = self.access_cause;
305-
let accessed = self.accessed_info;
326+
let cause = self.access_info.access_cause;
327+
let error_offset = self.access_info.transition_range.start;
328+
let accessed = self.accessed_node_info;
306329
let accessed_str =
307-
self.accessed_info.map(|v| format!("{v}")).unwrap_or_else(|| "<wildcard>".into());
308-
let conflicting = self.conflicting_info;
330+
self.accessed_node_info.map(|v| format!("{v}")).unwrap_or_else(|| "<wildcard>".into());
331+
let conflicting = self.conflicting_node_info;
309332
// An access is considered conflicting if it happened through a
310333
// different tag than the one who caused UB.
311334
// When doing a wildcard access (where `accessed` is `None`) we
@@ -316,9 +339,8 @@ impl TbError<'_> {
316339
// all tags through which an access would cause UB.
317340
let accessed_is_conflicting = accessed.map(|a| a.tag) == Some(conflicting.tag);
318341
let title = format!(
319-
"{cause} through {accessed_str} at {alloc_id:?}[{offset:#x}] is forbidden",
320-
alloc_id = self.alloc_id,
321-
offset = self.error_offset
342+
"{cause} through {accessed_str} at {alloc_id:?}[{error_offset:#x}] is forbidden",
343+
alloc_id = self.access_info.alloc_id
322344
);
323345
let (title, details, conflicting_tag_name) = match self.error_kind {
324346
ChildAccessForbidden(perm) => {
@@ -362,13 +384,13 @@ impl TbError<'_> {
362384
}
363385
};
364386
let mut history = HistoryData::default();
365-
if let Some(accessed_info) = self.accessed_info
387+
if let Some(accessed_info) = self.accessed_node_info
366388
&& !accessed_is_conflicting
367389
{
368390
history.extend(accessed_info.history.forget(), "accessed", false);
369391
}
370392
history.extend(
371-
self.conflicting_info.history.extract_relevant(self.error_offset, self.error_kind),
393+
self.conflicting_node_info.history.extract_relevant(error_offset, self.error_kind),
372394
conflicting_tag_name,
373395
true,
374396
);
@@ -379,12 +401,12 @@ impl TbError<'_> {
379401
/// Cannot access this allocation with wildcard provenance, as there are no
380402
/// valid exposed references for this access kind.
381403
pub fn no_valid_exposed_references_error<'tcx>(
382-
alloc_id: AllocId,
383-
offset: u64,
384-
access_cause: AccessCause,
404+
DiagnosticInfo { alloc_id, transition_range, access_cause, .. }: &DiagnosticInfo,
385405
) -> InterpErrorKind<'tcx> {
386-
let title =
387-
format!("{access_cause} through <wildcard> at {alloc_id:?}[{offset:#x}] is forbidden");
406+
let title = format!(
407+
"{access_cause} through <wildcard> at {alloc_id:?}[{offset:#x}] is forbidden",
408+
offset = transition_range.start
409+
);
388410
let details = vec![format!("there are no exposed tags which may perform this access here")];
389411
let history = HistoryData::default();
390412
err_machine_stop!(TerminationInfo::TreeBorrowsUb { title, details, history })

0 commit comments

Comments
 (0)