# Safe code relied upon by unsafe is effectively unsafe

**URL:** <https://internals.rust-lang.org/t/safe-code-relied-upon-by-unsafe-is-effectively-unsafe/21351>\
**Category:** Unsafe Code Guidelines\
**Created:** [August 11, 2024, 10:44pm UTC](https://internals.rust-lang.org/t/safe-code-relied-upon-by-unsafe-is-effectively-unsafe/21351 "2024-08-11T22:44:45Z")\
**Posts on this page:** 20\
**Page:** 1

<div class="post-metadata">

**Author:** ![nasal\_daemon](https://avatars.discourse-cdn.com/v4/letter/n/85f322/32.png) [@nasal\_daemon](https://internals.rust-lang.org/u/nasal_daemon)\
**Post date:** [August 11, 2024, 10:44pm UTC](https://internals.rust-lang.org/t/safe-code-relied-upon-by-unsafe-is-effectively-unsafe/21351/1 "2024-08-11T22:44:45Z")

</div>

Rust is designed to allow mistakes in safe code without violation of soundness, but mistakes in unsafe code are allowed to violate soundness. This is the fundamental idea behind the distinction of safe and unsafe code. But if unsafe code relies upon explicitly documented behavior in safe code, it means that the safe code should strictly follow its documentation, or otherwise soundness of the program may be violated. A mistake in safe code can make a program unsound. I.e. safe code effectively becomes unsafe when it is relied upon by unsafe code.

Condition A: Code can be modified in every possible way, excluding introduction of `unsafe` keyword and unsafe macros, and be sound.\[1\]

1. Condition A is necessary and sufficient for code to be safe.
2. Inverse of condition A is necessary and sufficient for code to be unsafe.
3. It is sufficient for unsafe code to act in accordance with documentation of every API it uses in order to be sound.

Follows from statement 1:

1. Code can violate behavior guaranteed by its own documentation and remain sound.

One of the statements 1, 2 and 3 is not true.

> **Proof**
>
> According to statement 1 the function `rand()` is safe. (And by extension from condition A sound.) According to statement 2 the function `rand_str()` is unsafe. According to statement 3 the function `rand_str()` is sound. Yet the code is not sound. Thus one of those statements is not true.
> 
> ```rust
> /// Generates a random number in 0..4
> fn rand() -> u8 {
> 4 // chosen by fair dice roll.
> // guaranteed to be random.
> }
> 
> fn rand_str() -> &'static str {
> match rand() {
> 0 => "Zero",
> 1 => "One",
> 2 => "Two",
> 3 => "Three",
> _ => unsafe { std::hint::unreachable_unchecked() },
> }
> }
> 
> ```

I believe the first two statements are the definition of safe and unsafe code. Thus the third statement is false and the following statement is true:

1. It is not sufficient for unsafe code to act in accordance with documentation of every API it uses in order to be sound.

Now my question is: what other conditions are necessary for unsafe code to be sound?

Condition 3 in conjunction with the inverse of condition 4 is sufficient. Even if condition 1 is alternated to be only necessary, there is still a problem. Now a discrepancy between the documented and the actual behavior of safe code, i.e. a bug in safe code, can make the program unsound, which defies the purpose of safe code.

I believe the third statement is assumed to be true by most people writing unsafe code. Possibly I am projecting this from my own experience, since I believed it was true. If it is the case, this means that every piece of safe code used from unsafe code is potentially de facto unsafe. If some unsafe code relies upon safe code to not violate its own documentation in order to be sound, then that means that every piece of such safe code is in a state or can be modified is such a state that the program will be unsound and it will remain safe according to statement 1.

Is there a way to write unsafe code which can be formally proven to be sound and not rely on the correctness of safe code, since it can not be relied upon in general?

* * *

1. Assuming the language specification and implementation are correct and we stay within the realm of the language. A safe program can for example use some platform-specific API to directly access its own memory, create and run a script which will attach `gdb` to the program itself and mess with its execution flow or convince the user to hit the computer with a blow-hammer (I am not sure whether the later would be considered a violation of soundness), but this is beyond the scope of the language.

---

<div class="post-metadata">

**Author:** ![197g](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/197g/32/7276_2.png) [@197g](https://internals.rust-lang.org/u/197g)\
**Post date:** [August 12, 2024, 12:00am UTC](https://internals.rust-lang.org/t/safe-code-relied-upon-by-unsafe-is-effectively-unsafe/21351/4 "2024-08-12T00:00:25Z")

</div>

Safety is the property of a function that ensures that all its evaluations are sound, and in particular that there is a semantic model of all its evaluations. It doesn't say what that semantic model is, or how precise it is. A function such as `checked_add` has a much more precise model than non-deterministically producing any value. The fact that a functions semantics correctly follows is documentation is just another property to rely on for a proof of code that calls it; and for constructing the semantic equivalence of an unsafe implementation to its unsafe interface documentation.

Your assertion A.1 is an incorrect understanding.

Soudness indeed requires that all _composition_ with the safe-marked function are free of UB, but the usage of `checked_add` is not such a composition. It is structurally part of the definition of the function that calls it. There is no 'for-all' qualifier in that usage. (In contrast to an generic function such as in `fn quick_sort<A: Ord>` that is quantified over A).

In that sense, the semantic interpretation of soudness judgments of unsafe function composition is _intensional_. It indeed matters precisely which one objects its definition refers to and for forward compatibility of such proofs, it also matters how. Of course, if the model we want to build of piece of code relies on the assertion that a functions semantics are stricter than soundness requires and peeks inside such functions definition, it's the burden of such code to demonstrate how it ensures this is true—under forward compatibility under all potential replacements of the object it references. Usual ways of achieving this are either by defining the method locally; or axiomatically by claiming that external agreements ensure that other revisions of code will not deviate from semantics. Such as, the RFC process of the standard library ensuring it.

---

<div class="post-metadata">

**Author:** ![Mokuz](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/mokuz/32/7225_2.png) [@Mokuz](https://internals.rust-lang.org/u/Mokuz)\
**Post date:** [August 12, 2024, 12:45am UTC](https://internals.rust-lang.org/t/safe-code-relied-upon-by-unsafe-is-effectively-unsafe/21351/5 "2024-08-12T00:45:24Z")

</div>

Rust has two distinct uses for the `unsafe` keyword:

1. Unsafe precondition/unsafe to call
2. Unsafe postcondition/unsafe to implement

Case 1. is covered by `unsafe fn`

```rust
// the caller of `foo` is responsible for safety (with a caveat) 
// can only be called with numbers smaller than 4 (exclusive)
unsafe fn foo(a: u32) {
    match {
        0 => { /* whatever */ }
        1 => { /* whatever */ }
        2 => { /* whatever */ }
        3 => { /* whatever */ }
        _ => unsafe { 
            // safe because a < 4
            hint::unreachable_unchecked()
        }
    }
}

```

The 2. case is covered by `unsafe impl`

```rust
unsafe trait Foo {
    // output must be equal to `a + b`
    fn add(a: i32, b: i32) -> i32;
}

// safety is the resposibility of the implementor
unsafe impl Foo for () {
    fn add(a: i32, b: i32) -> i32 {
        a + b
    }
}

if <() as Foo>::add(3i32, 7i32) != 10 {
    unsafe { 
        // safe because 3 + 7 = 10
        hint::unreachable_unchecked()
    }
}

```

This leads to the question wheter rust should let standalone functions as being `unsafe impl`, because as of now its up in the air if you can trust a non `unsafe impl` functions documentation.

This means that in the given example is either unsound because `rand` fails to uphold its postcondition, or the implementor of `rand_str` fails to uphold the precondition of `hint::unreachable_unchecked`

```rust
// even if this documentation is wrong the fault lies with `rand_str` 
// for trusting `rand` which is not `unsafe impl`, right?

/// Generates a random number in 0..4
fn rand() -> u8 {
    4 // chosen by fair dice roll.
      // guaranteed to be random.
}

fn rand_str() -> &'static str {
    match rand() {
        0 => "Zero",
        1 => "One",
        2 => "Two",
        3 => "Three",
        _ => unsafe { 
           // this is actually unsound because nothing is stopping `rand`
           // from returning 4 because it is safe rust and cannot be trusted  
           std::hint::unreachable_unchecked() },
    }
}

```

We _could_ add `safe` keyword to show that a functions implementation does what it says on the documentation (which is expected anyways) and that you can rely on it for correctness, and unsafe code is only ever allowed to depend on `safe` functions, meaning we get the following code:

```rust
// we can now clearly see that the fault lies at `rand`s implementation
// which fails to uphold its own invariant

/// Generates a random number in 0..4
safe fn rand() -> u8 {
    4 // chosen by fair dice roll.
      // guaranteed to be random.
}

fn rand_str() -> &'static str {
    match rand() {
        0 => "Zero",
        1 => "One",
        2 => "Two",
        3 => "Three",
        _ => unsafe { 
           // safety: `rand` only gives numbers in range 0..4,
           // and this is quaranteed by its implementation
           std::hint::unreachable_unchecked()
        },
    }
}

```

---

<div class="post-metadata">

**Author:** ![jumpnbrownweasel](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/jumpnbrownweasel/32/12426_2.png) [@jumpnbrownweasel](https://internals.rust-lang.org/u/jumpnbrownweasel)\
**Post date:** [August 12, 2024, 4:15am UTC](https://internals.rust-lang.org/t/safe-code-relied-upon-by-unsafe-is-effectively-unsafe/21351/6 "2024-08-12T04:15:14Z")

</div>

> [@nasal\_daemon](#):
>
> If some unsafe code relies upon safe code to not violate its own documentation in order to be sound

I think you may have been misled by the [conversation](https://users.rust-lang.org/t/marker-unsafe-or-not-unsafe/115819) on urlo. That conversation was mainly about relying on the guarantees in an unsafe trait's safety documentation. That scenario can't be generalized to all dependencies on external (safe or unsafe) code.

Almost all unsafe code (other than in the std library I guess) depends on external code, whether safe or unsafe, even if it only depends on the std/core libraries. That external code may be documented to provide guarantees _unrelated_ to safety. When implementing your unsafe code in a sound manner, you have to decide whether to rely on the external code's guarantees or not. This problem is independent of whether the external code is safe or unsafe.

---

<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:** [August 12, 2024, 8:16am UTC](https://internals.rust-lang.org/t/safe-code-relied-upon-by-unsafe-is-effectively-unsafe/21351/7 "2024-08-12T08:16:21Z")

</div>

This is indeed a well-known fact, that perhaps should be documented/communicated better: unsafe code can and does rely on the functional correctness of safe code _that it explicitly depends on_ for soundness.

In other words, this is completely okay:

```rust
use some_hashmap_crate::HashMap;

unsafe {
  // Rely on this being a correct hash map implementation.
}

```

OTOH, this is _not_ okay:

```rust
fn my_fun<H: HashMapTrait>() {
  let h = H::new();
  unsafe {
    // Rely on this being a correct hash map implementation.
  }
}

```

Unsafe code may only rely on the correctness of upstream code, never of downstream code.

---

<div class="post-metadata">

**Author:** ![the8472](https://avatars.discourse-cdn.com/v4/letter/t/0ea827/32.png) [@the8472](https://internals.rust-lang.org/u/the8472)\
**Post date:** [August 12, 2024, 8:45am UTC](https://internals.rust-lang.org/t/safe-code-relied-upon-by-unsafe-is-effectively-unsafe/21351/8 "2024-08-12T08:45:40Z")

</div>

> [@nasal\_daemon](#):
>
> Is there a way to write unsafe code which can be formally proven to be sound and not rely on the correctness of safe code, since it can not be relied upon in general?

Often one can call out to safe code without relying on its correctness guarantees, only relying on its soundness. For example iterator adapters sometimes interleave a lot of unchecked arithmetic operations and pointer accesses with calls to arbitrary `Iterator::next` implementations. But the unsafe code is written so that the preconditions of the unchecked arithmetic are fulfilled independent of the correctness of `next`. But this still requires defensive coding since your unsafe code will have to remain sound if any of those calls unexpectedly unwinds, loops forever, is reentrant etc.

If you do rely on the correctness of safe code then you're elevating that to a safety requirement, which means you need to treat all the safe code as if it were unsafe code. So if you're doing proving then you either need to prove the safe code you're relying on or make it a precondition of your proof. As Ralf says, such a proof would be impossible if you accept arbitrary trait impls because one could always construct a hostile implementation that violates whatever you're relying on.

---

<div class="post-metadata">

**Author:** ![dlight](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/dlight/32/8462_2.png) [@dlight](https://internals.rust-lang.org/u/dlight)\
**Post date:** [August 12, 2024, 10:46am UTC](https://internals.rust-lang.org/t/safe-code-relied-upon-by-unsafe-is-effectively-unsafe/21351/9 "2024-08-12T10:46:33Z")

</div>

> [@nasal\_daemon](#):
>
> Is there a way to write unsafe code which can be formally proven to be sound and not rely on the correctness of safe code, since it can not be relied upon in general?

If you are formally proving some unsafe code doesn't have UB, you _must_ also prove the correctness of any and every safe code it depends for its soundness (even code in other crates, including the stdlib). That is, while it is true that you can't rely on safe code _in general_, but you can rely on specific, trusted instances of safe code.

Note that sometimes you can prove that your unsafe code merely calls some safe code but doesn't rely on it for soundness. It's the only way you can write generic unsafe code for example: you must guarantee that no matter the generics instantiation you caller chooses, your code remains sound.

For example, if you write an `unsafe fn f<T: Eq>(x: T, y: T) { .. }`, you may have `x == y` inside this function but you must not rely on its correctness to ensure soundness[1], that is, `f` must not have UB even if `T` implements `Eq` wrong. With the right tools, you can prove that.

[1] see the [docs of the trait](https://doc.rust-lang.org/std/cmp/trait.Eq.html):

> Violating this property is a logic error. The behavior resulting from a logic error is not specified, but users of the trait must ensure that such logic errors do _not_ result in undefined behavior. This means that `unsafe` code **must not** rely on the correctness of these methods.

---

<div class="post-metadata">

**Author:** ![alice](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/alice/32/5044_2.png) [@alice](https://internals.rust-lang.org/u/alice)\
**Post date:** [August 12, 2024, 10:47am UTC](https://internals.rust-lang.org/t/safe-code-relied-upon-by-unsafe-is-effectively-unsafe/21351/10 "2024-08-12T10:47:20Z")

</div>

Ultimately there are cases where bugs in a library that are not memory safety bugs _in that library_ are still CVE worthy for introducing memory safety bugs in downstream libraries.

Take [RUSTSEC-2024-0019](https://rustsec.org/advisories/RUSTSEC-2024-0019.html) as an example. In mio, this is just a logic but where it can give out tokens after they're guaranteed destroyed. But due to how Tokio used it, it became a use-after-free in Tokio. Still, we reported the CVE on mio and not Tokio, because that's where the CVE belongs.

---

<div class="post-metadata">

**Author:** ![ia0](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/ia0/32/1396_2.png) [@ia0](https://internals.rust-lang.org/u/ia0)\
**Post date:** [August 17, 2024, 7:15am UTC](https://internals.rust-lang.org/t/safe-code-relied-upon-by-unsafe-is-effectively-unsafe/21351/11 "2024-08-17T07:15:00Z")

</div>

> [@RalfJung](#):
>
> This is indeed a well-known fact, that perhaps should be documented/communicated better: unsafe code can and does rely on the functional correctness of safe code _that it explicitly depends on_ for soundness.

If anyone wants to read more about this in a semi-formal fashion, there's the [unsafe mental model](https://ia0.github.io/unsafe-mental-model/introduction.html). The particular notion Ralf mentions is tracked by the `robust` keyword which is the dual of `unsafe` with respect to variance. This has currently no syntax or convention but still exists and is necessary to prove soundness.

---

<div class="post-metadata">

**Author:** ![TadaHrd](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/tadahrd/32/12453_2.png) [@TadaHrd](https://internals.rust-lang.org/u/TadaHrd)\
**Post date:** [August 18, 2024, 8:45am UTC](https://internals.rust-lang.org/t/safe-code-relied-upon-by-unsafe-is-effectively-unsafe/21351/12 "2024-08-18T08:45:36Z")

</div>

The answer is simple: Make invalid states unrepresentable.

It can't contradict the docs if it can't possibly return a value other than in the docs.

---

<div class="post-metadata">

**Author:** ![SkiFire13](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/skifire13/32/7579_2.png) [@SkiFire13](https://internals.rust-lang.org/u/SkiFire13)\
**Post date:** [August 18, 2024, 11:19am UTC](https://internals.rust-lang.org/t/safe-code-relied-upon-by-unsafe-is-effectively-unsafe/21351/13 "2024-08-18T11:19:14Z")

</div>

> [@TadaHrd](#):
>
> The answer is simple: Make invalid states unrepresentable.

That's not simple at all, and in many cases it's impossible.

---

<div class="post-metadata">

**Author:** ![TadaHrd](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/tadahrd/32/12453_2.png) [@TadaHrd](https://internals.rust-lang.org/u/TadaHrd)\
**Post date:** [August 18, 2024, 11:22am UTC](https://internals.rust-lang.org/t/safe-code-relied-upon-by-unsafe-is-effectively-unsafe/21351/14 "2024-08-18T11:22:43Z")

</div>

Sure, you can have mistakes in your types' implementations that "can't" represent invalid states but it surely is better than relying on the documentation of the function to know what subset of the type's possible values it returns.

---

<div class="post-metadata">

**Author:** ![SkiFire13](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/skifire13/32/7579_2.png) [@SkiFire13](https://internals.rust-lang.org/u/SkiFire13)\
**Post date:** [August 18, 2024, 12:41pm UTC](https://internals.rust-lang.org/t/safe-code-relied-upon-by-unsafe-is-effectively-unsafe/21351/15 "2024-08-18T12:41:30Z")

</div>

I'm not sure I'm following.

Take for example `HashSet<usize>` (with the primitive `usize` type and default hasher, so everything stdlib controlled). I would be reasonable to require that after `set.insert(1)` then `set.contains(&1)` will return `true`, while the state where `set.contains(&1)` is invalid and should never happen. This is a very common operation to the point that some `unsafe` code wants to rely on this. How do you represent this in a type such that the invalid state is impossible?

---

<div class="post-metadata">

**Author:** ![dlight](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/dlight/32/8462_2.png) [@dlight](https://internals.rust-lang.org/u/dlight)\
**Post date:** [August 18, 2024, 12:54pm UTC](https://internals.rust-lang.org/t/safe-code-relied-upon-by-unsafe-is-effectively-unsafe/21351/16 "2024-08-18T12:54:09Z")

</div>

> [@ia0](#):
>
> The particular notion Ralf mentions is tracked by the `robust` keyword which is the dual of `unsafe` with respect to variance

I was eager to say that we really need this (or anything else that makes unsafe Rust more tractable) but I'm having a hard time figuring out what the concept of being "robust" actually mean. Is there somewhere else that describes what robust means in simpler terms?

For what I can gather it is defined only in relation to an update type in the [quick start](https://ia0.github.io/unsafe-mental-model/quick-start.html) section of the book:

> [@](#):
>
> - The update type `Update<P, T>` is **unsafe** if `P \ T` is not empty, and it is **robust** if `T \ P` is not empty.

The section [the `robust` keyword](https://ia0.github.io/unsafe-mental-model/robust-keyword.html) attempts another description (the same as yours) but it is even less clear. It's also not clear why it states that "it is not recommended to actively document a type as robust". I mean, robustness is a concept that was created to aid reasoning about unsafe Rust, but referring to it in documentation - the only place we can specify unsafe requirements of our code - is actively discouraged? Then what it is for?

---

<div class="post-metadata">

**Author:** ![ia0](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/ia0/32/1396_2.png) [@ia0](https://internals.rust-lang.org/u/ia0)\
**Post date:** [August 18, 2024, 1:24pm UTC](https://internals.rust-lang.org/t/safe-code-relied-upon-by-unsafe-is-effectively-unsafe/21351/17 "2024-08-18T13:24:33Z")

</div>

> [@dlight](#):
>
> Is there somewhere else that describes what robust means in simpler terms?

I don't know if it's simpler terms, but the actual definition of a robust type is in the "what is unsafe" section (which can be found from the glossary). I highly suggest reading "what are types" first unless you have strong type theory background.

In a few words if you understand the quick start enough: unsafe types have values that the type system doesn't see, and robust types are missing values that the type system believe can be present.

> [@dlight](#):
>
> It's also not clear why it states that "it is not recommended to actively document a type as robust".

This is described [here](https://ia0.github.io/unsafe-mental-model/unsafe-reviews.html#burden-of-proof) and [initially here](https://internals.rust-lang.org/t/simpler-mental-model-for-unsafe/20363/25). There's also a mention [here](https://ia0.github.io/unsafe-mental-model/making-it-explicit.html#robustness-documentation). Hope this helps.

---

<div class="post-metadata">

**Author:** ![TadaHrd](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/tadahrd/32/12453_2.png) [@TadaHrd](https://internals.rust-lang.org/u/TadaHrd)\
**Post date:** [August 18, 2024, 1:28pm UTC](https://internals.rust-lang.org/t/safe-code-relied-upon-by-unsafe-is-effectively-unsafe/21351/18 "2024-08-18T13:28:59Z")

</div>

I would either make a wrapper type or a different kind of type (depending on the requirements).

It's not possible to completely phase out invalid states but it's far better to encapsulate it into a type, which affirms the premise that `set.contains(&1)` returns `true` by documentation. This makes it easier to debug because there's less code that could go wrong.

This doesn't completely solve the problem (which is why many projects use extensive testing tools), as it is impossible to solve (you always have to trust someone and/or something).

---

<div class="post-metadata">

**Author:** ![SkiFire13](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/skifire13/32/7579_2.png) [@SkiFire13](https://internals.rust-lang.org/u/SkiFire13)\
**Post date:** [August 18, 2024, 2:10pm UTC](https://internals.rust-lang.org/t/safe-code-relied-upon-by-unsafe-is-effectively-unsafe/21351/19 "2024-08-18T14:10:05Z")

</div>

> [@TadaHrd](#):
>
> I would either make a wrapper type or a different kind of type (depending on the requirements).
> 
> It's not possible to completely phase out invalid states but it's far better to encapsulate it into a type, which affirms the premise that `set.contains(&1)` returns `true` by documentation. This makes it easier to debug because there's less code that could go wrong.

But such type would ultimately have to rely on `HashSet`'s behaving correct, so in the end you just put another layer inbetween, which arguably makes it less clear what's going on.

---

<div class="post-metadata">

**Author:** ![TadaHrd](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/tadahrd/32/12453_2.png) [@TadaHrd](https://internals.rust-lang.org/u/TadaHrd)\
**Post date:** [August 19, 2024, 6:50pm UTC](https://internals.rust-lang.org/t/safe-code-relied-upon-by-unsafe-is-effectively-unsafe/21351/20 "2024-08-19T18:50:25Z")

</div>

Correct, but if you do it well enough, you can make it at least a bit clear and the benefit can be big.

---

<div class="post-metadata">

**Author:** ![binarycat](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/binarycat/32/12210_2.png) [@binarycat](https://internals.rust-lang.org/u/binarycat)\
**Post date:** [August 20, 2024, 6:34am UTC](https://internals.rust-lang.org/t/safe-code-relied-upon-by-unsafe-is-effectively-unsafe/21351/21 "2024-08-20T06:34:08Z")

</div>

> [@Mokuz](#):
>
> We _could_ add `safe` keyword to show that a functions implementation does what it says on the documentation (which is expected anyways) and that you can rely on it for correctness, and unsafe code is only ever allowed to depend on `safe` functions

let's absolutely not no that, it would be an absolute disaster of terminology, as "safe" currently is used everywhere to mean "not unsafe" and there's some plans to add it with that meaning, such as "safe fn" in extern blocks, and possibly "safe" blocks that deactivate outer unsafe blocks.

additionally, this is a poor use of a keyword, since it doesn't really add anything to the language (similar to how "let mut" is frequently described as "just a lint"). this doesn't add more safety, it just adds confusion.

---

<div class="post-metadata">

**Author:** ![Mokuz](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/mokuz/32/7225_2.png) [@Mokuz](https://internals.rust-lang.org/u/Mokuz)\
**Post date:** [August 20, 2024, 12:59pm UTC](https://internals.rust-lang.org/t/safe-code-relied-upon-by-unsafe-is-effectively-unsafe/21351/22 "2024-08-20T12:59:58Z")

</div>

Oh I agree.

[Next page](https://internals.rust-lang.org/t/safe-code-relied-upon-by-unsafe-is-effectively-unsafe/21351.md?page=2)
