Live data from Hacker News

Several core problems with Rust

bykozy.me

301–310 of 341 posts

Re: Several core problems with Rust

#301
post #248

Earlier quoted context omitted.

Something else I usually don't see: A system hitting a fail-safe is a lot easier to detect and handle from the outside than one that just enters an unknown invalid state. Like, if the rule were "Always-Keep-Running" then hospital equipment power supplies wouldn't have circuit breakers that cut the power when something is wrong. But cutting power seems lot easier to detect for the backup power supply so it can fully t…

Engineer: “It crashed on an assert…” Pointy haired boss: “… well, what are you waiting for!? remove all the asserts so it doesn’t crash any more!”

it's funny because I have seen the opposite. Engineer: "it crashed because it dereferenced a null pointer" boss: "add null pointer checks everywhere!"

... and because it used "if" instead of "assert", it made the null pointer arg a valid argument, making it a tolerable state of the running software, which displaced the locus of crashes far from the source of the issue. Moral of the story, use "assert" to make it crash as early as possible and debug THAT. You want to restrict the representable states in the software, not expand them by adding null checks everywhere.

Re: Several core problems with Rust

#302

Earlier quoted context omitted.

The unsafe code is not fulfilling the contract of "unsafe", which requires the coder to uphold the memory safety rules as seen from outside. make_slice is putting a very wrong lifetime on the slice it returns.

My whole comment here is that safe code has to care about how it uses data from unsafe code. That's pretty evident from my example and from reading from_raw_parts. How would you fix this by only editing the code inside the unsafe block? Because you said the problem is the lifetime. That's outside of the unsafe block. > The unsafe code is not fulfilling the contract of "unsafe", which requires the coder to uphold the…

> How would you fix this by only editing the code inside the unsafe block?

In this case, the solution is to mark make_slice as unsafe. This should make sense if you think about it for a second, because it's a thin wrapper around an unsafe function. If it were possible to make a function which did what std::slice::from_raw_parts does safe, it wouldn't be marked as unsafe.

> It's the exact opposite. From the Rust docs.

The docs you quote say the exact opposite of what you claim. Where do you do call the unsafe function in an unsafe block? In make_slice, not main.

> So yes, as long as you change your function so much you can basically remove unsafe, you can fix it from the function.

The actual use case for std::slice::from_raw_parts is for when you control the pointer and length and thus can guarantee that they're valid (specifically, by encapsulating them and making sure no safe functions can get them into an invalid state). For example, std::Vec::as_slice uses it [1] to get a slice from the pointer to it's managed buffer and it's stored length.

> FFI

There are two possible ways FFI could cause memory safety violations despite being called from safe code:

- The safe wrapper makes incorrect assumptions about the contract of the functions it's calling (e.g. maybe it assumes that a c function returns a pointer which it's the caller's responsibility to free, but is actually freed by the c code). In this case, the bug is in the unsafe rust. - The foreign code violates it's contract (e.g. same as above, but the documentation of the c code claims otherwise). In that case, the bug is in the foreign code.

Either way, the memory safety bug is not in safe rust.

[1] https://github.com/rust-lang/rust/blob/7934bbdf84a6b9a30297c...

Re: Several core problems with Rust

#303
post #290

Earlier quoted context omitted.

I do not understand how you justify your claims. Should I link any number of instances where Rust team members admit to compile times being a major issue, one which prompts significant effort to improve? Perhaps you are right about 10x speedups, but then that clearly isn't enough, reading the room. I also do not understand how you see hostility in my comment. For one thing, I did not downvote you. Rather, your origin…

Don’t know what to tell you. Just trying to keep things real in response to a highly ungrounded post. The issues with compilation times are as severe an issue because of the reason I mentioned — folks don’t like to think about how they factor their build. So some members of the core team are sympathetic to that — and for good reason. But the virtues of shifting context to the build and refactoring it is rarely discus…

I can't speak for everyone, or even the majority, but I know that oftentimes large projects focus on build times, undergoing refactorings as you describe, and their compile times are still high. To make up some numbers, maybe the fraction of projects that have unacceptable compile times could be reduced from 80% to 40% (at what effort?), but that 40% remainder probably includes many large, popular crates.

Re: Several core problems with Rust

#304
post #262

