1. 15

  2. 2

    This seems a very strange definition of “undefined behavior”. At first it seems to be referring to the same concept as C, but there’s nothing undefined about accessing a uint8_t variable through a uint8_t pointer.

    1. 5

      What do you mean?

      C pointers, as far as I understand them (I not an expert C standard rules lawyer), can be chopped up into about three categories

      • restrict pointers, which definitely allow you to invoke UB by accessing a uint8_t pointer through a uint8_t pointer, if you deference two different aliasing pointers, one of which is restrict.

      • “normal” pointers, which are still subject to the strict aliasing rules in standard C. This definitely means you can access a uint8_t variable through a uint8_t pointer, but you can’t access the first byte of an int through one unless you do an appropriate dance through union. Otherwise, it’s undefined behavior.

      • “generic” pointers, namely void* and char*, have no aliasing rules. About the only way to invoke undefined behavior is to alias them with a restrict pointer, or dereference them when they dangle.

      You’ll notice that this article describes two different types of pointer in Rust:

      • References, which are a bit like restrict pointers in C.

      • Raw pointers, which are a bit like “generic” pointers in C, but can exist in any type, not just c_char.

      “a bit like restrict” is a complete oversimplification, though. The real deal of how any of these things work is the spec. The C spec is at least as bad as this article is for Rust.

      1. 2

        The first code example, in C:

        uint8_t x;
        uint8_t *y = &x;
        x = 7;
        *y = 5;

        Or whatever. There’s nothing undefined about that.

        1. 5

          That’s not a completely accurate translation. An accurate translation would make the pointer a restrict pointer, and it would be undefined behavior in C too.

          An easier way to look at it is this: In Rust, some things that would be UB in C (e.g. strict aliasing violations) are not UB in Rust, however other things that not UB in C (writing through multiple aliases that are not marked as unsafecell) are UB in Rust.

          The final nature of undefined behavior in Rust will likely not map cleanly to C concepts. We can refine the concept of restrict pointers a lot, for one.

      2. 4

        Yes, Rust has its own cases of undefined behaviour. Especially that &mut references are not allowed to alias and are always unique, so getting hold of a second on the same value while one is already active is undefined behaviour. unsafe allows you to create that case.

        The nomicon has an example why breaking this rule does matter, as the compiler will rely on the uniqueness of &mut references. https://doc.rust-lang.org/nomicon/aliasing.html

        The example is trivial, but &mut needs to be globally unique (its on of the core guarantees of Rust), so some care is necessary when handing them out from Rusts unsafe blocks.

        Ralfj has more writing on this (that’s his research topic).

        1. 2

          Thanks. I missed some context.

          cc @notriddle @Manishearth

          1. 1

            You’re welcome.