# You\_can::turn\_off\_the\_borrow\_checker should not be allowed without declaring unsafe

**URL:** <https://internals.rust-lang.org/t/you-can-turn-off-the-borrow-checker-should-not-be-allowed-without-declaring-unsafe/16001>\
**Category:** Unsafe Code Guidelines\
**Created:** [January 21, 2022, 7:20pm UTC](https://internals.rust-lang.org/t/you-can-turn-off-the-borrow-checker-should-not-be-allowed-without-declaring-unsafe/16001 "2022-01-21T19:20:01Z")\
**Posts on this page:** 15\
**Page:** 1

<div class="post-metadata">

**Author:** ![arnabanimesh](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/arnabanimesh/32/7647_2.png) [@arnabanimesh](https://internals.rust-lang.org/u/arnabanimesh)\
**Post date:** [January 21, 2022, 7:20pm UTC](https://internals.rust-lang.org/t/you-can-turn-off-the-borrow-checker-should-not-be-allowed-without-declaring-unsafe/16001/1 "2022-01-21T19:20:01Z")

</div>

[Attribute Macro you\_can::turn\_off\_the\_borrow\_checker](https://docs.rs/you-can/0.0.1/you_can/attr.turn_off_the_borrow_checker.html) should not be allowed without declaring `unsafe`.

Speaking of which why is [Function unbounded::reference](https://docs.rs/unbounded/0.0.2022/unbounded/fn.reference.html) even allowed without declaring `unsafe`?

Discussion: [Reddit](https://www.reddit.com/r/rust/comments/s9az4y/you_canturn_off_the_borrow_checker/)

Repo: [you-can](https://github.com/jeremyBanks/you-can), [unbounded](https://docs.rs/unbounded/0.0.2022/src/unbounded/lib.rs.html#1-86)

---

<div class="post-metadata">

**Author:** ![steffahn](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/steffahn/32/13288_2.png) [@steffahn](https://internals.rust-lang.org/u/steffahn)\
**Post date:** [January 21, 2022, 7:27pm UTC](https://internals.rust-lang.org/t/you-can-turn-off-the-borrow-checker-should-not-be-allowed-without-declaring-unsafe/16001/2 "2022-01-21T19:27:09Z")

</div>

The “unbounded::reference” function [does _use_ `unsafe`](https://docs.rs/unbounded/0.0.2022/src/unbounded/lib.rs.html#49) but doesn’t offer a sound safe API. The fact that it’s not declared as an `unsafe fn` is making it unsound, i.e. violating the usual principles you are expected to follow when using `unsafe` code. It self-documents as unsound though; maybe its purpose is to be used in that macro you linked without the macro needing to insert any “`unsafe`” blocks. The macro _also_ self-documents as “allow[ing] unsound [code]”.

There is no way for the rust compiler to prevent unsound functions. The reason why you can use `unsafe {}` blocks in a non-`unsafe` function is because the whole _purpose_ of `unsafe {}` blocks is to be able to call unsafe functions internally, hidden behind a (usually sound) safe API. So yes, a function like this _is_ “allowed” by the compiler in that it doesn’t run into any compilation errors, and it is _not allowed_ in the sense that you’re not supposed to write unsound code like this. The reddit discussion you linked also has multiple people pointing out that the crate lacks any part that requires users of it to write the word “`unsafe`” when using - either the macro, or that function.

In any case, note that’s just shenanigans that some random crate is pulling. What’s happening here is in no way related to the compiler or the standard library, hence it’s off-topic to this forum 😉 ; unless you’re asking that the compiler should change its rules here. In that case, you _could_ have also started by asking somewhere about _why it is_ allowed in the first place; e.g. in that reddit discussion or on [users.rust-lang.org](http://users.rust-lang.org). It’s often advisable to try and learn more about the subject at hand first before proposing compiler changes. Still, since you’ve posted here now, I hope my explanation above helps you learn more. To learn more in-depth context around the distinction between “`unsafe`” code and the concept of “unsound” code, see also e.g. [this blog post](https://raphlinus.github.io/rust/2020/01/18/soundness-pledge.html) or [this post](https://docs.rs/dtolnay/latest/dtolnay/macro._03__soundness_bugs.html) it links to; or [this glossary entry](https://rust-lang.github.io/unsafe-code-guidelines/glossary.html#soundness-of-code--of-a-library) in the UCG reference, [this section](https://doc.rust-lang.org/reference/behavior-considered-undefined.html#behavior-considered-undefined) in the reference, or [the Rustonomicon](https://doc.rust-lang.org/nomicon/working-with-unsafe.html#working-with-unsafe).

---

<div class="post-metadata">

**Author:** ![ibraheemdev](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/ibraheemdev/32/13406_2.png) [@ibraheemdev](https://internals.rust-lang.org/u/ibraheemdev)\
**Post date:** [January 21, 2022, 10:39pm UTC](https://internals.rust-lang.org/t/you-can-turn-off-the-borrow-checker-should-not-be-allowed-without-declaring-unsafe/16001/3 "2022-01-21T22:39:00Z")

</div>

> [@steffahn](#):
>
> The fact that it’s not declared as an `unsafe fn` is making it unsound

FWIW [the latest release of `unbounded`](https://docs.rs/unbounded/0.0.4/unbounded/fn.reference.html) marks `unbounded::reference` as `unsafe`:

> This is **unsound and unsafe**. Invoking this functions risks incurring the wrath of the optimizer. Rust references are not pointers. For edutainment purposes only.

---

<div class="post-metadata">

**Author:** ![arnabanimesh](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/arnabanimesh/32/7647_2.png) [@arnabanimesh](https://internals.rust-lang.org/u/arnabanimesh)\
**Post date:** [January 21, 2022, 11:54pm UTC](https://internals.rust-lang.org/t/you-can-turn-off-the-borrow-checker-should-not-be-allowed-without-declaring-unsafe/16001/4 "2022-01-21T23:54:47Z")

</div>

It is just that one can use turn\_off\_the\_borrow\_checker macro without declaring unsafe even when it uses unsafe functions underneath. That's the main issue.

---

<div class="post-metadata">

**Author:** ![ibraheemdev](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/ibraheemdev/32/13406_2.png) [@ibraheemdev](https://internals.rust-lang.org/u/ibraheemdev)\
**Post date:** [January 22, 2022, 1:11am UTC](https://internals.rust-lang.org/t/you-can-turn-off-the-borrow-checker-should-not-be-allowed-without-declaring-unsafe/16001/5 "2022-01-22T01:11:42Z")

</div>

Rust is built on writing safe abstractions that use unsafe underneath. A simple "Hello world" program uses a lot of unsafe, but the caller does not have to worry about it because the standard library has ensured that it is not possible to use the function unsoundly. The way that crate uses unsafe is unsound (as a joke), but that isn't a Rust problem, it's a `you_can::turn_off_the_borrow_checker` problem.

---

<div class="post-metadata">

**Author:** ![elidupree](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/elidupree/32/4304_2.png) [@elidupree](https://internals.rust-lang.org/u/elidupree)\
**Post date:** [January 22, 2022, 4:22pm UTC](https://internals.rust-lang.org/t/you-can-turn-off-the-borrow-checker-should-not-be-allowed-without-declaring-unsafe/16001/6 "2022-01-22T16:22:25Z")

</div>

I do think there's one meaningful issue here. `you_can::turn_off_the_borrow_checker` is clearly unsafe, so it should be marked as `unsafe`, just like `unbounded::reference` is - but it can't be, because it's an attribute macro. I don't know that there's enough need to add a syntax to declare and use unsafe attribute macros, but at least theoretically, that's a gap in what Rust can express.

---

<div class="post-metadata">

**Author:** ![steffahn](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/steffahn/32/13288_2.png) [@steffahn](https://internals.rust-lang.org/u/steffahn)\
**Post date:** [January 22, 2022, 5:12pm UTC](https://internals.rust-lang.org/t/you-can-turn-off-the-borrow-checker-should-not-be-allowed-without-declaring-unsafe/16001/7 "2022-01-22T17:12:50Z")

</div>

An attribute macro can require an `unsafe` token as an argument. You’d call it as

```rust
#[you_can::turn_off_the_borrow_checker(unsafe)]
fn foo() {

    // ...
}

```

This is not covered by `#![forbid(unsafe_code)]`, but the approach to “grep for `unsafe` tokens” covers this at least. I just double-checked, `#![forbid(unsafe_code)]` apparently doesn’t properly catch uses of `unsafe` anyways. You can easily bypass it using a `macro_rules` macro from a different (also `#![forbid(unsafe_code)]`) crate to compose the `unsafe` with a block.

---

<div class="post-metadata">

**Author:** ![untitaker](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/untitaker/32/8846_2.png) [@untitaker](https://internals.rust-lang.org/u/untitaker)\
**Post date:** [January 22, 2022, 5:30pm UTC](https://internals.rust-lang.org/t/you-can-turn-off-the-borrow-checker-should-not-be-allowed-without-declaring-unsafe/16001/8 "2022-01-22T17:30:40Z")

</div>

You can probably come up with some minor adjustments to `you_can` that would make it safer for cargo geiger, e.g. require some sort of `unsafe` token in the attribute itself or require that the function itself is an unsafe one, but at the end of the day we're discussing a joke crate here. I feel like even the discussion about the API of `unbounded::reference` is overblown in that context.

This is related to [RUSTSEC-2020-0011 is not a security vulnerability. · Issue #275 · rustsec/advisory-db · GitHub](https://github.com/rustsec/advisory-db/issues/275). I find it problematic that existing tooling cannot catch such crates in some automated way (even if it means maintaining a list of questionable crates somewhere), but IMO there's nothing that can be changed in the language to make this better, and fixing this particular crate to be "nicer to audit" won't solve a real-world concern of auditing underhanded code.

---

<div class="post-metadata">

**Author:** ![RalfJung](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/ralfjung/32/2415_2.png) [@RalfJung](https://internals.rust-lang.org/u/RalfJung)\
**Post date:** [January 23, 2022, 12:20am UTC](https://internals.rust-lang.org/t/you-can-turn-off-the-borrow-checker-should-not-be-allowed-without-declaring-unsafe/16001/9 "2022-01-23T00:20:42Z")

</div>

Indeed, for Macros Rust does not have a built-in notion of them being "unsafe". It is up to the macro author to somehow indicate that a macro is unsafe to use, e.g. by including `unsafe` in its name.

---

<div class="post-metadata">

**Author:** ![jeremyBanks](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/jeremybanks/32/9711_2.png) [@jeremyBanks](https://internals.rust-lang.org/u/jeremyBanks)\
**Post date:** [January 23, 2022, 7:36pm UTC](https://internals.rust-lang.org/t/you-can-turn-off-the-borrow-checker-should-not-be-allowed-without-declaring-unsafe/16001/10 "2022-01-23T19:36:42Z")

</div>

For what it's worth: I was failing to pass along a span when generating the `unsafe { ... }` blocks. Now that I've fixed that ([v0.0.7](https://docs.rs/you-can/0.0.7/you_can/attr.turn_off_the_borrow_checker.html)), `#[warn(unsafe_code])` is appropriately triggered by use of this macro:

 ![](https://us1.discourse-cdn.com/flex002/uploads/rustlang/original/2X/a/a6e9b6f8facd6d87d20430fa696b176efc5972af.jpeg)

> **Tangentially: custom diagnostic warnings on nightly are very neat:**
>
> ![](https://us1.discourse-cdn.com/flex002/uploads/rustlang/original/2X/0/0d24ad7e288be2c5bea67f49ef25ce92b8e2c1c4.jpeg) ![](https://us1.discourse-cdn.com/flex002/uploads/rustlang/original/2X/2/2432b770102f6a204513316701ab233b3e8ec545.png)

---

<div class="post-metadata">

**Author:** ![steffahn](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/steffahn/32/13288_2.png) [@steffahn](https://internals.rust-lang.org/u/steffahn)\
**Post date:** [January 23, 2022, 7:57pm UTC](https://internals.rust-lang.org/t/you-can-turn-off-the-borrow-checker-should-not-be-allowed-without-declaring-unsafe/16001/11 "2022-01-23T19:57:45Z")

</div>

Oh, that’s cool! I’m not too much into proc macros, I just tested what happened to an `unsafe` token passed to a macro that ignores it, and noted that this doesn’t trigger the lint. Whether or not `warn(unsafe_code)` catches its usage is an interesting aspect in the discussion of soundness of macros, besides approaches like

> [@RalfJung](#):
>
> including `unsafe` in its name

I suppose, in a perfect world, an unsafe macro would usually try to do _both_? However, arguably a macro that spells “turn\_off\_the\_borrow\_checker” doesn’t really need any additional remarks on whether or not such an operation is unsafe.

(And beyond that, if that wasn’t enough, the “DANGER DANGER DANGER” message during the build makes things quite clear as-well 🙂 )

---

<div class="post-metadata">

**Author:** ![hyeonu](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/hyeonu/32/2162_2.png) [@hyeonu](https://internals.rust-lang.org/u/hyeonu)\
**Post date:** [January 24, 2022, 5:08am UTC](https://internals.rust-lang.org/t/you-can-turn-off-the-borrow-checker-should-not-be-allowed-without-declaring-unsafe/16001/12 "2022-01-24T05:08:06Z")

</div>

While the macro system itself doesn't have any safety notation, it's practial in many cases to enforce the macro is used in usafe context. For example unsafe macros that produces statements/expressions should not wrap its result with unsafe block by itself. A serious implementation of `#[you_can::turn_off_the_borrow_checker]` would assert/make the function `unsafe fn`.

---

<div class="post-metadata">

**Author:** ![crlf0710](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/crlf0710/32/1987_2.png) [@crlf0710](https://internals.rust-lang.org/u/crlf0710)\
**Post date:** [January 24, 2022, 9:45am UTC](https://internals.rust-lang.org/t/you-can-turn-off-the-borrow-checker-should-not-be-allowed-without-declaring-unsafe/16001/13 "2022-01-24T09:45:50Z")

</div>

> [@steffahn](#):
>
> This is not covered by `#![forbid(unsafe_code)]` , but the approach to “grep for `unsafe` tokens” covers this at least. I just double-checked, `#![forbid(unsafe_code)]` apparently doesn’t properly catch uses of `unsafe` anyways. You can easily bypass it using a `macro_rules` macro from a different (also `#![forbid(unsafe_code)]` ) crate to compose the `unsafe` with a block.

Indeed, i documented the current behavior with a test at [Add a strange test for `unsafe_code` lint. by crlf0710 · Pull Request #89821 · rust-lang/rust · GitHub](https://github.com/rust-lang/rust/pull/89821)

---

<div class="post-metadata">

**Author:** ![Nemo157](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/nemo157/32/11585_2.png) [@Nemo157](https://internals.rust-lang.org/u/Nemo157)\
**Post date:** [January 24, 2022, 9:55am UTC](https://internals.rust-lang.org/t/you-can-turn-off-the-borrow-checker-should-not-be-allowed-without-declaring-unsafe/16001/14 "2022-01-24T09:55:04Z")

</div>

It gets even weirder if the macro generates `#[allow(unsafe_code)] unsafe { ... }` since the `forbid` will forbid setting the `allow` still.

---

<div class="post-metadata">

**Author:** ![steffahn](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/steffahn/32/13288_2.png) [@steffahn](https://internals.rust-lang.org/u/steffahn)\
**Post date:** [December 22, 2024, 5:04pm UTC](https://internals.rust-lang.org/t/you-can-turn-off-the-borrow-checker-should-not-be-allowed-without-declaring-unsafe/16001/15 "2024-12-22T17:04:10Z")

</div>

Closed on December 22, 2024, 5:04pm UTC

This topic was automatically closed 540 days after the last reply. New replies are no longer allowed.
