Skip to content

"_" patterns and validity invariants #261

Description

@RalfJung

The following code is not even unsafe, so it certainly cannot be UB:

fn foo(ptr: *const bool) {
    let _ = *ptr;
}

foo(&3u8 as *const u8 as *const bool);

This indicates that the pointer does not really get dereferenced, so the pointed-to data is never interpreted at type bool and thus must not be valid. I am not sure I like this; *ptr (as a value expression!) to me seems like it should conceptually perform the load even if the result is later discarded.

Something similar happens here:

fn bar(ptr: *const (i8, bool)) { unsafe {
    let (x, _) = *ptr;
} }

This compiles effectively to let x = (*ptr).0, so again whatever data is in the second field does not matter. (Note that *ptr here occurs only as a place expression, not as a value expression, so it makes sense that in (*ptr).0 we do not require the second field to be valid.)

I think this behavior of "_" can be explained by saying that it suppresses the place-to-value coercion, and it is smart enough to even do this in cases like (x, _) where the coercion is partially suppressed. But I am not sure I like this semantics, it seems rather counter-intuitive to me. It also makes patterns much harder to explain. And it leads to strange special cases such as rust-lang/rust#79735 (I cannot tell if this is some compiler author also being confused by "_", or if the intention is that ! is special in that even creating the place is already UB, or something else).

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    A-validityTopic: Related to validity invariantsS-pending-documentationStatus: The issue is "resolved," but this resolution needs documentation

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions