turn_off_the_borrow_checker in you_can - Rust
Docs.rs
you-can-0.0.14
you-can 0.0.14
Permalink
Docs.rs crate page
MIT OR Apache-2.0
Links
Repository
crates.io
Source
Owners
jeremyBanks
Dependencies
you-can-build-macros ^0.0.14
normal
compiletest_rs ^0.8.0
dev
rustc_version ^0.4.0
dev
Versions
100%<br>of the crate is documented
Platform
i686-pc-windows-msvc
i686-unknown-linux-gnu
x86_64-apple-darwin
x86_64-pc-windows-msvc
x86_64-unknown-linux-gnu
Feature flags
docs.rs<br>About docs.rs<br>Badges<br>Builds<br>Metadata<br>Shorthand URLs<br>Download<br>Rustdoc JSON<br>Build queue<br>Privacy policy
Rust
Rust website
The Book
Standard Library API Reference
Rust by Example
The Cargo Guide
Clippy Documentation
This old browser is unsupported and will most likely display funky things.<br>turn_off_the_borrow_checker
you_can<br>Attribute Macro turn_off_the_borrow_checker Copy item path<br>Source<br>#[turn_off_the_borrow_checker]Expand descriptionYou can’t “turn off the borrow checker” in Rust, and you shouldn’t want<br>to. Rust’s references aren’t pointers, and the compiler is free to<br>decimate code that tries to use references as though they are. If you need raw<br>pointer behaviour in Rust, don’t use this, use<br>Rust’s actual raw pointers, which don’t make the same aliasing guarantees<br>to the compiler. However, if you would like to pretend the borrow checker<br>doesn’t exist for educational purposes and never in production code , this<br>macro that will suppress many (though not all) borrow checker errors in the code<br>it’s applied to.
This shouldn’t break any otherwise-valid code; the borrow checker doesn’t affect<br>compilation output, only verify input validity. However, it will allow unsound<br>and unsafe nonsense that will fail unpredictably and dangerously. This is not<br>safe to use .
§Example<br>§Without Macro
ⓘfn main() {<br>let mut owned = vec![1, 32];
let mut_1 = &mut owned[0];<br>let mut_2 = &mut owned[1];<br>//~^ ERROR cannot borrow `owned` as mutable more than once at a time
drop(owned);<br>//~^ ERROR cannot move out of `owned` because it is borrowed<br>let undefined = *mut_1 + *mut_2;<br>println!("{undefined}");<br>§With Macro
#[you_can::turn_off_the_borrow_checker]<br>fn main() {<br>let mut owned = vec![1, 32];
let mut_1 = &mut owned[0];<br>let mut_2 = &mut owned[1];<br>//~^ WARNING the borrow checker is suppressed for these references.
drop(owned);<br>let undefined = *mut_1 + *mut_2;<br>println!("{undefined}");<br>§Explanation
The macro looks for references created in the code by use of the & or &mut<br>operators or the ref and ref mut bindings, and wraps them with our<br>borrow_unchecked() function to unbind their lifetimes, causing the<br>borrow checker to effectively ignore them. If running on nightly, it adds new<br>warning diagnostic messages for every reference it modifies.
§Expanded
fn main() {<br>let mut owned = vec![1, 32];
let mut_1 = unsafe { ::you_can::borrow_unchecked(&mut owned[0]) };<br>let mut_2 = unsafe { ::you_can::borrow_unchecked(&mut owned[1]) };
drop(owned);<br>let undefined = *mut_1 + *mut_2;<br>println!("{undefined}");
This approached is limited. It can’t suppress errors resulting from the code<br>illegally composing lifetimes created elsewhere, or references created<br>implicitly. As a workaround, prefixing &* can sometimes be used to force an<br>explicit reference where one is needed, such as as in the example below.
§Example
#[you_can::turn_off_the_borrow_checker]<br>fn main() {<br>let mut source = Some(1);<br>let inner_mut = &*source.as_ref().unwrap();<br>let mutable_alias = &mut source;
source = None;<br>*mutable_alias = Some(2);
if let Some(ref mut inner_a) = source {<br>match source {<br>Some(ref mut inner_b) => {<br>*inner_b = inner_mut + 1;<br>*inner_a = inner_mut + 2;<br>},<br>None => {<br>println!("none");<br>},
println!("{source:?}");<br>§Expanded
fn main() {<br>let mut source = Some(1);<br>let inner_mut = unsafe { ::you_can::borrow_unchecked(&*source.as_ref().unwrap()) };<br>let mutable_alias = unsafe { ::you_can::borrow_unchecked(&mut source) };
source = None;<br>*mutable_alias = Some(2);
if let Some(ref mut inner_a) = source {<br>let inner_a = unsafe { ::you_can::borrow_unchecked(inner_a) };
match source {<br>Some(ref mut inner_b) => {<br>let inner_b = unsafe { ::you_can::borrow_unchecked(inner_b) };
*inner_b = inner_mut + 1;<br>*inner_a = inner_mut + 2;<br>},<br>None => {<br>println!("none");<br>},
println!("{source:?}");<br>§Discussions
Here are some related discussions, mostly about why you shouldn’t do this:
https://reddit.com/s9az4y
https://internals.rust-lang.org/t/16001
https://news.ycombinator.com/item?id=30031323
https://twitter.com/pcwalton/status/1485718602233704452
https://smitop.com/post/rust-skip-borrowck