Based on a golang-nuts thread.

Consider this program:

var (
    x struct{}
    y *int = (*int)(unsafe.Pointer(&x))
)
*y = 42

The spec says about unsafe.Pointer:

A Pointer is a pointer type but a Pointer value may not be dereferenced. Any pointer or value of core type uintptr can be converted to a type of core type Pointer and vice versa. The effect of converting between Pointer and uintptr is implementation-defined.

Notably, while this does specify that conversion between unsafe.Pointer and uintptr is implementation-defined, it doesn't contain the same caveat for conversion between unsafe.Pointer and other pointers (like *int in the example above). So the spec does not give any way to reason about the behavior of the above program - not even that it is implementation defined.

The unsafe.Pointer rules do of course rule that program out, so the implementation-defined rules do allow us to reason about the program. But, technically speaking, we are not giving it purview to do that.

I would propose to change "The effect of converting between Pointer and uintptr is implementation-defined" to "The effect of such conversions is implementation-defined".

Comment From: gabyhelp

Similar Issues

(Emoji vote if this was helpful or unhelpful; more detailed feedback welcome in this discussion.)

Comment From: mauri870

cc @griesemer per https://dev.golang.org/owners

Comment From: ruyi789

You shouldn't use this API if you want to be safe, because that's how it's used and it doesn't report errors. That's the very practical value of it.

You might consider using it this way or staying away from it, but what's wrong with it?

```

func Generic_ToE any, T any (r T) { return (T)(unsafe.Pointer(val)) } func Generic_To2E any, T any (r T) { return (T)(unsafe.Pointer(val)) } func Generic_To3E any, T any (r T) { return (T)(unsafe.Pointer(&val)) }

Comment From: griesemer

@Merovius We probably were (implicitly) assuming that since an unsafe.Pointer is a pointer type, any conversion between pointer types only changes the types but doesn't really "do" anything at runtime - which is of course what happens but we (probably) don't want to write that down, yet we need to write something about it. I think your suggestion seems fine, thanks.

Comment From: gopherbot

Change https://go.dev/cl/593755 mentions this issue: spec: clarify prose about unsafe pointer conversions