Skip to content

Commit 98c5fce

Browse files
committed
Auto merge of #2918 - Vanille-N:tb-diags, r=RalfJung
TB: improve error messages (distinguish between accesses and reborrows) I don't remember where, but there was a complaint that while SB's error messages distinguish between "invalidated by an access" and "invalidated by a reborrow", TB's error messages do not.
2 parents 5d01a6b + 7a1cdf7 commit 98c5fce

File tree

51 files changed

+195
-142
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

51 files changed

+195
-142
lines changed

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

Lines changed: 46 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -12,16 +12,46 @@ use crate::borrow_tracker::tree_borrows::{
1212
use crate::borrow_tracker::{AccessKind, ProtectorKind};
1313
use crate::*;
1414

15+
/// Cause of an access: either a real access or one
16+
/// inserted by Tree Borrows due to a reborrow or a deallocation.
17+
#[derive(Clone, Copy, Debug)]
18+
pub enum AccessCause {
19+
Explicit(AccessKind),
20+
Reborrow,
21+
Dealloc,
22+
}
23+
24+
impl fmt::Display for AccessCause {
25+
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
26+
match self {
27+
Self::Explicit(kind) => write!(f, "{kind}"),
28+
Self::Reborrow => write!(f, "reborrow"),
29+
Self::Dealloc => write!(f, "deallocation"),
30+
}
31+
}
32+
}
33+
34+
impl AccessCause {
35+
fn print_as_access(self, is_foreign: bool) -> String {
36+
let rel = if is_foreign { "foreign" } else { "child" };
37+
match self {
38+
Self::Explicit(kind) => format!("{rel} {kind}"),
39+
Self::Reborrow => format!("reborrow (acting as a {rel} read access)"),
40+
Self::Dealloc => format!("deallocation (acting as a {rel} write access)"),
41+
}
42+
}
43+
}
44+
1545
/// Complete data for an event:
1646
#[derive(Clone, Debug)]
1747
pub struct Event {
1848
/// Transformation of permissions that occured because of this event
1949
pub transition: PermTransition,
2050
/// Kind of the access that triggered this event
21-
pub access_kind: AccessKind,
51+
pub access_cause: AccessCause,
2252
/// Relative position of the tag to the one used for the access
2353
pub is_foreign: bool,
24-
/// User-visible range of the access
54+
/// Whether this access was explicit or inserted implicitly by Tree Borrows.
2555
pub access_range: AllocRange,
2656
/// The transition recorded by this event only occured on a subrange of
2757
/// `access_range`: a single access on `access_range` triggers several events,
@@ -83,17 +113,19 @@ impl HistoryData {
83113
self.events.push((Some(created.0.data()), msg_creation));
84114
for &Event {
85115
transition,
86-
access_kind,
87116
is_foreign,
117+
access_cause,
88118
access_range,
89119
span,
90120
transition_range: _,
91121
} in &events
92122
{
93123
// NOTE: `transition_range` is explicitly absent from the error message, it has no significance
94124
// to the user. The meaningful one is `access_range`.
95-
self.events.push((Some(span.data()), format!("{this} later transitioned to {endpoint} due to a {rel} {access_kind} at offsets {access_range:?}", endpoint = transition.endpoint(), rel = if is_foreign { "foreign" } else { "child" })));
96-
self.events.push((None, format!("this corresponds to {}", transition.summary())));
125+
let access = access_cause.print_as_access(is_foreign);
126+
self.events.push((Some(span.data()), format!("{this} later transitioned to {endpoint} due to a {access} at offsets {access_range:?}", endpoint = transition.endpoint())));
127+
self.events
128+
.push((None, format!("this transition corresponds to {}", transition.summary())));
97129
}
98130
}
99131
}
@@ -238,9 +270,8 @@ pub(super) struct TbError<'node> {
238270
/// On accesses rejected due to insufficient permissions, this is the
239271
/// tag that lacked those permissions.
240272
pub conflicting_info: &'node NodeDebugInfo,
241-
/// Whether this was a Read or Write access. This field is ignored
242-
/// when the error was triggered by a deallocation.
243-
pub access_kind: AccessKind,
273+
// What kind of access caused this error (read, write, reborrow, deallocation)
274+
pub access_cause: AccessCause,
244275
/// Which tag the access that caused this error was made through, i.e.
245276
/// which tag was used to read/write/deallocate.
246277
pub accessed_info: &'node NodeDebugInfo,
@@ -250,46 +281,46 @@ impl TbError<'_> {
250281
/// Produce a UB error.
251282
pub fn build<'tcx>(self) -> InterpError<'tcx> {
252283
use TransitionError::*;
253-
let kind = self.access_kind;
284+
let cause = self.access_cause;
254285
let accessed = self.accessed_info;
255286
let conflicting = self.conflicting_info;
256287
let accessed_is_conflicting = accessed.tag == conflicting.tag;
288+
let title = format!("{cause} through {accessed} is forbidden");
257289
let (title, details, conflicting_tag_name) = match self.error_kind {
258290
ChildAccessForbidden(perm) => {
259291
let conflicting_tag_name =
260292
if accessed_is_conflicting { "accessed" } else { "conflicting" };
261-
let title = format!("{kind} through {accessed} is forbidden");
262293
let mut details = Vec::new();
263294
if !accessed_is_conflicting {
264295
details.push(format!(
265296
"the accessed tag {accessed} is a child of the conflicting tag {conflicting}"
266297
));
267298
}
299+
let access = cause.print_as_access(/* is_foreign */ false);
268300
details.push(format!(
269-
"the {conflicting_tag_name} tag {conflicting} has state {perm} which forbids child {kind}es"
301+
"the {conflicting_tag_name} tag {conflicting} has state {perm} which forbids this {access}"
270302
));
271303
(title, details, conflicting_tag_name)
272304
}
273305
ProtectedTransition(transition) => {
274306
let conflicting_tag_name = "protected";
275-
let title = format!("{kind} through {accessed} is forbidden");
307+
let access = cause.print_as_access(/* is_foreign */ true);
276308
let details = vec![
277309
format!(
278310
"the accessed tag {accessed} is foreign to the {conflicting_tag_name} tag {conflicting} (i.e., it is not a child)"
279311
),
280312
format!(
281-
"the access would cause the {conflicting_tag_name} tag {conflicting} to transition {transition}"
313+
"this {access} would cause the {conflicting_tag_name} tag {conflicting} to transition {transition}"
282314
),
283315
format!(
284-
"this is {loss}, which is not allowed for protected tags",
316+
"this transition would be {loss}, which is not allowed for protected tags",
285317
loss = transition.summary(),
286318
),
287319
];
288320
(title, details, conflicting_tag_name)
289321
}
290322
ProtectedDealloc => {
291323
let conflicting_tag_name = "strongly protected";
292-
let title = format!("deallocation through {accessed} is forbidden");
293324
let details = vec![
294325
format!(
295326
"the allocation of the accessed tag {accessed} also contains the {conflicting_tag_name} tag {conflicting}"

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

Lines changed: 16 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -62,7 +62,14 @@ impl<'tcx> Tree {
6262
};
6363
let global = machine.borrow_tracker.as_ref().unwrap();
6464
let span = machine.current_span();
65-
self.perform_access(access_kind, tag, range, global, span)
65+
self.perform_access(
66+
access_kind,
67+
tag,
68+
range,
69+
global,
70+
span,
71+
diagnostics::AccessCause::Explicit(access_kind),
72+
)
6673
}
6774

6875
/// Check that this pointer has permission to deallocate this range.
@@ -273,7 +280,14 @@ trait EvalContextPrivExt<'mir: 'ecx, 'tcx: 'mir, 'ecx>: crate::MiriInterpCxExt<'
273280
// Count this reborrow as a read access
274281
let global = &this.machine.borrow_tracker.as_ref().unwrap();
275282
let span = this.machine.current_span();
276-
tree_borrows.perform_access(AccessKind::Read, orig_tag, range, global, span)?;
283+
tree_borrows.perform_access(
284+
AccessKind::Read,
285+
orig_tag,
286+
range,
287+
global,
288+
span,
289+
diagnostics::AccessCause::Reborrow,
290+
)?;
277291
if let Some(data_race) = alloc_extra.data_race.as_ref() {
278292
data_race.read(alloc_id, range, &this.machine)?;
279293
}

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

Lines changed: 13 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -349,7 +349,14 @@ impl<'tcx> Tree {
349349
global: &GlobalState,
350350
span: Span, // diagnostics
351351
) -> InterpResult<'tcx> {
352-
self.perform_access(AccessKind::Write, tag, access_range, global, span)?;
352+
self.perform_access(
353+
AccessKind::Write,
354+
tag,
355+
access_range,
356+
global,
357+
span,
358+
diagnostics::AccessCause::Dealloc,
359+
)?;
353360
for (perms_range, perms) in self.rperms.iter_mut(access_range.start, access_range.size) {
354361
TreeVisitor { nodes: &mut self.nodes, tag_mapping: &self.tag_mapping, perms }
355362
.traverse_parents_this_children_others(
@@ -368,7 +375,7 @@ impl<'tcx> Tree {
368375
let ErrHandlerArgs { error_kind, conflicting_info, accessed_info } = args;
369376
TbError {
370377
conflicting_info,
371-
access_kind: AccessKind::Write,
378+
access_cause: diagnostics::AccessCause::Dealloc,
372379
error_offset: perms_range.start,
373380
error_kind,
374381
accessed_info,
@@ -391,7 +398,8 @@ impl<'tcx> Tree {
391398
tag: BorTag,
392399
access_range: AllocRange,
393400
global: &GlobalState,
394-
span: Span, // diagnostics
401+
span: Span, // diagnostics
402+
access_cause: diagnostics::AccessCause, // diagnostics
395403
) -> InterpResult<'tcx> {
396404
for (perms_range, perms) in self.rperms.iter_mut(access_range.start, access_range.size) {
397405
TreeVisitor { nodes: &mut self.nodes, tag_mapping: &self.tag_mapping, perms }
@@ -456,8 +464,8 @@ impl<'tcx> Tree {
456464
if !transition.is_noop() {
457465
node.debug_info.history.push(diagnostics::Event {
458466
transition,
459-
access_kind,
460467
is_foreign: rel_pos.is_foreign(),
468+
access_cause,
461469
access_range,
462470
transition_range: perms_range.clone(),
463471
span,
@@ -472,7 +480,7 @@ impl<'tcx> Tree {
472480
let ErrHandlerArgs { error_kind, conflicting_info, accessed_info } = args;
473481
TbError {
474482
conflicting_info,
475-
access_kind,
483+
access_cause,
476484
error_offset: perms_range.start,
477485
error_kind,
478486
accessed_info,

src/tools/miri/tests/fail/both_borrows/alias_through_mutation.tree.stderr

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ LL | let _val = *target_alias;
66
|
77
= help: this indicates a potential bug in the program: it performed an invalid operation, but the Tree Borrows rules it violated are still experimental
88
= help: the accessed tag <TAG> is a child of the conflicting tag <TAG>
9-
= help: the conflicting tag <TAG> has state Disabled which forbids child read accesses
9+
= help: the conflicting tag <TAG> has state Disabled which forbids this child read access
1010
help: the accessed tag <TAG> was created here
1111
--> $DIR/alias_through_mutation.rs:LL:CC
1212
|
@@ -22,7 +22,7 @@ help: the conflicting tag <TAG> later transitioned to Disabled due to a foreign
2222
|
2323
LL | *target = 13;
2424
| ^^^^^^^^^^^^
25-
= help: this corresponds to a loss of read and write permissions
25+
= help: this transition corresponds to a loss of read and write permissions
2626
= note: BACKTRACE (of the first span):
2727
= note: inside `main` at $DIR/alias_through_mutation.rs:LL:CC
2828

src/tools/miri/tests/fail/both_borrows/aliasing_mut1.tree.stderr

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -5,18 +5,18 @@ LL | *x = 1;
55
| ^^^^^^ write access through <TAG> is forbidden
66
|
77
= help: this indicates a potential bug in the program: it performed an invalid operation, but the Tree Borrows rules it violated are still experimental
8-
= help: the accessed tag <TAG> has state Frozen which forbids child write accesses
8+
= help: the accessed tag <TAG> has state Frozen which forbids this child write access
99
help: the accessed tag <TAG> was created here, in the initial state Reserved
1010
--> $DIR/aliasing_mut1.rs:LL:CC
1111
|
1212
LL | pub fn safe(x: &mut i32, y: &mut i32) {
1313
| ^
14-
help: the accessed tag <TAG> later transitioned to Frozen due to a foreign read access at offsets [0x0..0x4]
14+
help: the accessed tag <TAG> later transitioned to Frozen due to a reborrow (acting as a foreign read access) at offsets [0x0..0x4]
1515
--> $DIR/aliasing_mut1.rs:LL:CC
1616
|
1717
LL | pub fn safe(x: &mut i32, y: &mut i32) {
1818
| ^
19-
= help: this corresponds to a loss of write permissions
19+
= help: this transition corresponds to a loss of write permissions
2020
= note: BACKTRACE (of the first span):
2121
= note: inside `safe` at $DIR/aliasing_mut1.rs:LL:CC
2222
note: inside `main`

src/tools/miri/tests/fail/both_borrows/aliasing_mut2.tree.stderr

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ LL | *y = 2;
55
| ^^^^^^ write access through <TAG> is forbidden
66
|
77
= help: this indicates a potential bug in the program: it performed an invalid operation, but the Tree Borrows rules it violated are still experimental
8-
= help: the accessed tag <TAG> has state Frozen which forbids child write accesses
8+
= help: the accessed tag <TAG> has state Frozen which forbids this child write access
99
help: the accessed tag <TAG> was created here, in the initial state Reserved
1010
--> $DIR/aliasing_mut2.rs:LL:CC
1111
|
@@ -16,7 +16,7 @@ help: the accessed tag <TAG> later transitioned to Frozen due to a foreign read
1616
|
1717
LL | let _v = *x;
1818
| ^^
19-
= help: this corresponds to a loss of write permissions
19+
= help: this transition corresponds to a loss of write permissions
2020
= note: BACKTRACE (of the first span):
2121
= note: inside `safe` at $DIR/aliasing_mut2.rs:LL:CC
2222
note: inside `main`

src/tools/miri/tests/fail/both_borrows/aliasing_mut3.tree.stderr

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -5,18 +5,18 @@ LL | *x = 1;
55
| ^^^^^^ write access through <TAG> is forbidden
66
|
77
= help: this indicates a potential bug in the program: it performed an invalid operation, but the Tree Borrows rules it violated are still experimental
8-
= help: the accessed tag <TAG> has state Frozen which forbids child write accesses
8+
= help: the accessed tag <TAG> has state Frozen which forbids this child write access
99
help: the accessed tag <TAG> was created here, in the initial state Reserved
1010
--> $DIR/aliasing_mut3.rs:LL:CC
1111
|
1212
LL | pub fn safe(x: &mut i32, y: &i32) {
1313
| ^
14-
help: the accessed tag <TAG> later transitioned to Frozen due to a foreign read access at offsets [0x0..0x4]
14+
help: the accessed tag <TAG> later transitioned to Frozen due to a reborrow (acting as a foreign read access) at offsets [0x0..0x4]
1515
--> $DIR/aliasing_mut3.rs:LL:CC
1616
|
1717
LL | pub fn safe(x: &mut i32, y: &i32) {
1818
| ^
19-
= help: this corresponds to a loss of write permissions
19+
= help: this transition corresponds to a loss of write permissions
2020
= note: BACKTRACE (of the first span):
2121
= note: inside `safe` at $DIR/aliasing_mut3.rs:LL:CC
2222
note: inside `main`

src/tools/miri/tests/fail/both_borrows/aliasing_mut4.tree.stderr

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,8 +6,8 @@ LL | ptr::write(dest, src);
66
|
77
= help: this indicates a potential bug in the program: it performed an invalid operation, but the Tree Borrows rules it violated are still experimental
88
= help: the accessed tag <TAG> is foreign to the protected tag <TAG> (i.e., it is not a child)
9-
= help: the access would cause the protected tag <TAG> to transition from Frozen to Disabled
10-
= help: this is a loss of read permissions, which is not allowed for protected tags
9+
= help: this foreign write access would cause the protected tag <TAG> to transition from Frozen to Disabled
10+
= help: this transition would be a loss of read permissions, which is not allowed for protected tags
1111
help: the accessed tag <TAG> was created here
1212
--> $DIR/aliasing_mut4.rs:LL:CC
1313
|

src/tools/miri/tests/fail/both_borrows/box_noalias_violation.tree.stderr

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -6,8 +6,8 @@ LL | *y
66
|
77
= help: this indicates a potential bug in the program: it performed an invalid operation, but the Tree Borrows rules it violated are still experimental
88
= help: the accessed tag <TAG> is foreign to the protected tag <TAG> (i.e., it is not a child)
9-
= help: the access would cause the protected tag <TAG> to transition from Active to Frozen
10-
= help: this is a loss of write permissions, which is not allowed for protected tags
9+
= help: this foreign read access would cause the protected tag <TAG> to transition from Active to Frozen
10+
= help: this transition would be a loss of write permissions, which is not allowed for protected tags
1111
help: the accessed tag <TAG> was created here
1212
--> $DIR/box_noalias_violation.rs:LL:CC
1313
|
@@ -23,7 +23,7 @@ help: the protected tag <TAG> later transitioned to Active due to a child write
2323
|
2424
LL | *x = 5;
2525
| ^^^^^^
26-
= help: this corresponds to the first write to a 2-phase borrowed mutable reference
26+
= help: this transition corresponds to the first write to a 2-phase borrowed mutable reference
2727
= note: BACKTRACE (of the first span):
2828
= note: inside `test` at $DIR/box_noalias_violation.rs:LL:CC
2929
note: inside `main`

src/tools/miri/tests/fail/both_borrows/buggy_as_mut_slice.tree.stderr

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ LL | v2[1] = 7;
66
|
77
= help: this indicates a potential bug in the program: it performed an invalid operation, but the Tree Borrows rules it violated are still experimental
88
= help: the accessed tag <TAG> is a child of the conflicting tag <TAG>
9-
= help: the conflicting tag <TAG> has state Disabled which forbids child write accesses
9+
= help: the conflicting tag <TAG> has state Disabled which forbids this child write access
1010
help: the accessed tag <TAG> was created here
1111
--> $DIR/buggy_as_mut_slice.rs:LL:CC
1212
|
@@ -22,7 +22,7 @@ help: the conflicting tag <TAG> later transitioned to Disabled due to a foreign
2222
|
2323
LL | v1[1] = 5;
2424
| ^^^^^^^^^
25-
= help: this corresponds to a loss of read and write permissions
25+
= help: this transition corresponds to a loss of read and write permissions
2626
= note: BACKTRACE (of the first span):
2727
= note: inside `main` at $DIR/buggy_as_mut_slice.rs:LL:CC
2828

src/tools/miri/tests/fail/both_borrows/buggy_split_at_mut.tree.stderr

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ LL | b[1] = 6;
66
|
77
= help: this indicates a potential bug in the program: it performed an invalid operation, but the Tree Borrows rules it violated are still experimental
88
= help: the accessed tag <TAG> is a child of the conflicting tag <TAG>
9-
= help: the conflicting tag <TAG> has state Disabled which forbids child write accesses
9+
= help: the conflicting tag <TAG> has state Disabled which forbids this child write access
1010
help: the accessed tag <TAG> was created here
1111
--> $DIR/buggy_split_at_mut.rs:LL:CC
1212
|
@@ -22,7 +22,7 @@ help: the conflicting tag <TAG> later transitioned to Disabled due to a foreign
2222
|
2323
LL | a[1] = 5;
2424
| ^^^^^^^^
25-
= help: this corresponds to a loss of read and write permissions
25+
= help: this transition corresponds to a loss of read and write permissions
2626
= note: BACKTRACE (of the first span):
2727
= note: inside `main` at $DIR/buggy_split_at_mut.rs:LL:CC
2828

src/tools/miri/tests/fail/both_borrows/illegal_write1.tree.stderr

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ LL | unsafe { *x = 42 };
55
| ^^^^^^^ write access through <TAG> is forbidden
66
|
77
= help: this indicates a potential bug in the program: it performed an invalid operation, but the Tree Borrows rules it violated are still experimental
8-
= help: the accessed tag <TAG> has state Frozen which forbids child write accesses
8+
= help: the accessed tag <TAG> has state Frozen which forbids this child write access
99
help: the accessed tag <TAG> was created here, in the initial state Frozen
1010
--> $DIR/illegal_write1.rs:LL:CC
1111
|

0 commit comments

Comments
 (0)