4 ms·
This "clearly something has gone horribly wrong" is where I think we actually get lazy. Let me illustrate using my example. The mid-level consumer is a crop fu
by spion 10y ago
This "clearly something has gone horribly wrong" is where I think we actually get lazy.
Let me illustrate using my example. The mid-level consumer is a crop function that takes the image and coordinates. It has no reason to assume someone wont check the image bounds so it uses the panicky API to access the array, assuming "Ok, they'll check if they are out of image dimensions beforehand".
But another level up, we're passing user-generated data right to it, after the face detection crop. Clearly thats wrong. Unfortunately the mid-level consumer didn't provide a non-panicky API so we had to write our own wrapper.
The question is, is it crashy-wrong? If shared mutable state is cleaned up via RAII/defer/finally, there is nothing wrong with the "exception" being caught and the process can continue running. The reason why we don't know if something went horribly wrong is that we don't have the cleanup contract for handling these types of things in the first place.
So why do we want this extremely unsafe "cleanupless" contract to begin with? I can't think of any other reason than performance, because syntax sugar can always take care of the rest.
- Manishearth 10y ago> Ok, they'll check if they are out of image dimensions beforehand that's a straw man example, its not the kind of API I'm talking about. Let me repeat: this is for cases where the library developer has written code where it won't go out of bounds, and if it does it's a bug in their own library. Not the input. Rust APIs are not designed the exception-way where unexpected input is supposed to be caught like exceptions. For example, I may allocate a buffer of size n, and index it willy nilly at various points I know to be less than n (perhaps, for example, values from another array which was constructed with values not exceeding n). If this doesn't work, it's a bug in your program and there no two ways about it. The assumptions you made about your own program when writing it were wrong. This can happen if you make a mistake when programming, or mess up a refactoring, or rely on a library that changes behavior (which itself shouldn't happen but the world isn't perfect). Almost all of the indexing panics I've seen in Rust have been bugs in the code that was indexing; where continuing the program somehow would probably make things worse since the state is inconsistent (according to the assumptions the programmer made about their own code, not the input). People tend to use `.get()` when it's possible that the input may trigger an out of bounds error. Its not a performance issue; the bounds check happens either way, please stop making it one. Its an ergonomics issue. Rust tries to offer both imperative and functional styles, and also tries to be palatable to people from C++. This leads to some C++-like defaults like the indexing syntax. If people had to unwrap/try on every index in rust half the community would probably revolt. (note that indexing isn't that common; rust uses iterators and other safer, bounds-check-contained abstractions, but it was determined that when you want to use direct indexing in Rust you usually are designing your code such that the out of bounds is a bug)