This I agree with entirely. I would expect many users of unions to provide safe functions that use the unsafe wrappers to get at the underlying data; I would not expect the majority of users to use the unsafe operations directly at every call site.
In many cases, the union itself cannot implement any such tag function, because the tag exists outside the union. Quite commonly, for instance, you have a struct containing a tag, some common fields, and a union. Only the “tag bits” case or similar could identify the branch of the union based only on the union itself.
Furthermore, a single “tag” may not fully identify a union; accesses may legitimately occur to multiple fields of the union. For instance, you might determine some flags by checking a numeric version of a field, and then follow a pointer after masking its low bits.
You could certainly have a safe function that used the unsafe direct access interfaces to extract data from the union, or from a containing structure, and then call that function and match on the result. For that matter, you could translate the entire union into a Rust-style safely tagged enum. However, it doesn’t seem likely to me that functions doing so would have anything more in common than “safe, implementation contains unsafe blocks, accepts a type that at some level contains a union, returns something not containing a union”. That seems far too general to build a standard interface on.
More importantly, I don’t want to make the perfect the enemy of the good.
I would propose standardizing unions themselves, seeing if common practices arise in the use of unions for tag handling, and subsequently defining a standard interface for that if those practices have anything significant in common.
I could also imagine a potential compiler optimization for “function that returns an enum, and the caller frequently pattern-matches the result”: inline the function enough to dispatch directly from the code that determines the enum (and has the relevant temporaries in registers) to the branches of the match. Such an optimization would help in many cases, including for functions to return safely matchable enums given structures that contain unions.
I have no objection to rephrasing this comment in the RFC, and specifically mentioning the use case you’ve described as another application.