Skip to content

Commit

Permalink
Make TB tree traversal bottom-up
Browse files Browse the repository at this point in the history
In preparation for rust-lang#3837, the tree traversal needs to be made bottom-up,
because the current top-down tree traversal, coupled with that PR's
changes to the garbage collector, can introduce non-deterministic error
messages if the GC removes a parent tag of the accessed tag that would
have triggered the error first.

This is a breaking change for the diagnostics emitted by TB. The
implemented semantics stay the same.
  • Loading branch information
JoJoDeveloping committed Aug 25, 2024
1 parent 242df69 commit bbc5af1
Show file tree
Hide file tree
Showing 20 changed files with 229 additions and 272 deletions.
289 changes: 169 additions & 120 deletions src/borrow_tracker/tree_borrows/tree.rs

Large diffs are not rendered by default.

4 changes: 4 additions & 0 deletions src/borrow_tracker/tree_borrows/unimap.rs
Original file line number Diff line number Diff line change
Expand Up @@ -221,6 +221,10 @@ impl<'a, V> UniEntry<'a, V> {
}
self.inner.as_mut().unwrap()
}

pub fn get(&self) -> Option<&V> {
self.inner.as_ref()
}
}

mod tests {
Expand Down
14 changes: 4 additions & 10 deletions tests/fail/both_borrows/alias_through_mutation.tree.stderr
Original file line number Diff line number Diff line change
Expand Up @@ -5,24 +5,18 @@ LL | let _val = *target_alias;
| ^^^^^^^^^^^^^ read access through <TAG> at ALLOC[0x0] is forbidden
|
= help: this indicates a potential bug in the program: it performed an invalid operation, but the Tree Borrows rules it violated are still experimental
= help: the accessed tag <TAG> is a child of the conflicting tag <TAG>
= help: the conflicting tag <TAG> has state Disabled which forbids this child read access
help: the accessed tag <TAG> was created here
= help: the accessed tag <TAG> has state Disabled which forbids this child read access
help: the accessed tag <TAG> was created here, in the initial state Frozen
--> $DIR/alias_through_mutation.rs:LL:CC
|
LL | *x = &mut *(target as *mut _);
| ^^^^^^^^^^^^^^^^^^^^^^^^
help: the conflicting tag <TAG> was created here, in the initial state Reserved
--> $DIR/alias_through_mutation.rs:LL:CC
|
LL | retarget(&mut target_alias, target);
| ^^^^^^
help: the conflicting tag <TAG> later transitioned to Disabled due to a foreign write access at offsets [0x0..0x4]
help: the accessed tag <TAG> later transitioned to Disabled due to a foreign write access at offsets [0x0..0x4]
--> $DIR/alias_through_mutation.rs:LL:CC
|
LL | *target = 13;
| ^^^^^^^^^^^^
= help: this transition corresponds to a loss of read and write permissions
= help: this transition corresponds to a loss of read permissions
= note: BACKTRACE (of the first span):
= note: inside `main` at $DIR/alias_through_mutation.rs:LL:CC

Expand Down
12 changes: 3 additions & 9 deletions tests/fail/both_borrows/box_exclusive_violation1.tree.stderr
Original file line number Diff line number Diff line change
Expand Up @@ -5,19 +5,13 @@ LL | *LEAK = 7;
| ^^^^^^^^^ write access through <TAG> at ALLOC[0x0] is forbidden
|
= help: this indicates a potential bug in the program: it performed an invalid operation, but the Tree Borrows rules it violated are still experimental
= help: the accessed tag <TAG> is a child of the conflicting tag <TAG>
= help: the conflicting tag <TAG> has state Disabled which forbids this child write access
help: the accessed tag <TAG> was created here
= help: the accessed tag <TAG> has state Disabled which forbids this child write access
help: the accessed tag <TAG> was created here, in the initial state Frozen
--> $DIR/box_exclusive_violation1.rs:LL:CC
|
LL | fn unknown_code_1(x: &i32) {
| ^
help: the conflicting tag <TAG> was created here, in the initial state Frozen
--> $DIR/box_exclusive_violation1.rs:LL:CC
|
LL | unknown_code_1(&*our);
| ^^^^^
help: the conflicting tag <TAG> later transitioned to Disabled due to a foreign write access at offsets [0x0..0x4]
help: the accessed tag <TAG> later transitioned to Disabled due to a foreign write access at offsets [0x0..0x4]
--> $DIR/box_exclusive_violation1.rs:LL:CC
|
LL | *our = 5;
Expand Down
12 changes: 3 additions & 9 deletions tests/fail/both_borrows/buggy_as_mut_slice.tree.stderr
Original file line number Diff line number Diff line change
Expand Up @@ -5,19 +5,13 @@ LL | v2[1] = 7;
| ^^^^^^^^^ write access through <TAG> at ALLOC[0x4] is forbidden
|
= help: this indicates a potential bug in the program: it performed an invalid operation, but the Tree Borrows rules it violated are still experimental
= help: the accessed tag <TAG> is a child of the conflicting tag <TAG>
= help: the conflicting tag <TAG> has state Disabled which forbids this child write access
help: the accessed tag <TAG> was created here
= help: the accessed tag <TAG> has state Disabled which forbids this child write access
help: the accessed tag <TAG> was created here, in the initial state Reserved
--> $DIR/buggy_as_mut_slice.rs:LL:CC
|
LL | let v2 = safe::as_mut_slice(&v);
| ^^^^^^^^^^^^^^^^^^^^^^
help: the conflicting tag <TAG> was created here, in the initial state Reserved
--> $DIR/buggy_as_mut_slice.rs:LL:CC
|
LL | unsafe { from_raw_parts_mut(self_.as_ptr() as *mut T, self_.len()) }
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
help: the conflicting tag <TAG> later transitioned to Disabled due to a foreign write access at offsets [0x4..0x8]
help: the accessed tag <TAG> later transitioned to Disabled due to a foreign write access at offsets [0x4..0x8]
--> $DIR/buggy_as_mut_slice.rs:LL:CC
|
LL | v1[1] = 5;
Expand Down
12 changes: 3 additions & 9 deletions tests/fail/both_borrows/buggy_split_at_mut.tree.stderr
Original file line number Diff line number Diff line change
Expand Up @@ -5,19 +5,13 @@ LL | b[1] = 6;
| ^^^^^^^^ write access through <TAG> at ALLOC[0x4] is forbidden
|
= help: this indicates a potential bug in the program: it performed an invalid operation, but the Tree Borrows rules it violated are still experimental
= help: the accessed tag <TAG> is a child of the conflicting tag <TAG>
= help: the conflicting tag <TAG> has state Disabled which forbids this child write access
help: the accessed tag <TAG> was created here
= help: the accessed tag <TAG> has state Disabled which forbids this child write access
help: the accessed tag <TAG> was created here, in the initial state Reserved
--> $DIR/buggy_split_at_mut.rs:LL:CC
|
LL | let (a, b) = safe::split_at_mut(&mut array, 0);
| ^
help: the conflicting tag <TAG> was created here, in the initial state Reserved
--> $DIR/buggy_split_at_mut.rs:LL:CC
|
LL | from_raw_parts_mut(ptr.offset(mid as isize), len - mid),
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
help: the conflicting tag <TAG> later transitioned to Disabled due to a foreign write access at offsets [0x4..0x8]
help: the accessed tag <TAG> later transitioned to Disabled due to a foreign write access at offsets [0x4..0x8]
--> $DIR/buggy_split_at_mut.rs:LL:CC
|
LL | a[1] = 5;
Expand Down
12 changes: 3 additions & 9 deletions tests/fail/both_borrows/illegal_write5.tree.stderr
Original file line number Diff line number Diff line change
Expand Up @@ -5,19 +5,13 @@ LL | let _val = *xref;
| ^^^^^ read access through <TAG> at ALLOC[0x0] is forbidden
|
= help: this indicates a potential bug in the program: it performed an invalid operation, but the Tree Borrows rules it violated are still experimental
= help: the accessed tag <TAG> is a child of the conflicting tag <TAG>
= help: the conflicting tag <TAG> has state Disabled which forbids this child read access
help: the accessed tag <TAG> was created here
= help: the accessed tag <TAG> has state Disabled which forbids this child read access
help: the accessed tag <TAG> was created here, in the initial state Reserved
--> $DIR/illegal_write5.rs:LL:CC
|
LL | let xref = unsafe { &mut *xraw };
| ^^^^^^^^^^
help: the conflicting tag <TAG> was created here, in the initial state Reserved
--> $DIR/illegal_write5.rs:LL:CC
|
LL | let xref = unsafe { &mut *xraw };
| ^^^^^^^^^^
help: the conflicting tag <TAG> later transitioned to Disabled due to a foreign write access at offsets [0x0..0x4]
help: the accessed tag <TAG> later transitioned to Disabled due to a foreign write access at offsets [0x0..0x4]
--> $DIR/illegal_write5.rs:LL:CC
|
LL | unsafe { *xraw = 15 };
Expand Down
12 changes: 3 additions & 9 deletions tests/fail/both_borrows/load_invalid_shr.tree.stderr
Original file line number Diff line number Diff line change
Expand Up @@ -5,19 +5,13 @@ LL | let _val = *xref_in_mem;
| ^^^^^^^^^^^^ reborrow through <TAG> at ALLOC[0x0] is forbidden
|
= help: this indicates a potential bug in the program: it performed an invalid operation, but the Tree Borrows rules it violated are still experimental
= help: the accessed tag <TAG> is a child of the conflicting tag <TAG>
= help: the conflicting tag <TAG> has state Disabled which forbids this reborrow (acting as a child read access)
help: the accessed tag <TAG> was created here
= help: the accessed tag <TAG> has state Disabled which forbids this reborrow (acting as a child read access)
help: the accessed tag <TAG> was created here, in the initial state Frozen
--> $DIR/load_invalid_shr.rs:LL:CC
|
LL | let xref_in_mem = Box::new(xref);
| ^^^^^^^^^^^^^^
help: the conflicting tag <TAG> was created here, in the initial state Frozen
--> $DIR/load_invalid_shr.rs:LL:CC
|
LL | let xref = unsafe { &*xraw };
| ^^^^^^
help: the conflicting tag <TAG> later transitioned to Disabled due to a foreign write access at offsets [0x0..0x4]
help: the accessed tag <TAG> later transitioned to Disabled due to a foreign write access at offsets [0x0..0x4]
--> $DIR/load_invalid_shr.rs:LL:CC
|
LL | unsafe { *xraw = 42 }; // unfreeze
Expand Down
12 changes: 3 additions & 9 deletions tests/fail/both_borrows/mut_exclusive_violation1.tree.stderr
Original file line number Diff line number Diff line change
Expand Up @@ -5,19 +5,13 @@ LL | *LEAK = 7;
| ^^^^^^^^^ write access through <TAG> at ALLOC[0x0] is forbidden
|
= help: this indicates a potential bug in the program: it performed an invalid operation, but the Tree Borrows rules it violated are still experimental
= help: the accessed tag <TAG> is a child of the conflicting tag <TAG>
= help: the conflicting tag <TAG> has state Disabled which forbids this child write access
help: the accessed tag <TAG> was created here
= help: the accessed tag <TAG> has state Disabled which forbids this child write access
help: the accessed tag <TAG> was created here, in the initial state Frozen
--> $DIR/mut_exclusive_violation1.rs:LL:CC
|
LL | fn unknown_code_1(x: &i32) {
| ^
help: the conflicting tag <TAG> was created here, in the initial state Frozen
--> $DIR/mut_exclusive_violation1.rs:LL:CC
|
LL | unknown_code_1(&*our);
| ^^^^^
help: the conflicting tag <TAG> later transitioned to Disabled due to a foreign write access at offsets [0x0..0x4]
help: the accessed tag <TAG> later transitioned to Disabled due to a foreign write access at offsets [0x0..0x4]
--> $DIR/mut_exclusive_violation1.rs:LL:CC
|
LL | *our = 5;
Expand Down
12 changes: 3 additions & 9 deletions tests/fail/both_borrows/mut_exclusive_violation2.tree.stderr
Original file line number Diff line number Diff line change
Expand Up @@ -5,19 +5,13 @@ LL | *raw1 = 3;
| ^^^^^^^^^ write access through <TAG> at ALLOC[0x0] is forbidden
|
= help: this indicates a potential bug in the program: it performed an invalid operation, but the Tree Borrows rules it violated are still experimental
= help: the accessed tag <TAG> is a child of the conflicting tag <TAG>
= help: the conflicting tag <TAG> has state Disabled which forbids this child write access
help: the accessed tag <TAG> was created here
= help: the accessed tag <TAG> has state Disabled which forbids this child write access
help: the accessed tag <TAG> was created here, in the initial state Reserved
--> $DIR/mut_exclusive_violation2.rs:LL:CC
|
LL | let raw1 = ptr1.as_mut();
| ^^^^^^^^^^^^^
help: the conflicting tag <TAG> was created here, in the initial state Reserved
--> $DIR/mut_exclusive_violation2.rs:LL:CC
|
LL | let raw1 = ptr1.as_mut();
| ^^^^^^^^^^^^^
help: the conflicting tag <TAG> later transitioned to Disabled due to a foreign write access at offsets [0x0..0x4]
help: the accessed tag <TAG> later transitioned to Disabled due to a foreign write access at offsets [0x0..0x4]
--> $DIR/mut_exclusive_violation2.rs:LL:CC
|
LL | *raw2 = 2;
Expand Down
12 changes: 3 additions & 9 deletions tests/fail/both_borrows/pass_invalid_shr_option.tree.stderr
Original file line number Diff line number Diff line change
Expand Up @@ -5,19 +5,13 @@ LL | foo(some_xref);
| ^^^^^^^^^ reborrow through <TAG> at ALLOC[0x0] is forbidden
|
= help: this indicates a potential bug in the program: it performed an invalid operation, but the Tree Borrows rules it violated are still experimental
= help: the accessed tag <TAG> is a child of the conflicting tag <TAG>
= help: the conflicting tag <TAG> has state Disabled which forbids this reborrow (acting as a child read access)
help: the accessed tag <TAG> was created here
= help: the accessed tag <TAG> has state Disabled which forbids this reborrow (acting as a child read access)
help: the accessed tag <TAG> was created here, in the initial state Frozen
--> $DIR/pass_invalid_shr_option.rs:LL:CC
|
LL | let some_xref = unsafe { Some(&*xraw) };
| ^^^^^^^^^^^^
help: the conflicting tag <TAG> was created here, in the initial state Frozen
--> $DIR/pass_invalid_shr_option.rs:LL:CC
|
LL | let some_xref = unsafe { Some(&*xraw) };
| ^^^^^^
help: the conflicting tag <TAG> later transitioned to Disabled due to a foreign write access at offsets [0x0..0x4]
help: the accessed tag <TAG> later transitioned to Disabled due to a foreign write access at offsets [0x0..0x4]
--> $DIR/pass_invalid_shr_option.rs:LL:CC
|
LL | unsafe { *xraw = 42 }; // unfreeze
Expand Down
12 changes: 3 additions & 9 deletions tests/fail/both_borrows/pass_invalid_shr_tuple.tree.stderr
Original file line number Diff line number Diff line change
Expand Up @@ -5,19 +5,13 @@ LL | foo(pair_xref);
| ^^^^^^^^^ reborrow through <TAG> at ALLOC[0x0] is forbidden
|
= help: this indicates a potential bug in the program: it performed an invalid operation, but the Tree Borrows rules it violated are still experimental
= help: the accessed tag <TAG> is a child of the conflicting tag <TAG>
= help: the conflicting tag <TAG> has state Disabled which forbids this reborrow (acting as a child read access)
help: the accessed tag <TAG> was created here
= help: the accessed tag <TAG> has state Disabled which forbids this reborrow (acting as a child read access)
help: the accessed tag <TAG> was created here, in the initial state Frozen
--> $DIR/pass_invalid_shr_tuple.rs:LL:CC
|
LL | let pair_xref = unsafe { (&*xraw0, &*xraw1) };
| ^^^^^^^^^^^^^^^^^^
help: the conflicting tag <TAG> was created here, in the initial state Frozen
--> $DIR/pass_invalid_shr_tuple.rs:LL:CC
|
LL | let pair_xref = unsafe { (&*xraw0, &*xraw1) };
| ^^^^^^^
help: the conflicting tag <TAG> later transitioned to Disabled due to a foreign write access at offsets [0x0..0x4]
help: the accessed tag <TAG> later transitioned to Disabled due to a foreign write access at offsets [0x0..0x4]
--> $DIR/pass_invalid_shr_tuple.rs:LL:CC
|
LL | unsafe { *xraw0 = 42 }; // unfreeze
Expand Down
12 changes: 3 additions & 9 deletions tests/fail/both_borrows/return_invalid_shr_option.tree.stderr
Original file line number Diff line number Diff line change
Expand Up @@ -5,19 +5,13 @@ LL | ret
| ^^^ reborrow through <TAG> at ALLOC[0x4] is forbidden
|
= help: this indicates a potential bug in the program: it performed an invalid operation, but the Tree Borrows rules it violated are still experimental
= help: the accessed tag <TAG> is a child of the conflicting tag <TAG>
= help: the conflicting tag <TAG> has state Disabled which forbids this reborrow (acting as a child read access)
help: the accessed tag <TAG> was created here
= help: the accessed tag <TAG> has state Disabled which forbids this reborrow (acting as a child read access)
help: the accessed tag <TAG> was created here, in the initial state Frozen
--> $DIR/return_invalid_shr_option.rs:LL:CC
|
LL | let ret = Some(unsafe { &(*xraw).1 });
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^
help: the conflicting tag <TAG> was created here, in the initial state Frozen
--> $DIR/return_invalid_shr_option.rs:LL:CC
|
LL | let ret = Some(unsafe { &(*xraw).1 });
| ^^^^^^^^^^
help: the conflicting tag <TAG> later transitioned to Disabled due to a foreign write access at offsets [0x0..0x8]
help: the accessed tag <TAG> later transitioned to Disabled due to a foreign write access at offsets [0x0..0x8]
--> $DIR/return_invalid_shr_option.rs:LL:CC
|
LL | unsafe { *xraw = (42, 23) }; // unfreeze
Expand Down
12 changes: 3 additions & 9 deletions tests/fail/both_borrows/return_invalid_shr_tuple.tree.stderr
Original file line number Diff line number Diff line change
Expand Up @@ -5,19 +5,13 @@ LL | ret
| ^^^ reborrow through <TAG> at ALLOC[0x4] is forbidden
|
= help: this indicates a potential bug in the program: it performed an invalid operation, but the Tree Borrows rules it violated are still experimental
= help: the accessed tag <TAG> is a child of the conflicting tag <TAG>
= help: the conflicting tag <TAG> has state Disabled which forbids this reborrow (acting as a child read access)
help: the accessed tag <TAG> was created here
= help: the accessed tag <TAG> has state Disabled which forbids this reborrow (acting as a child read access)
help: the accessed tag <TAG> was created here, in the initial state Frozen
--> $DIR/return_invalid_shr_tuple.rs:LL:CC
|
LL | let ret = (unsafe { &(*xraw).1 },);
| ^^^^^^^^^^^^^^^^^^^^^^^^
help: the conflicting tag <TAG> was created here, in the initial state Frozen
--> $DIR/return_invalid_shr_tuple.rs:LL:CC
|
LL | let ret = (unsafe { &(*xraw).1 },);
| ^^^^^^^^^^
help: the conflicting tag <TAG> later transitioned to Disabled due to a foreign write access at offsets [0x0..0x8]
help: the accessed tag <TAG> later transitioned to Disabled due to a foreign write access at offsets [0x0..0x8]
--> $DIR/return_invalid_shr_tuple.rs:LL:CC
|
LL | unsafe { *xraw = (42, 23) }; // unfreeze
Expand Down
10 changes: 2 additions & 8 deletions tests/fail/both_borrows/shr_frozen_violation1.tree.stderr
Original file line number Diff line number Diff line change
Expand Up @@ -5,18 +5,12 @@ LL | *(x as *const i32 as *mut i32) = 7;
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ write access through <TAG> at ALLOC[0x0] is forbidden
|
= help: this indicates a potential bug in the program: it performed an invalid operation, but the Tree Borrows rules it violated are still experimental
= help: the accessed tag <TAG> is a child of the conflicting tag <TAG>
= help: the conflicting tag <TAG> has state Frozen which forbids this child write access
help: the accessed tag <TAG> was created here
= help: the accessed tag <TAG> has state Frozen which forbids this child write access
help: the accessed tag <TAG> was created here, in the initial state Frozen
--> $DIR/shr_frozen_violation1.rs:LL:CC
|
LL | fn unknown_code(x: &i32) {
| ^
help: the conflicting tag <TAG> was created here, in the initial state Frozen
--> $DIR/shr_frozen_violation1.rs:LL:CC
|
LL | unknown_code(&*x);
| ^^^
= note: BACKTRACE (of the first span):
= note: inside `unknown_code` at $DIR/shr_frozen_violation1.rs:LL:CC
note: inside `foo`
Expand Down
14 changes: 4 additions & 10 deletions tests/fail/tree_borrows/alternate-read-write.stderr
Original file line number Diff line number Diff line change
Expand Up @@ -5,25 +5,19 @@ LL | *y += 1; // Failure
| ^^^^^^^ write access through <TAG> at ALLOC[0x0] is forbidden
|
= help: this indicates a potential bug in the program: it performed an invalid operation, but the Tree Borrows rules it violated are still experimental
= help: the accessed tag <TAG> is a child of the conflicting tag <TAG>
= help: the conflicting tag <TAG> has state Frozen which forbids this child write access
help: the accessed tag <TAG> was created here
= help: the accessed tag <TAG> has state Frozen which forbids this child write access
help: the accessed tag <TAG> was created here, in the initial state Reserved
--> $DIR/alternate-read-write.rs:LL:CC
|
LL | let y = unsafe { &mut *(x as *mut u8) };
| ^^^^^^^^^^^^^^^^^^^^
help: the conflicting tag <TAG> was created here, in the initial state Reserved
--> $DIR/alternate-read-write.rs:LL:CC
|
LL | let y = unsafe { &mut *(x as *mut u8) };
| ^^^^^^^^^^^^^^^^^^^^
help: the conflicting tag <TAG> later transitioned to Active due to a child write access at offsets [0x0..0x1]
help: the accessed tag <TAG> later transitioned to Active due to a child write access at offsets [0x0..0x1]
--> $DIR/alternate-read-write.rs:LL:CC
|
LL | *y += 1; // Success
| ^^^^^^^
= help: this transition corresponds to the first write to a 2-phase borrowed mutable reference
help: the conflicting tag <TAG> later transitioned to Frozen due to a foreign read access at offsets [0x0..0x1]
help: the accessed tag <TAG> later transitioned to Frozen due to a foreign read access at offsets [0x0..0x1]
--> $DIR/alternate-read-write.rs:LL:CC
|
LL | let _val = *x;
Expand Down
Loading

0 comments on commit bbc5af1

Please sign in to comment.