```您可以::关闭借用检查器```
you_can::turn_off_the_borrow_checker

原始链接: https://docs.rs/you-can/latest/you_can/attr.turn_off_the_borrow_checker.html

所提供的文本介绍了一个 Rust 宏,它通过将引用包装在不安全的 `borrow_unchecked` 函数中来绕过借用检查器,从而有效地解除了它们的生命周期限制。虽然这使得原本会触发编译错误的代码得以运行,但作者强调:**这是极其危险的,绝不应在生产环境中使用。** 由于 Rust 引用并非简单的指针,编译器基于特定的别名规则进行假设;通过破坏这些规则,你会引入导致不可预测且灾难性崩溃的未定义行为。尽管该工具可用于 Rust 内存模型的教学探索,但它并不会真正“关闭”借用检查器。相反,它强迫编译器忽略安全违规,从而导致代码不健全。对于合法的底层内存访问,作者建议使用 Rust 原生的裸指针,它们是专为此类任务设计的。归根结底,这个宏展示了为什么 Rust 严格的所有权和借用规则对于内存安全至关重要。

```Hacker News新消息 | 过往 | 评论 | 提问 | 展示 | 招聘 | 投稿登录you_can::turn_off_the_borrow_checker (docs.rs)11 分,由 striking 发布于 4 小时前 | 隐藏 | 过往 | 收藏 | 讨论 帮助 指南 | 常见问题 | 列表 | API | 安全 | 法律 | 加入 YC | 联系 搜索: ```
相关文章

原文

You can’t “turn off the borrow checker” in Rust, and you shouldn’t want to. Rust’s references aren’t pointers, and the compiler is free to decimate code that tries to use references as though they are. If you need raw pointer behaviour in Rust, don’t use this, use Rust’s actual raw pointers, which don’t make the same aliasing guarantees to the compiler. However, if you would like to pretend the borrow checker doesn’t exist for educational purposes and never in production code, this macro that will suppress many (though not all) borrow checker errors in the code it’s applied to.

This shouldn’t break any otherwise-valid code; the borrow checker doesn’t affect compilation output, only verify input validity. However, it will allow unsound and unsafe nonsense that will fail unpredictably and dangerously. This is not safe to use.

§Example

§Without Macro
fn main() {
    let mut owned = vec![1, 32];

    let mut_1 = &mut owned[0];
    let mut_2 = &mut owned[1];
    drop(owned);
    let undefined = *mut_1 + *mut_2;
    println!("{undefined}");
}
§With Macro
#[you_can::turn_off_the_borrow_checker]
fn main() {
    let mut owned = vec![1, 32];

    let mut_1 = &mut owned[0];
    let mut_2 = &mut owned[1];
    drop(owned);
    let undefined = *mut_1 + *mut_2;
    println!("{undefined}");
}

§Explanation

The macro looks for references created in the code by use of the & or &mut operators or the ref and ref mut bindings, and wraps them with our borrow_unchecked() function to unbind their lifetimes, causing the borrow checker to effectively ignore them. If running on nightly, it adds new warning diagnostic messages for every reference it modifies.

§Expanded
fn main() {
    let mut owned = vec![1, 32];

    let mut_1 = unsafe { ::you_can::borrow_unchecked(&mut owned[0]) };
    let mut_2 = unsafe { ::you_can::borrow_unchecked(&mut owned[1]) };

    drop(owned);
    let undefined = *mut_1 + *mut_2;
    println!("{undefined}");
}

This approached is limited. It can’t suppress errors resulting from the code illegally composing lifetimes created elsewhere, or references created implicitly. As a workaround, prefixing &* can sometimes be used to force an explicit reference where one is needed, such as as in the example below.

§Example

#[you_can::turn_off_the_borrow_checker]
fn main() {
    let mut source = Some(1);
    let inner_mut = &*source.as_ref().unwrap();
    let mutable_alias = &mut source;

    source = None;
    *mutable_alias = Some(2);

    if let Some(ref mut inner_a) = source {
        match source {
            Some(ref mut inner_b) => {
                *inner_b = inner_mut + 1;
                *inner_a = inner_mut + 2;
            },
            None => {
                println!("none");
            },
        }
    }

    println!("{source:?}");
}
§Expanded
fn main() {
    let mut source = Some(1);
    let inner_mut = unsafe { ::you_can::borrow_unchecked(&*source.as_ref().unwrap()) };
    let mutable_alias = unsafe { ::you_can::borrow_unchecked(&mut source) };

    source = None;
    *mutable_alias = Some(2);

    if let Some(ref mut inner_a) = source {
        let inner_a = unsafe { ::you_can::borrow_unchecked(inner_a) };

        match source {
            Some(ref mut inner_b) => {
                let inner_b = unsafe { ::you_can::borrow_unchecked(inner_b) };

                *inner_b = inner_mut + 1;
                *inner_a = inner_mut + 2;
            },
            None => {
                println!("none");
            },
        }
    }

    println!("{source:?}");
}

§Discussions

Here are some related discussions, mostly about why you shouldn’t do this:

联系我们 contact @ memedata.com