Skip to content

Include the name of the created tag in TB's Reborrow events #4387

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 1 commit into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 4 additions & 3 deletions src/borrow_tracker/tree_borrows/diagnostics.rs
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ use crate::*;
#[derive(Clone, Copy, Debug)]
pub enum AccessCause {
Explicit(AccessKind),
Reborrow,
Reborrow(BorTag),
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
Reborrow(BorTag),
/// The tag here is the one *newly created* by the reborrow that caused the access.
Reborrow(BorTag),

Dealloc,
FnExit(AccessKind),
}
Expand All @@ -24,7 +24,7 @@ impl fmt::Display for AccessCause {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match self {
Self::Explicit(kind) => write!(f, "{kind}"),
Self::Reborrow => write!(f, "reborrow"),
Self::Reborrow(tag) => write!(f, "reborrow to create {tag:?}"),
Self::Dealloc => write!(f, "deallocation"),
// This is dead code, since the protector release access itself can never
// cause UB (while the protector is active, if some other access invalidates
Expand All @@ -40,7 +40,8 @@ impl AccessCause {
let rel = if is_foreign { "foreign" } else { "child" };
match self {
Self::Explicit(kind) => format!("{rel} {kind}"),
Self::Reborrow => format!("reborrow (acting as a {rel} read access)"),
Self::Reborrow(tag) =>
format!("reborrow to create {tag:?} (acting as a {rel} read access)"),
Self::Dealloc => format!("deallocation (acting as a {rel} write access)"),
Self::FnExit(kind) => format!("protector release (acting as a {rel} {kind})"),
}
Expand Down
6 changes: 5 additions & 1 deletion src/borrow_tracker/tree_borrows/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -375,7 +375,11 @@ trait EvalContextPrivExt<'tcx>: crate::MiriInterpCxExt<'tcx> {

tree_borrows.perform_access(
orig_tag,
Some((range_in_alloc, AccessKind::Read, diagnostics::AccessCause::Reborrow)),
Some((
range_in_alloc,
AccessKind::Read,
diagnostics::AccessCause::Reborrow(new_tag),
)),
this.machine.borrow_tracker.as_ref().unwrap(),
alloc_id,
this.machine.current_span(),
Expand Down
2 changes: 1 addition & 1 deletion tests/fail/async-shared-mutable.tree.stderr
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ help: the accessed tag <TAG> later transitioned to Active due to a child write a
LL | *x = 1;
| ^^^^^^
= help: this transition corresponds to the first write to a 2-phase borrowed mutable reference
help: the accessed tag <TAG> later transitioned to Frozen due to a reborrow (acting as a foreign read access) at offsets [OFFSET]
help: the accessed tag <TAG> later transitioned to Frozen due to a reborrow to create <TAG> (acting as a foreign read access) at offsets [OFFSET]
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is it clear that the newly created tag is always the more interesting one here, rather than the tag of the pointer that is the input to the reborrow?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, because it can be traced with -Zmiri-track-pointer-tag (which tells you the parent tag), but you can't find the child tag from the parent.

Copy link
Member Author

@saethlin saethlin Jun 9, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah, that's why the alternative solution to the linked issue is to make tag tracking also log reborrows of the tracked tag. But I suspect that will be an unusable amount of information written to the terminal.

--> tests/fail/async-shared-mutable.rs:LL:CC
|
LL | let _: Pin<&_> = f.as_ref(); // Or: `f.as_mut().into_ref()`.
Expand Down
2 changes: 1 addition & 1 deletion tests/fail/both_borrows/aliasing_mut1.tree.stderr
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ help: the accessed tag <TAG> was created here, in the initial state Reserved
|
LL | pub fn safe(x: &mut i32, y: &mut i32) {
| ^
help: the accessed tag <TAG> later transitioned to Reserved (conflicted) due to a reborrow (acting as a foreign read access) at offsets [0x0..0x4]
help: the accessed tag <TAG> later transitioned to Reserved (conflicted) due to a reborrow to create <TAG> (acting as a foreign read access) at offsets [0x0..0x4]
--> tests/fail/both_borrows/aliasing_mut1.rs:LL:CC
|
LL | pub fn safe(x: &mut i32, y: &mut i32) {
Expand Down
2 changes: 1 addition & 1 deletion tests/fail/both_borrows/aliasing_mut3.tree.stderr
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ help: the accessed tag <TAG> was created here, in the initial state Reserved
|
LL | pub fn safe(x: &mut i32, y: &i32) {
| ^
help: the accessed tag <TAG> later transitioned to Reserved (conflicted) due to a reborrow (acting as a foreign read access) at offsets [0x0..0x4]
help: the accessed tag <TAG> later transitioned to Reserved (conflicted) due to a reborrow to create <TAG> (acting as a foreign read access) at offsets [0x0..0x4]
--> tests/fail/both_borrows/aliasing_mut3.rs:LL:CC
|
LL | pub fn safe(x: &mut i32, y: &i32) {
Expand Down
2 changes: 1 addition & 1 deletion tests/fail/both_borrows/load_invalid_shr.rs
Original file line number Diff line number Diff line change
Expand Up @@ -12,5 +12,5 @@ fn main() {
unsafe { *xraw = 42 }; // unfreeze
let _val = *xref_in_mem;
//~[stack]^ ERROR: /retag .* tag does not exist in the borrow stack/
//~[tree]| ERROR: /reborrow through .* is forbidden/
//~[tree]| ERROR: /reborrow to create .* through .* is forbidden/
}
6 changes: 3 additions & 3 deletions tests/fail/both_borrows/load_invalid_shr.tree.stderr
Original file line number Diff line number Diff line change
@@ -1,11 +1,11 @@
error: Undefined Behavior: reborrow through <TAG> at ALLOC[0x0] is forbidden
error: Undefined Behavior: reborrow to create <TAG> through <TAG> at ALLOC[0x0] is forbidden
--> tests/fail/both_borrows/load_invalid_shr.rs:LL:CC
|
LL | let _val = *xref_in_mem;
| ^^^^^^^^^^^^ reborrow through <TAG> at ALLOC[0x0] is forbidden
| ^^^^^^^^^^^^ reborrow to create <TAG> 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> has state Disabled which forbids this reborrow (acting as a child read access)
= help: the accessed tag <TAG> has state Disabled which forbids this reborrow to create <TAG> (acting as a child read access)
help: the accessed tag <TAG> was created here, in the initial state Frozen
--> tests/fail/both_borrows/load_invalid_shr.rs:LL:CC
|
Expand Down
2 changes: 1 addition & 1 deletion tests/fail/both_borrows/newtype_pair_retagging.tree.stderr
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ help: the protected tag <TAG> was created here, in the initial state Reserved
|
LL | fn dealloc_while_running(_n: Newtype<'_>, dealloc: impl FnOnce()) {
| ^^
help: the protected tag <TAG> later transitioned to Reserved (conflicted) due to a reborrow (acting as a foreign read access) at offsets [0x0..0x4]
help: the protected tag <TAG> later transitioned to Reserved (conflicted) due to a reborrow to create <TAG> (acting as a foreign read access) at offsets [0x0..0x4]
--> tests/fail/both_borrows/newtype_pair_retagging.rs:LL:CC
|
LL | || drop(Box::from_raw(ptr)),
Expand Down
2 changes: 1 addition & 1 deletion tests/fail/both_borrows/newtype_retagging.tree.stderr
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ help: the protected tag <TAG> was created here, in the initial state Reserved
|
LL | fn dealloc_while_running(_n: Newtype<'_>, dealloc: impl FnOnce()) {
| ^^
help: the protected tag <TAG> later transitioned to Reserved (conflicted) due to a reborrow (acting as a foreign read access) at offsets [0x0..0x4]
help: the protected tag <TAG> later transitioned to Reserved (conflicted) due to a reborrow to create <TAG> (acting as a foreign read access) at offsets [0x0..0x4]
--> tests/fail/both_borrows/newtype_retagging.rs:LL:CC
|
LL | || drop(Box::from_raw(ptr)),
Expand Down
2 changes: 1 addition & 1 deletion tests/fail/both_borrows/pass_invalid_shr.rs
Original file line number Diff line number Diff line change
Expand Up @@ -11,5 +11,5 @@ fn main() {
unsafe { *xraw = 42 }; // unfreeze
foo(xref);
//~[stack]^ ERROR: /retag .* tag does not exist in the borrow stack/
//~[tree]| ERROR: /reborrow through .* is forbidden/
//~[tree]| ERROR: /reborrow to create .* through .* is forbidden/
}
6 changes: 3 additions & 3 deletions tests/fail/both_borrows/pass_invalid_shr.tree.stderr
Original file line number Diff line number Diff line change
@@ -1,11 +1,11 @@
error: Undefined Behavior: reborrow through <TAG> at ALLOC[0x0] is forbidden
error: Undefined Behavior: reborrow to create <TAG> through <TAG> at ALLOC[0x0] is forbidden
--> tests/fail/both_borrows/pass_invalid_shr.rs:LL:CC
|
LL | foo(xref);
| ^^^^ reborrow through <TAG> at ALLOC[0x0] is forbidden
| ^^^^ reborrow to create <TAG> 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> has state Disabled which forbids this reborrow (acting as a child read access)
= help: the accessed tag <TAG> has state Disabled which forbids this reborrow to create <TAG> (acting as a child read access)
help: the accessed tag <TAG> was created here, in the initial state Frozen
--> tests/fail/both_borrows/pass_invalid_shr.rs:LL:CC
|
Expand Down
2 changes: 1 addition & 1 deletion tests/fail/both_borrows/pass_invalid_shr_option.rs
Original file line number Diff line number Diff line change
Expand Up @@ -11,5 +11,5 @@ fn main() {
unsafe { *xraw = 42 }; // unfreeze
foo(some_xref);
//~[stack]^ ERROR: /retag .* tag does not exist in the borrow stack/
//~[tree]| ERROR: /reborrow through .* is forbidden/
//~[tree]| ERROR: /reborrow to create .* through .* is forbidden/
}
6 changes: 3 additions & 3 deletions tests/fail/both_borrows/pass_invalid_shr_option.tree.stderr
Original file line number Diff line number Diff line change
@@ -1,11 +1,11 @@
error: Undefined Behavior: reborrow through <TAG> at ALLOC[0x0] is forbidden
error: Undefined Behavior: reborrow to create <TAG> through <TAG> at ALLOC[0x0] is forbidden
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The new tag doesn't matter here, does it? Creating it failed, so it can't possibly occur anywhere else in the state already.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If the above is correct then I don't think the new tag should be shown here.

--> tests/fail/both_borrows/pass_invalid_shr_option.rs:LL:CC
|
LL | foo(some_xref);
| ^^^^^^^^^ reborrow through <TAG> at ALLOC[0x0] is forbidden
| ^^^^^^^^^ reborrow to create <TAG> 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> has state Disabled which forbids this reborrow (acting as a child read access)
= help: the accessed tag <TAG> has state Disabled which forbids this reborrow to create <TAG> (acting as a child read access)
help: the accessed tag <TAG> was created here, in the initial state Frozen
--> tests/fail/both_borrows/pass_invalid_shr_option.rs:LL:CC
|
Expand Down
2 changes: 1 addition & 1 deletion tests/fail/both_borrows/pass_invalid_shr_tuple.rs
Original file line number Diff line number Diff line change
Expand Up @@ -12,5 +12,5 @@ fn main() {
unsafe { *xraw0 = 42 }; // unfreeze
foo(pair_xref);
//~[stack]^ ERROR: /retag .* tag does not exist in the borrow stack/
//~[tree]| ERROR: /reborrow through .* is forbidden/
//~[tree]| ERROR: /reborrow to create .* through .* is forbidden/
}
6 changes: 3 additions & 3 deletions tests/fail/both_borrows/pass_invalid_shr_tuple.tree.stderr
Original file line number Diff line number Diff line change
@@ -1,11 +1,11 @@
error: Undefined Behavior: reborrow through <TAG> at ALLOC[0x0] is forbidden
error: Undefined Behavior: reborrow to create <TAG> through <TAG> at ALLOC[0x0] is forbidden
--> tests/fail/both_borrows/pass_invalid_shr_tuple.rs:LL:CC
|
LL | foo(pair_xref);
| ^^^^^^^^^ reborrow through <TAG> at ALLOC[0x0] is forbidden
| ^^^^^^^^^ reborrow to create <TAG> 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> has state Disabled which forbids this reborrow (acting as a child read access)
= help: the accessed tag <TAG> has state Disabled which forbids this reborrow to create <TAG> (acting as a child read access)
help: the accessed tag <TAG> was created here, in the initial state Frozen
--> tests/fail/both_borrows/pass_invalid_shr_tuple.rs:LL:CC
|
Expand Down
2 changes: 1 addition & 1 deletion tests/fail/both_borrows/return_invalid_shr.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ fn foo(x: &mut (i32, i32)) -> &i32 {
unsafe { *xraw = (42, 23) }; // unfreeze
ret
//~[stack]^ ERROR: /retag .* tag does not exist in the borrow stack/
//~[tree]| ERROR: /reborrow through .* is forbidden/
//~[tree]| ERROR: /reborrow to create .* through .* is forbidden/
}

fn main() {
Expand Down
6 changes: 3 additions & 3 deletions tests/fail/both_borrows/return_invalid_shr.tree.stderr
Original file line number Diff line number Diff line change
@@ -1,11 +1,11 @@
error: Undefined Behavior: reborrow through <TAG> at ALLOC[0x4] is forbidden
error: Undefined Behavior: reborrow to create <TAG> through <TAG> at ALLOC[0x4] is forbidden
--> tests/fail/both_borrows/return_invalid_shr.rs:LL:CC
|
LL | ret
| ^^^ reborrow through <TAG> at ALLOC[0x4] is forbidden
| ^^^ reborrow to create <TAG> 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> has state Disabled which forbids this reborrow (acting as a child read access)
= help: the accessed tag <TAG> has state Disabled which forbids this reborrow to create <TAG> (acting as a child read access)
help: the accessed tag <TAG> was created here, in the initial state Frozen
--> tests/fail/both_borrows/return_invalid_shr.rs:LL:CC
|
Expand Down
2 changes: 1 addition & 1 deletion tests/fail/both_borrows/return_invalid_shr_option.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ fn foo(x: &mut (i32, i32)) -> Option<&i32> {
unsafe { *xraw = (42, 23) }; // unfreeze
ret
//~[stack]^ ERROR: /retag .* tag does not exist in the borrow stack/
//~[tree]| ERROR: /reborrow through .* is forbidden/
//~[tree]| ERROR: /reborrow to create .* through .* is forbidden/
}

fn main() {
Expand Down
6 changes: 3 additions & 3 deletions tests/fail/both_borrows/return_invalid_shr_option.tree.stderr
Original file line number Diff line number Diff line change
@@ -1,11 +1,11 @@
error: Undefined Behavior: reborrow through <TAG> at ALLOC[0x4] is forbidden
error: Undefined Behavior: reborrow to create <TAG> through <TAG> at ALLOC[0x4] is forbidden
--> tests/fail/both_borrows/return_invalid_shr_option.rs:LL:CC
|
LL | ret
| ^^^ reborrow through <TAG> at ALLOC[0x4] is forbidden
| ^^^ reborrow to create <TAG> 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> has state Disabled which forbids this reborrow (acting as a child read access)
= help: the accessed tag <TAG> has state Disabled which forbids this reborrow to create <TAG> (acting as a child read access)
help: the accessed tag <TAG> was created here, in the initial state Frozen
--> tests/fail/both_borrows/return_invalid_shr_option.rs:LL:CC
|
Expand Down
2 changes: 1 addition & 1 deletion tests/fail/both_borrows/return_invalid_shr_tuple.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ fn foo(x: &mut (i32, i32)) -> (&i32,) {
unsafe { *xraw = (42, 23) }; // unfreeze
ret
//~[stack]^ ERROR: /retag .* tag does not exist in the borrow stack/
//~[tree]| ERROR: /reborrow through .* is forbidden/
//~[tree]| ERROR: /reborrow to create .* through .* is forbidden/
}

fn main() {
Expand Down
6 changes: 3 additions & 3 deletions tests/fail/both_borrows/return_invalid_shr_tuple.tree.stderr
Original file line number Diff line number Diff line change
@@ -1,11 +1,11 @@
error: Undefined Behavior: reborrow through <TAG> at ALLOC[0x4] is forbidden
error: Undefined Behavior: reborrow to create <TAG> through <TAG> at ALLOC[0x4] is forbidden
--> tests/fail/both_borrows/return_invalid_shr_tuple.rs:LL:CC
|
LL | ret
| ^^^ reborrow through <TAG> at ALLOC[0x4] is forbidden
| ^^^ reborrow to create <TAG> 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> has state Disabled which forbids this reborrow (acting as a child read access)
= help: the accessed tag <TAG> has state Disabled which forbids this reborrow to create <TAG> (acting as a child read access)
help: the accessed tag <TAG> was created here, in the initial state Frozen
--> tests/fail/both_borrows/return_invalid_shr_tuple.rs:LL:CC
|
Expand Down
2 changes: 1 addition & 1 deletion tests/fail/tree_borrows/fnentry_invalidation.stderr
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ help: the accessed tag <TAG> later transitioned to Active due to a child write a
LL | *z = 1;
| ^^^^^^
= help: this transition corresponds to the first write to a 2-phase borrowed mutable reference
help: the accessed tag <TAG> later transitioned to Frozen due to a reborrow (acting as a foreign read access) at offsets [0x0..0x4]
help: the accessed tag <TAG> later transitioned to Frozen due to a reborrow to create <TAG> (acting as a foreign read access) at offsets [0x0..0x4]
--> tests/fail/tree_borrows/fnentry_invalidation.rs:LL:CC
|
LL | x.do_bad();
Expand Down
2 changes: 1 addition & 1 deletion tests/fail/tree_borrows/parent_read_freezes_raw_mut.stderr
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ help: the accessed tag <TAG> later transitioned to Active due to a child write a
LL | *ptr = 0; // Write
| ^^^^^^^^
= help: this transition corresponds to the first write to a 2-phase borrowed mutable reference
help: the accessed tag <TAG> later transitioned to Frozen due to a reborrow (acting as a foreign read access) at offsets [0x0..0x1]
help: the accessed tag <TAG> later transitioned to Frozen due to a reborrow to create <TAG> (acting as a foreign read access) at offsets [0x0..0x1]
--> tests/fail/tree_borrows/parent_read_freezes_raw_mut.rs:LL:CC
|
LL | assert_eq!(root, 0); // Parent Read
Expand Down
2 changes: 1 addition & 1 deletion tests/fail/tree_borrows/protector-write-lazy.rs
Original file line number Diff line number Diff line change
Expand Up @@ -31,5 +31,5 @@ fn main() {
let funky_ptr_lazy_on_fst_elem = the_other_function(ref_to_fst_elem, ptr_to_vec);
// now we try to use the funky lazy pointer.
// It should be UB, since the write-on-protector-end should disable it.
unsafe { println!("Value of funky: {}", *funky_ptr_lazy_on_fst_elem) } //~ ERROR: /reborrow through .* is forbidden/
unsafe { println!("Value of funky: {}", *funky_ptr_lazy_on_fst_elem) } //~ ERROR: /reborrow to create .* through .* is forbidden/
}
6 changes: 3 additions & 3 deletions tests/fail/tree_borrows/protector-write-lazy.stderr
Original file line number Diff line number Diff line change
@@ -1,11 +1,11 @@
error: Undefined Behavior: reborrow through <TAG> at ALLOC[0x0] is forbidden
error: Undefined Behavior: reborrow to create <TAG> through <TAG> at ALLOC[0x0] is forbidden
--> tests/fail/tree_borrows/protector-write-lazy.rs:LL:CC
|
LL | unsafe { println!("Value of funky: {}", *funky_ptr_lazy_on_fst_elem) }
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^ reborrow through <TAG> at ALLOC[0x0] is forbidden
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^ reborrow to create <TAG> 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> has state Disabled which forbids this reborrow (acting as a child read access)
= help: the accessed tag <TAG> has state Disabled which forbids this reborrow to create <TAG> (acting as a child read access)
help: the accessed tag <TAG> was created here, in the initial state Reserved
--> tests/fail/tree_borrows/protector-write-lazy.rs:LL:CC
|
Expand Down
2 changes: 1 addition & 1 deletion tests/fail/tree_borrows/write-during-2phase.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@
struct Foo(u64);
impl Foo {
fn add(&mut self, n: u64) -> u64 {
//~^ ERROR: /reborrow through .* is forbidden/
//~^ ERROR: /reborrow to create .* through .* is forbidden/
self.0 + n
}
}
Expand Down
6 changes: 3 additions & 3 deletions tests/fail/tree_borrows/write-during-2phase.stderr
Original file line number Diff line number Diff line change
@@ -1,11 +1,11 @@
error: Undefined Behavior: reborrow through <TAG> at ALLOC[0x0] is forbidden
error: Undefined Behavior: reborrow to create <TAG> through <TAG> at ALLOC[0x0] is forbidden
--> tests/fail/tree_borrows/write-during-2phase.rs:LL:CC
|
LL | fn add(&mut self, n: u64) -> u64 {
| ^^^^^^^^^ reborrow through <TAG> at ALLOC[0x0] is forbidden
| ^^^^^^^^^ reborrow to create <TAG> 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> has state Disabled which forbids this reborrow (acting as a child read access)
= help: the accessed tag <TAG> has state Disabled which forbids this reborrow to create <TAG> (acting as a child read access)
help: the accessed tag <TAG> was created here, in the initial state Reserved
--> tests/fail/tree_borrows/write-during-2phase.rs:LL:CC
|
Expand Down