Earlier quoted context omitted.

> So many times I've tried to do something in Rust the old fashioned way, the way I have always done things, and been stopped by the compiler. I then investigate why the compiler/language is being so anal about this trivial thing I want to do.. and yup, there's a concurrency bug I never would have thought of! I guess all that old code I wrote has bugs that I didn't know about at the time. This is also my experience.…

That’s a very good quote. There’s a handful of pain points that the Rust model does impart which are not fundamental. For example, unsafe code is required to get a mutable borrow to two different fields of a struct at the same time. But really that’s the only example I can think of offhandedly, and I expect there are not many in total. Nearly all of the pain is merely the trouble of thinking through these issue upfro…

The only other one I can think of is kind of poor ergonomics around "self-borrows"; it's a lot less common than I've felt the need to mutably borrow two fields from the same struct independently, but there have very occasionally been times where I've realized the simplest way to structure something would be to have one field in a struct borrow another. This is somewhat hard to express given the need to initialize all of the values of a struct at once, and even if you could, there are some complications in how you could use such a struct (e.g. not being able to mutate field `a` safely if it's borrowed by field `b`). Overall though, the things that Rust prevents me from handling safely because of its own limitations rather than them being fundamentally unsafe are quite rare, and even with those, they tend to be things that I would be quite likely to mess up in practice if I tried to do them in a language without the same safety rails.

Re: Several core problems with Rust

#305

Earlier quoted context omitted.

The unsafe code is not fulfilling the contract of "unsafe", which requires the coder to uphold the memory safety rules as seen from outside. make_slice is putting a very wrong lifetime on the slice it returns.

My whole comment here is that safe code has to care about how it uses data from unsafe code. That's pretty evident from my example and from reading from_raw_parts. How would you fix this by only editing the code inside the unsafe block? Because you said the problem is the lifetime. That's outside of the unsafe block. > The unsafe code is not fulfilling the contract of "unsafe", which requires the coder to uphold the…

> The caller here is what is violating the contract.

"The caller" of the unsafe function is the unsafe block in make_slice. And yes it's violating the contract.

> How would you fix this by only editing the code inside the unsafe block? Because you said the problem is the lifetime. That's outside of the unsafe block.

If it's locked into returning a static lifetime, then the only fix is to return a slice into a static allocation.

Is this the functionality you wanted? Probably not. But an unsafe block having an awkward API isn't an excuse to violate safety. Sometimes the only answer is to say no. Calling from_raw_parts this way is a clear bug.

> How could it? It's just making a slice, it doesn't know what from.

It could know more if you added more to the unsafe block outside the call to from_raw_parts.

> It can't guarantee a slice it makes is ANY kind of lifetime. If it could, it wouldn't require unsafe.

> as long as you change your function so much you can basically remove unsafe, you can fix it from the function.

from_raw_parts exists for situations where the coder can guarantee that the lifetime is valid (no matter what safe code does), but the compiler can't guarantee it (because it's not smart enough).

It's not there for situations where you make the safe code promise to behave.

It does have a lot of uses, in places that do need unsafe. You just happened to make an example that doesn't need it.

Re: Several core problems with Rust

#306
post #217
post #169

Earlier quoted context omitted.

What UB? This has nothing to do with UB; it'd be well-defined in any language. It's equivalent to this python snippet: config = load_config() if !config.valid(): sys.exit(1) # config is corrupt. restart pod Did Python do something wrong by letting users call `sys.exit`? No. This is a deliberate crash. Under other circumstances, crashing might have been a valid strategy, but here it turned out to be a bad choice, sinc…

Sys exit does not crash. It raises a SystemExit exception, which can be caught on any layer above it. Given that python uses exceptions for trivial things like loop termination this can be considered normal flow control.

Yeah, and in Rust you can catch the panic from `unwrap()` with panic::catch_unwind. You just don't, for the same reason you don't catch SystemExits. If a SystemExit is being thrown, it's because you want to crash; if you don't wan to crash, don't throw a SystemExit.

Re: Several core problems with Rust

#307
post #5

Totally wrong. > Its compilation is slow. I mean SLOW. Slower than C++. No way. Maybe Rust 1.0, but it's steadily improved and it's definitely faster than C++ now. > It’s complex. Just as complex as C++. True, but the problem with C++'s complexity is that you have to memorise all of it or you'll accidentally invoke UB. It's so complex that is basically impossible. Rust is complex but most of the time the compiler wil…

