Remix.run Logo
GardenLetter27 15 hours ago

Rust gives you no guarantees that a function won't allocate or panic though.

VorpalWay 14 hours ago | parent | next [-]

Yes that is annoying, but I don't know of any mainstream systems language that does. C and C++ can also have allocations anywhere, and C++ have exceptions. And those are really the only competitors to Rust for what I do (hard realtime embedded).

Zig might be an option in the future, and it does give more control over allocations. I don't know what the exception story is there, and it isn't memory safe and doesn't have RAII so I'm not that interested myself at this point.

I guess Ada could be an option too, but I don't know nearly enough about it to say much.

jibal 14 hours ago | parent | next [-]

Zig doesn't have exceptions, it has error unions, so basically functions return either a value or an error code and the caller is forced by the language to note which was returned. And instead of RAII it has defer ... which of course can easily be forgotten or mis-scoped, so it's not safe.

alfiedotwtf 2 hours ago | parent | prev | next [-]

Tbh I’ve found that whenever I’ve hit MAX RAM, failed allocations are not the biggest problem you should be focusing at that time.

Sure, it would be nice to get an error, but usually the biggest threat to your system as a whole is the unapologetic OOM Killer

MindSpunk 2 hours ago | parent [-]

While this is 100% true for the system allocator, hitting OOM there you're likely hosed, it isn't true if you're using arenas. I work on games and being able to respond to OOM is important as in many places I'm allocating from arenas that it is very possible to exhaust under normal conditions.

gethly 13 hours ago | parent | prev | next [-]

For allocation, Zig and Odin. Zig is explicit and Odin is implicit.

prxm 11 hours ago | parent | next [-]

> Zig is explicit

i never got this point. whats stopping me from writing a function like this in zig?

  fn very_bad_func() !i32 {
      var GPA = std.heap.GeneralPurposeAllocator(.{}){};
      var gpa = GPA.allocator();
      var s = try gpa.alloc(i32, 1000);
      s[0] = 7;
      return s[0];
  }
the only thing explicit about zig approach is having ready-to-use allocator definitons in the std library. if you excluded std library and write your own allocators, you could have an even better api in rust compared to zig thanks to actual shared behaviour features (traits). explicit allocation is a library feature, not a language feature.
gethly 10 hours ago | parent [-]

the explicit part is that zig forces you to import allocator of your choosing whereas odin has allocator passed as part of hidden context and you can change/access it only if you want to. hence explicit behavior vs implicit behavior.

i use neither of those languages, so don't ask me for technical details :D

thegeekpirate 5 hours ago | parent | prev [-]

You can require allocations in Odin to be explicit using `#+vet explicit-allocators`

FpUser 8 hours ago | parent | prev [-]

>"Yes that is annoying, but I don't know of any mainstream systems language that does. C and C++ can also have allocations anywhere, and C++ have exceptions."

C++ has a way to tell to compiler that the function would raise no exceptions. Obviously it is not a guarantee that at runtime exception will not happen. In that case the program would just terminate. So it is up to a programmer to turn on some brain activity to decide should they mark function as one or not.

MaulingMonkey 15 hours ago | parent | prev [-]

This is something I do wish Rust could better support. A `#![no_std]` library crate can at least discourage allocation (although it can always `extern crate alloc;` in lib.rs or invoke malloc via FFI...)

maxbond 15 hours ago | parent [-]

Is the juice worth the squeeze to introduce two new function colors? What would you do if you needed to call `unreachable!()`?

It's a shame that you can't quite do this with a lint, because they can't recurse to check the definitions of functions you call. That would seem to me to be ideal, maintain it as an application-level discipline so as not to complicate the base language, but automate it.

MaulingMonkey 14 hours ago | parent [-]

> Is the juice worth the squeeze to introduce two new function colors?

Typically no... which is another way of saying occasionally yes.

> What would you do if you needed to call `unreachable!()`?

Probably one of e.g.:

    unsafe { core::hint::unreachable_unchecked() }
    loop {}
Which are of course the wrong habits to form! (More seriously: in the contexts where such no-panic colors become useful, it's because you need to not call `unreachable!()`.)

> It's a shame that you can't quite do this with a lint, because they can't recurse to check the definitions of functions you call. That would seem to me to be ideal, maintain it as an application-level discipline so as not to complicate the base language, but automate it.

Indeed. You can mark a crate e.g. #![deny(clippy::panic)] and isolate that way, but it's not quite the rock solid guarantees Rust typically spoils us with.

VorpalWay 8 hours ago | parent [-]

> Typically no... which is another way of saying occasionally yes.

You might be able to avoid generating panic handling landing pads if you know that a function does not call panic (transitively). Inlining and LTO often help, but there is no guarantee that it will be possible to elide, it depends on the whims of the optimiser.

Knowing that panicking doesn't happen can also enable other optimisations that wouldn't have been correct if a panic were to happen.

All of that is usually very minor, but in a hot loop it could matter, and it will help with code size and density.

(Note that this is assuming SysV ABI as used by everyone except Windows, I have no clue how SEH exceptions on Windows work.)

> Indeed. You can mark a crate e.g. #![deny(clippy::panic)] and isolate that way, but it's not quite the rock solid guarantees Rust typically spoils us with.

Also, there are many things in Rust which can panic apart from actual calls to panic or unwrap: indexing out of bounds, integer overflow (in debug), various std functions if misused, ...