Hacker News new | ask | show | jobs
by GolDDranks 607 days ago
Try imagining trait AlwaysIndexableUnder100. There's a generic codebase/library that takes in types that implement that trait, and do indexing with indexes that are always below 100. Like `usersCustomSliceA[4] = usersCustomSliceB[5];`

You'd be tempted, for performance, to use `get_unchecked` methods that skip the boundary checks. After all, the trait says that this should always succeed.

However, if the user passes in a type that is not indexable with integers smaller than 100, whose fault it is if the program segfaults? The users? But they managed to get the program to segfault _without_ writing unsafe code. The provider of the library? They are using `unsafe` to call `get_unchecked` after all.

Bingo. It's the library dev's fault. The API they provide is not sound. However, they can make it sound by marking the _trait_ unsafe to implement. Then the user needs to type `unsafe` when implementing the trait for their type. "I solemnly swear that this type is actually indexable with all integers smaller than 100." That shifts the blame to the mistaken implementation, and the user is to blame.

It's the same situation here. Deref is not unsafe to implement. That's why if you need to uphold a trust boundary, you need an unsafe trait.

So, the whole thing doesn't account to crossing the boundary willy nilly, a big point of Rust's unsafe is for the compiler to force documenting and checking for accountability: who is required to do what, and who is allowed to rely on that.