Skip to content

tree borrows: implicit writes#4947

Open
quiode wants to merge 36 commits intorust-lang:masterfrom
quiode:tb-strong-mode
Open

tree borrows: implicit writes#4947
quiode wants to merge 36 commits intorust-lang:masterfrom
quiode:tb-strong-mode

Conversation

@quiode
Copy link
Copy Markdown
Contributor

@quiode quiode commented Apr 8, 2026

This PR tries to address rust-lang/unsafe-code-guidelines#584 (comment). It is part of a bachelor thesis supervised by @JoJoDeveloping and @RalfJung, for more information, see: Project_Description.pdf.
This implements the checking for implicit writes for Tree Borrows. It is disabled by default but can be enabled using the -Zmiri-tree-borrows-implicit-writes flag.
When it is enabled, Miri inserts a write for all mutable borrows on function entry. This enables the optimization implemented here: rust-lang/rust#155207

@rustbot
Copy link
Copy Markdown
Collaborator

rustbot commented Apr 8, 2026

Thank you for contributing to Miri! A reviewer will take a look at your PR, typically within a week or two.
Please remember to not force-push to the PR branch except when you need to rebase due to a conflict or when the reviewer asks you for it.

@rustbot rustbot added the S-waiting-on-review Status: Waiting for a review to complete label Apr 8, 2026
@quiode
Copy link
Copy Markdown
Contributor Author

quiode commented Apr 8, 2026

r? @RalfJung

@quiode quiode marked this pull request as draft April 8, 2026 17:11
@rustbot rustbot added S-waiting-on-author Status: Waiting for the PR author to address review comments and removed S-waiting-on-review Status: Waiting for a review to complete labels Apr 8, 2026
Copy link
Copy Markdown
Member

@RalfJung RalfJung left a comment

Choose a reason for hiding this comment

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

I didn't look at the tests yet, and have to dig more into the logic, but here are some first comments.

View changes since this review

Comment thread src/bin/miri.rs Outdated
Comment thread src/borrow_tracker/mod.rs Outdated
Comment thread src/borrow_tracker/tree_borrows/mod.rs Outdated
Comment thread src/borrow_tracker/tree_borrows/mod.rs Outdated
Comment thread src/borrow_tracker/tree_borrows/mod.rs Outdated
Comment thread src/borrow_tracker/tree_borrows/mod.rs Outdated
Comment thread src/borrow_tracker/tree_borrows/perms.rs Outdated
Comment thread src/borrow_tracker/tree_borrows/tree.rs
Comment thread src/data_structures/dedup_range_map.rs Outdated
Comment thread src/borrow_tracker/tree_borrows/mod.rs Outdated
Copy link
Copy Markdown
Member

@RalfJung RalfJung left a comment

Choose a reason for hiding this comment

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

And here's the second round, now also with comments for the logic and the tests. :) Please ask either in this PR, or Johannes on Zulip, if you have questions.

View changes since this review

Comment thread src/borrow_tracker/tree_borrows/mod.rs Outdated
Comment thread src/borrow_tracker/tree_borrows/mod.rs Outdated
Comment thread src/borrow_tracker/tree_borrows/mod.rs Outdated
Comment thread src/borrow_tracker/tree_borrows/mod.rs Outdated
Comment thread src/borrow_tracker/tree_borrows/mod.rs Outdated
Comment thread tests/fail/function_calls/arg_inplace_locals_alias_ret.tree.stderr Outdated
Comment thread tests/fail/tree_borrows/implicit_writes/flag.rs Outdated
Comment thread tests/fail/tree_borrows/implicit_writes/fnentry_invalidation.rs Outdated
Comment thread tests/fail/tree_borrows/implicit_writes/mut_option.rs Outdated
Comment thread tests/fail/tree_borrows/implicit_writes/ptr_write2.rs Outdated
@RalfJung
Copy link
Copy Markdown
Member

@rustbot author

@rustbot
Copy link
Copy Markdown
Collaborator

rustbot commented Apr 10, 2026

Reminder, once the PR becomes ready for a review, use @rustbot ready.

Comment thread tests/fail/tree_borrows/implicit_writes/ptr_write.rs
@quiode quiode marked this pull request as ready for review April 10, 2026 13:15
@rustbot rustbot added S-waiting-on-review Status: Waiting for a review to complete and removed S-waiting-on-author Status: Waiting for the PR author to address review comments labels Apr 10, 2026
Comment thread src/borrow_tracker/mod.rs
@quiode
Copy link
Copy Markdown
Contributor Author

