News for hackers. Stuff that matters.
Re:Linux Rust Support by gpm on Tuesday July 06, 2021 @08:48AM (#27747767)
Apart from all the safety benefits mentioned, a modern language with modern conveniences.

Type inference

Language support for tagged unions (which they call enums for some reason), which among other things results in error handling which is "out of channel" instead of magic return values.

Speaking out error handling - syntax for easily forwarding errors to the calling function.

Generics, and therefore

- Libraries of collections with a rich collection of methods implemented for you.

- Library support for lazy iteration

- ...

Method (postfix call) syntax allowing for readable chaining

Hygenic macros

Compiler supported test harnesses

Compiler supported linting (that is really good)

Compiler supported automatic formatting (that is really good)

Compiler supported vtables

(pointer, length) strings

Proper namespaces

And so on and so forth

Re:Linux Rust Support by cesarb on Tuesday July 06, 2021 @12:02PM (#27750297)
> Language support for tagged unions (which they call enums for some reason)

Probably because the simplest case of Rust enums (without any data other than the tag itself) can act similar to a C enum, to the point that you can "#[repr(C)]" it and use as FFI for the equivalent C enum. One understated advantage of Rust for C programmers (which is on topic given that the Linux kernel is written mostly in C) is that its syntax and keywords have many similarities with C, starting with the use of braces for blocks and semicolons to end statements.

Re:Linux Rust Support by gpm on Tuesday July 06, 2021 @12:19PM (#27750574)
Ya, that was a throwaway comment that I probably should have left out.

> and use as FFI for the equivalent C enum.

Only if you're willing to accept undefined behavior if the foreign code passes you an unknown variant. For actual ffi work I've ended up using a macro that makes a "#[repr(C)] struct EnumName(u32)" with a bunch of constants for the values.

Re:Linux Rust Support by ElderKorihor on Tuesday July 06, 2021 @08:36PM (#27756086)
> Only if you're willing to accept undefined behavior if the foreign code passes you an unknown variant.

Isn't that what `#[non_exhaustive]` is for?

Re:Linux Rust Support by gpm on Tuesday July 06, 2021 @08:43PM (#27756128)
As far as I know that flag doesn't give you permission to create unknown variants or effect backend code generation that will assume there are only the defined variants. I could be wrong, but I don't see anything about this documented in the rfc: https://rust-lang.github.io/rfcs/2008-non-exhaustive.html
Re:Linux Rust Support by kzrdude on Tuesday July 06, 2021 @03:33PM (#27753224)
That wouldn't be ABI-correct for ffi function parameters by value, right? (Since it's a struct, not an enum).
Re:Linux Rust Support by gpm on Tuesday July 06, 2021 @03:49PM (#27753379)
It would be correct, up to the size of the integer. As far as the abi is concerned a C enum is just an integer. As far as the abi is concerned a struct containing a single integer field, is also just an integer.

If there are any values that don't fit in a u32, I would need to use a different int type. C enums automatically use bigger int types if they don't fit in the smaller ones.

If I was on an architecture where int was smaller than 32 bits it would also be incorrect (except by coincidence that 32 bits was the smallest type that could hold all the values). I could "solve" that by using libc::c_int instead, but that only sort of solves the issue because if libc::c_int is 8 bits, and the enum has a value 257, it's just not correct anymore.

I suppose it's possible that some abi treats a struct containing an int differently from an int, I doubt it though. If that's the case, #[repr(transparent)] instead of #[repr(C)] would be slightly more correct.

Re:Linux Rust Support by jlokier on Tuesday July 06, 2021 @07:16PM (#27755546)
> As far as the abi is concerned a C enum is just an integer

In some ABIs this is not true, a C enum is a char if the constants fit. Your code that assumes enums are stored and passed around as 32-bit integers is not entirely portable.

Re:Linux Rust Support by gpm on Tuesday July 06, 2021 @08:33PM (#27756068)
Yes, I agree.

Ultimately, at least at the time, there was no other option that had better compatibility. Now I suppose you could use MaybeUninit<#[repr(C)] enum> or something. Realistically I don't have much confidence in rustc properly matching enum sizes with C implementations that don't follow the typical behaviour here, so I doubt that would be worth it.

I guess the linux kernel is generic enough that it might end up on some such platforms, I guess in that context I'd just bite the bullet and accept undefined behavior if passed an unexpected enum variant, it's not like that should happen in a coherent system like the linux kernel (vs my use case which was wrapping some library that definitely might chose to add enum variants).

Re:Linux Rust Support by tialaramex on Tuesday July 06, 2021 @12:56PM (#27751187)
You can do all sorts of C things in Rust, and they're merely not idiomatic.

For example your Rust function that always returns 42 should probably be:

  const fn fortytwo() -> i32 {
    42
  }
But C programmers might try:

  const fn fortytwo() -> i32 {
    return 42;
  }
And that works fine, the compiler sees that you wanted to return 42 here, and, although the value at the tail of the function is an empty tuple and thus incompatible with your function signature you never reach that tail, so no problem.