# Pre-RFC: I/O Safety

**URL:** <https://internals.rust-lang.org/t/pre-rfc-i-o-safety/14585>\
**Category:** Unsafe Code Guidelines\
**Created:** [April 28, 2021, 12:00am UTC](https://internals.rust-lang.org/t/pre-rfc-i-o-safety/14585 "2021-04-28T00:00:02Z")\
**Posts on this page:** 1\
**Showing post:** 7

<div class="post-metadata">

**Author:** ![sunfishcode](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/sunfishcode/32/1381_2.png) [@sunfishcode](https://internals.rust-lang.org/u/sunfishcode)\
**Post date:** [April 29, 2021, 6:15pm UTC](https://internals.rust-lang.org/t/pre-rfc-i-o-safety/14585/7 "2021-04-29T18:15:26Z")

</div>

> [@matklad](#):
>
> > Is there a way to express this without using unsafe keyword?

I'm open to suggestions, but I don't expect there is. I/O safety is similar to memory safety in that it's built on rules that apply at the lowest level of abstraction. These rules conceptually apply everywhere, even through FFI calls where Rust can't enforce them.

> [@matklad](#):
>
> > How much of a problem is this in practice? One difference between memory safety and IO safety is that we always mess up the former in a memory-unsafe languages, but the letter seems to work well enough most of the time? Are there are specific examples of bugs that this system would prevent?

Most programs have a great many times more pointers and dereferences than handles and system calls, so they naturally get more visibility :-).

Use-after-close and double-close are well known. Rust today doesn't see a lot of them, but this may be because it's already mostly enforcing I/O safety, even if it doesn't call it that yet. `File`, `TcpStream`, and numerous other types in `std` and independent crates already do. The motivation here isn't specific bugs, but just to close a hole in a property that Rust in practice already mostly has.

> [@matklad](#):
>
> > I totally see how doing FFI can lead to double closes, but I don't immediately see why this RFC helps. When doing FFI, we often have double frees as well, despite memory safety being in there anyway.

We obviously can't statically enforce rules on FFI code :-). This RFC just says that if you have an FFI call that takes a raw handle, you need to explicitly take responsibility for proving that the code is using it safely.

> [@matklad](#):
>
> > We already have a second kind of safety, unwind safety: std::panic::UnwindSafe 1. It works without using unsafe keyword.
> 
> > I feel rather strongly that keeping unsafe strictly for memory safety has a lot of value.

> [@matklad](#):
>
> > Again, the analogy with panic safety is useful. I think that the current consensus is that panic safety is not a clear win -- often times, it's more annoying then helpful, and people just AssertUnwindSafe.

In Rust, one of the big reasons memory safety is important is that it's the difference between a bug meaning "the program might do the wrong thing" and "it's difficult to bound the set of things the program might do". I/O safety is also in this category. Especially from the perspective of a crate that doesn't know what other resources may exist in programs it's used in, it's impossible to know what one might be corrupting, or exposing. My understanding of Rust's position on unwind safety is that it's not in this category (on its own).

And, unwind safety's usefulness or lack thereof is likely specific to the kinds of things people are doing after a `catch_unwind`. `Ord` and `Eq` are also "assertion" traits, used in different circumstances, and as far as I'm aware, people generally see these as useful (provided one keeps in mind that for floating point, they're only the messengers).

---

_[View the full topic](https://internals.rust-lang.org/t/pre-rfc-i-o-safety/14585)._