quiode commented Apr 17, 2026

While looking over the code, an issue came forward which is mentioned in #4947 (comment). 29d5336 tries to address this issue by "constraining" the outside permission to Reserved if it is Unique. A test that currently breaks (but should not), but with the changes not anymore, has been implemented in array-pointer-access.rs. Also added additional assertions when using is_initial() as this now allows Unqiue which some functions do not expect.

Copy link
Copy Markdown
Member

@RalfJung RalfJung left a comment

Choose a reason for hiding this comment

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

Thanks for the revision! However I am confused by some of the changes.

View changes since this review

Comment thread src/borrow_tracker/tree_borrows/tree.rs Outdated
Comment thread tests/fail/tree_borrows/implicit_writes/ptr_write.rs Outdated
Comment thread tests/fail/tree_borrows/implicit_writes/ptr_write_unsafe_cell.rs Outdated
Comment thread tests/pass/tree_borrows/array-pointer-access.rs
@RalfJung
Copy link
Copy Markdown
Member

I have pushed a refactor of the permission logic that is a bit longer than what you had but IMO also easier to follow. Please let me know what you think.

github-actions Bot pushed a commit to rust-lang/stdarch that referenced this pull request Apr 20, 2026
add llvm writable attribute conditionally




This PR tries to address rust-lang/unsafe-code-guidelines#584 (comment). It is part of a bachelor thesis supervised by @JoJoDeveloping and @RalfJung, for more information, see: [Project_Description.pdf](https://github.com/user-attachments/files/26537277/Project_Description.pdf).
If the new `-Zllvm-writable` flag is set, the [llvm writable attribute](https://llvm.org/docs/LangRef.html#writable) is inserted for all mutable borrows. This can be conditionally turned off on a per-function basis using the `#[rustc_no_writable]` attribute. The new Undefined Behaviour introduced by this can detected by Miri, which is implemented here: rust-lang/miri#4947.

Two library functions already received the `#[rustc_no_writable]` attribute, as they are known to cause problems under the Tree Borrows aliasing model with implicit writes enabled.
lnicola pushed a commit to lnicola/rust-analyzer that referenced this pull request Apr 20, 2026
add llvm writable attribute conditionally




This PR tries to address rust-lang/unsafe-code-guidelines#584 (comment). It is part of a bachelor thesis supervised by @JoJoDeveloping and @RalfJung, for more information, see: [Project_Description.pdf](https://github.com/user-attachments/files/26537277/Project_Description.pdf).
If the new `-Zllvm-writable` flag is set, the [llvm writable attribute](https://llvm.org/docs/LangRef.html#writable) is inserted for all mutable borrows. This can be conditionally turned off on a per-function basis using the `#[rustc_no_writable]` attribute. The new Undefined Behaviour introduced by this can detected by Miri, which is implemented here: rust-lang/miri#4947.

Two library functions already received the `#[rustc_no_writable]` attribute, as they are known to cause problems under the Tree Borrows aliasing model with implicit writes enabled.
Comment thread tests/pass/tree_borrows/read_retag_no_race.rs Outdated
@quiode quiode requested a review from JoJoDeveloping April 21, 2026 15:06
@quiode
Copy link
Copy Markdown
Contributor Author

quiode commented Apr 21, 2026

All requested changes should be implemented now.
@rustbot ready

@rustbot rustbot added S-waiting-on-review Status: Waiting for a review to complete and removed S-waiting-on-author Status: Waiting for the PR author to address review comments labels Apr 21, 2026
Copy link
Copy Markdown
Contributor

@JoJoDeveloping JoJoDeveloping left a comment

Choose a reason for hiding this comment

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

the test is good, but I have some comments mostly affecting the things beside the code that is run as part of this test. (I.e. it's mostly bikeshedding, sorry.)

View changes since this review

Comment thread tests/fail/tree_borrows/implicit_writes/read_retag.rs Outdated
Comment thread tests/fail/tree_borrows/implicit_writes/read_retag.rs Outdated
Comment thread tests/fail/tree_borrows/implicit_writes/read_retag.rs Outdated
Comment thread tests/fail/tree_borrows/implicit_writes/read_retag.rs Outdated
Comment thread tests/fail/tree_borrows/implicit_writes/read_retag.rs Outdated
Comment thread tests/fail/tree_borrows/implicit_writes/read_retag.rs Outdated
Comment thread tests/fail/tree_borrows/implicit_writes/read_retag.stdout Outdated
@JoJoDeveloping
Copy link
Copy Markdown
Contributor

I will try to have another look over the entire code soon ™️ but it's a very busy week for me.

// `noalias` would not be sound.
Permission::new_reserved_frz()
} else {
Permission::new_reserved_im()
Copy link
Copy Markdown
Contributor

@JoJoDeveloping JoJoDeveloping Apr 24, 2026

Choose a reason for hiding this comment

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

@RalfJung I don't think it makes sense to mark Boxes as ReservedIM, does it? It's what the logic was doing before and we likely didn't notice... (Note that Minirust does the same).

View changes since the review

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Why does it not make sense? Box<T> as a function argument should be treated the same as &mut T, just without the protector.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

this is about Box in non-function-argument position, i.e. when moved inside a method.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

What is your proposal for what their initial state should be?

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

just Reserved. For mutable references we have ReservedIM because of the safe code in this test, but I don't think that is possible with boxes.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Interesting. We figured it'd be like &mut because "why not".

I'd say lets leave this unchanged for now, but please open an issue or PR (depending on what you have time for) specifically for this change, also including an example of code that you think should have UB but currently doesn't because of this.

Copy link
Copy Markdown
Contributor

@JoJoDeveloping JoJoDeveloping Apr 24, 2026

Choose a reason for hiding this comment

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

@RalfJung We added the tree_iwrites revision to some of the fail tests. There are many more fail tests that we could add this to. Is there a reason why not to do so?

Specifically, this should probably be on all tests in fail/both_borrows and on selected tests in fail/tree_borrows even outside the fail/tree_borrows/implicit_writes folder...

View changes since the review

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

You already added this is more than enough places I think. The pass tests are more critical since the flag makes TB less permissive.

@JoJoDeveloping
Copy link
Copy Markdown
Contributor

JoJoDeveloping commented Apr 24, 2026

I will try to have another look over the entire code soon ™️ but it's a very busy week for me.

I had another look at it and am now happy with it 🎉 (except for the things noted above)

Copy link
Copy Markdown
Member

@RalfJung RalfJung left a comment

Choose a reason for hiding this comment

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

Thanks! Just a few more comments for the tests, the rest looks good. :)

@rustbot author

View changes since this review

@@ -0,0 +1,30 @@
// Tests that accessing the same array using disjoint pointers does not cause UB under Tree Borrows.
// The pointer will access the memory range using the outside permission, thus testing if it has been set correctly.
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Suggested change
// The pointer will access the memory range using the outside permission, thus testing if it has been set correctly.
// The pointer will access the memory range using the outside permission, thus testing if it has been set correctly.
// In particular, in implicit_writes mode we used to set the "outside" permissions to
// `Unique`, which caused an ICE.
// Put differently, this checks the absence of subobject provenance for arrays.


fn main() {
let mut x: Box<u8> = Box::new(0u8);
let ptr = &mut *x as *mut u8;
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

There's still a mutable reference here. If that isn't relevant, maybe use &raw mut *x instead?

@@ -1,4 +1,6 @@
//@compile-flags: -Zmiri-tree-borrows
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

You can keep this line so that all revisions use TB.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

This is quite confusing to be in this folder as this test is about not having implicit writes.

Maybe call it tests/pass/tree_borrows/no_implicit_writes.rs?

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

This can be merged with tests/pass/tree_borrows/implicit_writes/ptr_write.rs.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Maybe make this just a function in tests/pass/tree_borrows/tree-borrows.rs? That's where we have most of these kinds of tests.

@rustbot rustbot added S-waiting-on-author Status: Waiting for the PR author to address review comments and removed S-waiting-on-review Status: Waiting for a review to complete labels Apr 27, 2026
Copy link
Copy Markdown
Contributor

@JoJoDeveloping JoJoDeveloping left a comment

Choose a reason for hiding this comment

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

some other cosmetic things in tests I noticed while reading over this with Ralf.

View changes since this review

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

can you rename this test into retag_is_data_race.rs or something like that? The current name is in praticular wrong as it is not a "read" retag.

thread::yield_now(); // force other thread to read first

fn write(y: &mut u8, v: u8, barrier: &Arc<Barrier>) {
//~^ ERROR: Data race detected
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

can you make the error message more specific, to match on the retag being called a write?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

S-waiting-on-author Status: Waiting for the PR author to address review comments

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants