Hacker News new | ask | show | jobs
by pcwalton 4405 days ago
> runtime bounds checking

In practice this is quite rare because of iterators, which do not need to do bounds checking. In the rare case in which you need to use indexes, you can always opt out of the safety without the use of a compile-time switch, exactly like the choice between C++'s "operator[]" and ".at()". The only difference is that the default is safe, and the unsafe version requires you to jump through the "unsafe{}" hoop, unlike C++.

Also, with MPX on Skylake even the bounds checking may well become zero-cost.

> symbol mangling

How does symbol mangling make your program go slower?

> exception handling frames

Also enabled by default in C++, and you can turn it off just as in C++. LLVM will also optimize it out if you don't use it and use LTO. On most architectures exception handling is zero-cost via table-driven unwinding (although it can inhibit optimizations).

> split-stacks (this may have changed?))

They're gone.

> this was and still is my complaint about it, the one way to fix it is death by a thousand knobs that modify functionality but by then it's not even the same language.

Nothing needs to be fixed, as none of the things you mention are an issue.

> Also the recent change adding -ffuntion-sections -fdata-sections (a hack imo) shows that the language or the implementation has an issue.

Why? Rust's compilation model is exactly the same as C++ "unity builds" (which are becoming the norm in large projects).

2 comments

> symbol mangling

Preference in all honesty, what besides the obvious requires mangling?

> split-stacks

What took place of split stacks? guard pages?

> ffunction-sections fdata-sections

an example is to use weak aliasing of dummy functions - but this is sort of elf dependent (I have no idea how or if weak aliasing works in pe). I think this is an area that needs to be improved.

If I'm wrong, let me know.

> Preference in all honesty, what besides the obvious requires mangling?

We have a module system. So we have to do name mangling to allow you to use multiple functions with the same name in different modules. This allows you to program without fear of annoying name collisions.

    mod foo {
        fn f() {}
    }
    mod bar {
        fn f() {}
    }
> What took place of split stacks? guard pages?

Stack checks that abort if you run out of stack (like MSVC's __chkstk). It would be nice to just replace it with guard pages where available, and we can probably do that in future versions.

> an example is to use weak aliasing of dummy functions - but this is sort of elf dependent (I have no idea how or if weak aliasing works in pe). I think this is an area that needs to be improved.

How does this allow the linker to throw away unused functions? The reason we use function and data sections is to allow the static linker to remove dead code (which is a lot for many programs).

Modules don't really need sym mangling though a simple mod_fn or mod_fn_type for parametric polymorphism but I'm probably missing something. Weak aliasing to a dummy creates a stub if the other strong sym function is not used thus not pulling it in. I think this is a language level issue and shouldn't be punted to the linker to figure out.

  > what besides the obvious requires mangling?
Rust's symbol mangling allows multiple versions of the same library to be installed on the same system and peacefully coexist. A single Rust program can even link against two different versions of the same library (which comes in handy when two of your dependencies rely on the same library, but are updated at different rates).

You can explicitly disable mangling via an attribute:

  #[no_mangle]
  fn this_symbol_wont_be_mangled() { ... }

  > What took place of split stacks?
https://mail.mozilla.org/pipermail/rust-dev/2013-November/00...

"Instead of segmented stacks we're going to rely on the OS and MMU to help us map pages lazily."

So a version of gnu symbol versioning, does it have the same issue with gnu symbol versioning? If multiple versions of functions are supported it defaults to the lowest version if none are specified, thus possibly introducing broken behaviour.
If rust had compile time analysis of stack usage wouldn't that remove the need for bounds checking, iterator abstraction as well as guard pages (or whatever is in use)?
Statically verifying stack sizes is a hard problem, and I've never heard of a programming language that does it (Ada might?).

In any case, it wouldn't obviate the need for bounds checking. It's possible to index into an array given information known only at runtime, which means that the check for whether that index is valid needs to happen at runtime.