>I would love to hear what he thinks a good programming language is, because I can easily pick more holes in any other language than he has.

I have a working theory that the classic programming is basically dying out: https://bykozy.me/blog/llm-s-are-not-smart-rather-programmin... You just cannot write fast and reliable program neither with C++ nor with Rust, because the fundamental model is broken and nobody's really bothered fixing it.

Re: Several core problems with Rust

#308

Earlier quoted context omitted.

My whole comment here is that safe code has to care about how it uses data from unsafe code. That's pretty evident from my example and from reading from_raw_parts. How would you fix this by only editing the code inside the unsafe block? Because you said the problem is the lifetime. That's outside of the unsafe block. > The unsafe code is not fulfilling the contract of "unsafe", which requires the coder to uphold the…

> The caller here is what is violating the contract. "The caller" of the unsafe function is the unsafe block in make_slice. And yes it's violating the contract. > How would you fix this by only editing the code inside the unsafe block? Because you said the problem is the lifetime. That's outside of the unsafe block. If it's locked into returning a static lifetime, then the only fix is to return a slice into a static…

It's not a bug until main uses it incorrectly.

The lifetime is outside of the unsafe block. I can change it from static and we still have the same bug.

Re: Several core problems with Rust

#309

Earlier quoted context omitted.

My whole comment here is that safe code has to care about how it uses data from unsafe code. That's pretty evident from my example and from reading from_raw_parts. How would you fix this by only editing the code inside the unsafe block? Because you said the problem is the lifetime. That's outside of the unsafe block. > The unsafe code is not fulfilling the contract of "unsafe", which requires the coder to uphold the…

> How would you fix this by only editing the code inside the unsafe block? In this case, the solution is to mark make_slice as unsafe. This should make sense if you think about it for a second, because it's a thin wrapper around an unsafe function. If it were possible to make a function which did what std::slice::from_raw_parts does safe, it wouldn't be marked as unsafe. > It's the exact opposite. From the Rust docs.…

> The actual use case for std::slice::from_raw_parts is for when you control the pointer and length and thus can guarantee that they're valid (specifically, by encapsulating them and making sure no safe functions can get them into an invalid state)

Right...so you fix it from the safe code, because the safe code is in charge of using from_raw_parts correctly.

> Either way, the memory safety bug is not in safe rust

This might just be a difference of semantics between us, but I really don't see how you can arrive at that conclusion. Just remove the function entirely and let's use from_raw_parts directly. The bug is literally not in unsafe, it's when we drop the vec after making a slice from it. To fix this, we would not change anything in unsafe.

  let vec: Vec = vec![1, 2, 3, 4, 5];
  let ptr = vec.as_ptr();
  let len = vec.len();
  
  let slice_ref = unsafe {slice::from_raw_parts(ptr, len)};
  
  drop(vec);
  
  println!("{:?}", slice_ref);

Re: Several core problems with Rust

#310

Earlier quoted context omitted.

> The caller here is what is violating the contract. "The caller" of the unsafe function is the unsafe block in make_slice. And yes it's violating the contract. > How would you fix this by only editing the code inside the unsafe block? Because you said the problem is the lifetime. That's outside of the unsafe block. If it's locked into returning a static lifetime, then the only fix is to return a slice into a static…

It's not a bug until main uses it incorrectly. The lifetime is outside of the unsafe block. I can change it from static and we still have the same bug.

> It's not a bug until main uses it incorrectly.

It's always a bug. The lifetime is wrong.

The mere ability to "use it incorrectly" and break memory safety is evidence of a bug. Safe rust in a program without unsafe can't use anything incorrectly in that way. Safe rust in a program with appropriately careful unsafe can't use anything incorrectly in that way.

> The lifetime is outside of the unsafe block.

The unsafe block uses the types from the surrounding function, so you can't change those types without double checking the unsafe block is still valid.

> I can change it from static and we still have the same bug.

Change it to something correct and have the same bug?

Because your continued examples look like no. If you make the lifetime arbitrary then it's still messed up, and if you get the lifetime off the vec then the bug is fixed.

Post reply on HN